Sign in to follow this  
tendifo

windows messages

Recommended Posts

I create a button like so:
HWND button1 = CreateWindow("BUTTON", "button1", WS_CHILD | BS_PUSHBUTTON, 10, 10, 100, 30, form1, NULL, hinstance, NULL);

ShowWindow(button1, true);
form1 is a HWND that the main window is stored in. hinstance is the application instance. So that works. The button appears. But because there's no user defined WNDCLASS struct that I passed to create the button, I have no control over the messages (or so I think anyways). How do I catch the events that the button produces? I'm assuming they come to the main window's message handler.. but not sure how to seperate them from the other ones. Thanks for the help.

Share this post


Link to post
Share on other sites
Buttons send WM_COMMAND messages with the low word of WPARAM set to the id of the button, and the high word set to the notification message. The LPARAM value is the handle of the button control. It also sends some notifications via the WM_NOTIFY message, and a couple other special messages, WM_CTLCOLORBTN and in XP BCN_HOTITEMCHANGE.

Share this post


Link to post
Share on other sites
That works sorta like I hoped.

When I catch WM_COMMAND, it only registers when I release the button. Is it possible to catch when the button is pressed, released, and if the mouse moves over it? Is it possible to find out where on the button the user clicks?

Thanks a bucnh.

Share this post


Link to post
Share on other sites
You have two options, either subclass the button control, which I doubt you are ready to tackle, or use the BS_OWNERDRAW button style and handle the WM_DRAWITEM messages. See this: Using Buttons

Share this post


Link to post
Share on other sites
From what I've read so far, I can do this to create a "subclass" of the button.

SetWindowLongPtr(button1, GWL_WNDPROC, buttonproc);


So now, my buttonproc handles all messages from the button. I went ahead and tried this, but now the button doesn't show up. Am I now responsible for drawing the button? If so, I'm assuming WM_PAINT or more likely WM_DRAWITEM is the event where I draw it. Do I need to handle more events too?

Is there a windows function that I can pass some values to to draw a standard windows button? Or do I need to create a custom drawn button (which wouldn't be such a bad idea because the standard one is pretty crappy).

Thanks.

Edit:

I think I get it now actually. I need to store the original button proceudre, then change it to mine. After I catch the messages I want, I need to call CallWindowProc and use the original call back function. Then the button will be drawn?

Thanks again.

Share this post


Link to post
Share on other sites
If you subclass a function that way YOU are responsible to pass the messages on to the default function.

Use the function CallWindowProc with the old WNDPROC pointer you got as return code from SetWindowLong(Ptr).

Share this post


Link to post
Share on other sites
Here's my windows loop.

while (!done)
{
if (PeekMessage(&msg, form1, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}


After I do a subclass for the random controls I have, will this loop still pop the messages off the message queue for the controls? Or do I need to do a PeekMessage for each of the controls now as well?

Thanks.

Share this post


Link to post
Share on other sites
yes, PeekMessage examines messages from the hwnd and all of it's children:

MSDN: PeekMessage retrieves messages associated with the window identified by the hWnd parameter or any of its children as specified by the IsChild function.

however, if you have other windows or forms around you shouldn't filter the hwnd in your message loop (it shouldn't effect modal dialogs or anything running a modal loop, but if there are other windows around...). i, personally, would never filter the hwnd of my main message loop or any looping message pump (i would, however, if it was a one shot testing thing).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Just thinking out loud:

If you only do a pure window app and don't need to do the extra processing when the window doesn't get any messages, then PeekMessage is a waste of resources, because, look at the processor usage, it will spike close to 100% (or 50% if you have dual-core or hyper threading). In those scenarios, use GetMessage, it will put your app in a sleep state until a message is available, not using processing power. Also, you should test with the WM_CLOSE message, because that won't be passed to you windowProc...

Julian

Share this post


Link to post
Share on other sites
yeah, i'll also second with AP and that if you don't need PeekMessage, you shouldn't use it. and even if you have to, you should always call GetMessage (something like below):


for(;;)
{
if(PeekMessage(&msg, 0, 0, 0, 0, PM_NOREMOVE)) {
if(GetMessage(&msg, 0, 0, 0, 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else break;
}
else {
// idle processing
}
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this