|
|
|
I want to make the flat control (2D look) instead of (3D), I can draw a rectangle or changing the color using custom draw
(DRAWITEMSTRUCT) but the changes behind the tab as the picture below, the black is my rectangle
http://social.msdn.microsoft.com/Forums/getfile/305523[Tab control 1 ]
I have changed my rectangle to OPAQUE but still the same thing
By the way the whole tab has that (3D), I have no idea why??
http://social.msdn.microsoft.com/Forums/getfile/305526[Tab control 2]
Can I remove that 3D look from the tab control?
And if the DRAWCUSTOM should deal with that Why my rectangle behind the tab it supposed to be on it for covering that tab?
Edit:
using
TCS_faltbutton and
TCS_BUTTONS does not solve this
|
|
|
|
|
I'm struggling at how to customize the console window background color. I have found that SetConsoleScreenBufferInfoEx may help me, but I don't know how to do it. I want to customize the background color like the properties window do. Anybody can help me?enter image description here
And now what I have is customize the foreground color with RGB, here is my code:
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFOEX csbiInfo;
csbiInfo.cbSize = sizeof(csbiInfo);
GetConsoleScreenBufferInfoEx(hStdout, &csbiInfo);
csbiInfo.ColorTable[6] = RGB(200, 255, 0);
SetConsoleScreenBufferInfoEx(hStdout, &csbiInfo);
SetConsoleTextAttribute(hStdout, 6);
The more I do, the more I can do!
|
|
|
|
|
After a bit of experimentation I found that setting the background colour and then sending a clear screen (cls command) will set the entire background to the selected colour. The only bit I cannot find, is how to send a clear screen command from code. In the old ANSI.SYS days it was done by <ESC>[2J , but that does not seem to work in command.com windows. However by adding a system("cls") call I can get the entire screen to the new colour. The following code sets the background to white.
SetConsoleTextAttribute(hStdout, BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_GREEN);
system("cls");
Use the best guess
|
|
|
|
|
How to customize the color with RGB ? This is the real question.
|
|
|
|
|
I don't think you can; the function accepts any combination of the single values [ RED | GREEN | BLUE ] which allows up to 8 colours (16 if you add the highlight flag). If you want full colour control then you should be looking to use a proper Windows application which lets you use the complete range of RGB values.
Use the best guess
|
|
|
|
|
I am creating a modeless dialog from an ActiveX which loads in the Internet Explorer 9/Windows 7 using following code:
Where CMyActiveXCtrl class is of COleControl type.
void CMyActiveXCtrl::OnBnClickedTest()
{
m_MainDialog.bClosed = false;
m_MainDialog.ShowWindow( SW_SHOW );
MSG Msg;
BOOL bRet;
while (bRet = GetMessage(&Msg, NULL, 0, 0))
{
if (bRet == -1)
{
MessageBoxA(this->m_hWnd, "Message loop error", "My ActiveX", MB_OK);
break;
}
if (PreTranslateMessage( &Msg ) == 0 )
{
if (!::IsDialogMessage(m_MainDialog.m_hWnd, &Msg))
{
TranslateMessage( &Msg );
DispatchMessage(&Msg);
}
}
if (m_MainDialog.bClosed == true)
{
break;
}
}}
m_MainDialog.bClosed set true on modeless dialog close/destroy. Now when my modeless dialog is opened in ActiveX and the user closes the browser window using IE > File > Exit or clicks on top right "X" button, IE main windows closes (no longer visible) but it leaves an orphan IE process in the task manager.
The same code working fine on Windows XP/ IE 8. Can anyone suggest me what could be the problem with above message loop in OnBnClickedTest() else without that message loop, it works fine.
Manish Agarwal
manish.k.agarwal @ gmail DOT com
modified 5-Jul-13 8:03am.
|
|
|
|
|
Here is my guess:
Message order can be different with different window managers. Even on the same windows installation the window manager and the message order can be different if you change between aero/oldschool/whatever look.
One possible reason can be the following: when you press X the window receives WM_SYSCOMMAND/SC_CLOSE that triggers a WM_CLOSE that triggers WM_DESTROY that finally executes a PostQuitMessage() in a usual windows program. Pressing the Exit menuitem usually skips the first step of the chain and sends WM_CLOSE directly to the window. I think here the problem can be that your loop consumes the WM_QUIT message placed by PostQuitMessage() to the message queue (when your GetMessage call returns FALSE) so when you return from your loop the message loop of IE doesn't have any quit message to process. I'm not exactly sure about this (haven't tried it) because WM_QUIT isn't really a message in the message queue of your thread, its rather a bit that tells GetMessage()/PeekMessage() to return WM_QUIT when there are no more messages left in the queue, maybe this flag remains set but who knows... If the flag doesn't remain set (that can be windows version specific) then the problem can be what I described. When your main loop ends (GetMessage returns false) try to repost the quit message by calling PostQuitMessage((int)Msg.wParam) a the end of your OnBnClickedTest() function to place a WM_QUIT message (flag) in the queue for the main loop of IE. Try it and good luck with this.
Of course this disaster can happen only if the WM_QUIT is consumed and if WM_QUIT comes before the bClosed flag of your dialog becomes true. You can check that by placing a log into your bClosed checking if block and after the end of your loop.
EDIT: Another even better solution if you know the HWND of the main window: after checking the m_MainDialog.bClosed flag of your dialog put in another if block that checks whether this message is a WM_CLOSE message sent to the main window and in that case break out of your loop. An even better version of this: in your loop you should call PeekMessage() before every GetMessage() call just to look ahead in the queue (without removing the message) and if its a suspicious message sent to the main window (WM_SYSCOMMAND/SC_CLOSE or WM_CLOSE) then you break out your loop immediately without processing the message and you let the message loop of IE to process it. What is nice about this solution is that it would work even if the main loop of IE wanted to act on the WM_SYSCOMMAND/SC_CLOSE or WM_CLOSE message of the main window - putting such handlers into the main loop is not a good practice (you should handle that in the windowproc of the specified hwnd) but maybe MS guys committed that hack...
briefly:
for (;;)
{
WaitMessage();
PeekMessage();
if (WM_SYSCOMMAND/SC_CLOSE or WM_CLOSE sent to the main window)
break;
BOOL bRet = !GetMessage();
if (!bRet)
break;
}
EDIT: of course you know the HWND of the main window because you just have to call GetParent() on the HWND of the activex control or its window in a loop (or recursively) until it returns NULL HWND and the HWND before the NULL result is the top level window.
modified 7-Jul-13 21:13pm.
|
|
|
|
|
Thanks a lot.
PeekMessage approach is working with a small correction if (!bRet) to if (bRet) i.e. removed NOT operator.
Manish Agarwal
manish.k.agarwal @ gmail DOT com
|
|
|
|
|
You are welcome! I haven't put in any checks on my PeekMessage() so you couldn't negate it! Both peekmessage and getmessage are needed, with careful parametrization of PeekMessage(). Of course the PeekMessage doc says that it returns nozero if there is a message available so you have to check for (bRet). Can you please post the resulting code? We may be able to spot other errors and it can help other people in the future.
|
|
|
|
|
I have already found a bug in my solution: If there is no message in the queue when PeekMessage() is executed then control is immediately transferred to the GetMessage() call so the next incoming message will be removed for sure by your loop no matter what the message is. To avoid this you should probably call WaitMessage() before PeekMessage().
|
|
|
|
|
My final code looks like as below and it does not require handling of WM_SYSCOMMAND/SC_CLOSE or any other message as my test shows that we always get WM_CLOSE irrespective of how we are closing it.
for (;;)
{
WaitMessage();
PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE);
if (Msg.message == WM_CLOSE)
{
break;
}
BOOL bRet = GetMessage(&Msg, NULL, 0, 0);
if (!bRet)
break;
if (PreTranslateMessage( &Msg ) == 0 )
{
if (m_MainDialog.m_hWnd == (HWND) NULL || !::IsDialogMessage(m_MainDialog.m_hWnd, &Msg))
{
TranslateMessage( &Msg );
DispatchMessage(&Msg);
}
}
if (m_MainDialog.bClosed == true)
{
break;
}
}
Manish Agarwal
manish.k.agarwal @ gmail DOT com
|
|
|
|
|
Thank you for posting, WM_CLOSE should be okay. You don't check the return value of PeekMessage (that should always be zero but its better to make sure...) and you should check Msg.hwnd whether its the main window hwnd or something else (it could be one of your dialog hwnds or any other HWND inside the IE process). I would write "if (PeekMessage()) { check for WM_CLOSE }". You can get the main window hwnd by performing the following operation on one of your activex hwnds that are placed directly/indirectly on your main window:
HWND GetRootWindow(HWND hwnd)
{
for (;;)
{
HWND parent = GetParent(hwnd);
if (!parent)
return hwnd;
hwnd = parent;
}
}
WM_SYSCOMMAND/SC_CLOSE is gui specific (it indicates that someone pressed X on the window), noone should put critical handling on this message as your window can easily get simulated WM_CLOSE messages without gui interaction/WM_SYSCOMMAND/SC_CLOSE.
|
|
|
|
|
Thanks again for your detailed reply. I will take care of this.
Manish Agarwal
manish.k.agarwal @ gmail DOT com
|
|
|
|
|
You are welcome! Ignore my previous post, I posted something here and the deleted it later but you probably received a mail notification! 
|
|
|
|
|
There is one message pump and one message handler per process, why would you want to duplicate the message pump of IE in a dialog box onclick handler?
Its uterly stupid.
|
|
|
|
|
For example because he may want dialogbox features on his dialog using IsDialogMessage() that wouldn't be done by the main loop of IE. Such dialogbox features include for example hotkeys like closing the dialog with ENTER/ESC, traversing the controls with TAB. Of course this own loop is a bit hacky but still can be a good balance between invested time and functionality. Sometimes its not you writing the code - it can be heritage from another guy who worked for the company years ago and your boss wont give you time to put together a better solution especially if the current one works in a more or less satisfactory way. The world is not perfect, and one day you will have to realize this.
|
|
|
|
|
You never heard of windows hooks then?
|
|
|
|
|
You still havent answered. Just because a dialog is interested in some messages and register for them why should it duplicate the message pump?
Thwere is one message pumop, one queue, one handler per process. Period.
|
|
|
|
|
The hook can indeed be a good solution. This still isn't a reason for you to talk to other people here using an arrogant style with degrading words. You can be the best programmer in the world if you are missing basic social skills and the respect towards others, noone wants people like you in his team. Respect is mutual or nonexistent.
|
|
|
|
|
Forget hooking, why shouold there be a duplicate message pump in the process? Dont you think it is stupid?
|
|
|
|
|
It is not stupid, but its an ugly workaround to a problem that has no fine solution. This own message loop workaround has several problems: it runs as long as our modeless dialogs are open and during this time it serves the messages to other windows as well, in this case if IE had its own modeless dialogs then dialog features wouldn't work on those dialogs as those are handled by IE's main message loops (same is true for other possible features that are implemented in the main loop of IE). We could probably find even more problems with this solution. The question is: how much time is available for the asker to finish this job and how much risk he takes if he chooses to implement dialog features for himself in his own dialogs by going with the message loop of IE. Sadly, programming for companies is often about saving time and playing safe and not taking risks for delivering correct solutions (unlike in hobby projects) especially if that would involve modifying legacy code that "still works". There are cases where the own loop is fine: for example the winapi MessageBox() does this (but its a modal dialog) and windows also running its own loop while you are moving a window by grabbing its title bar (and there can be other cases). There are probably many other cases where the own loop can be appropriate but a modeless dialog is definitely not among those.
|
|
|
|
|
You have already suggested using IsDialogMessage() so the dialog can register to receive required messages from the processes message handler. This is the suggested way of doing it so putting your own message pump in the dialog and peeking at messages IS stupid.
Any suggestion that bad code should be implemented OR maintained is also stupid. If it is crap, chuck it out.
Code is either 100% perfect or it is junk. Period. (I have spent 16 years in the WIndows kernel where this law is absoloutely true. ONE bug, and its a BSOD. Its either 100% perfect or unusable junk. )
|
|
|
|
|
Nothing is 100% perfect. Period. This is true even for drivers and we experience this at least monthly here (usb drivers for android, various drivers for 3d graphics). The size of driver code is usually much less than the legacy enterprise software codebase of some corporations so keeping drivers tidy is much easier than doing the same with some other software - especially because at a driver developer company you are probably expected to invest time in perfecting things while some other companies have to prioritize which part of the codebase to develop and you have time only to maintain the rest. It is usually not the programmer who decides about priorities.
|
|
|
|