Archived

This topic is now archived and is closed to further replies.

bishop_pass

Subclassed buttons aren't being rendered. Why?

Recommended Posts

bishop_pass    109
I made some buttons with CreateWindow(). They work fine. They show up in my window and I can process their clicks with the WM_COMMAND msg. Ok, I wanted to subclass them to compartmentalize some of their functionality away from the main code. I wrote the subclass function like this.
  
LRESULT CALLBACK expandProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    int id;

    id = GetWindowLong (hWnd, GWL_ID);

    switch (msg) {
    case WM_COMMAND:

        if (HIWORD (wParam) == BN_CLICKED) {
            toggleExpandable (Top[id - 5000]);
            adjustRows (Top[id - 5000], 0);
        }
       
        break;
    }

    return CallWindowProc (parentProc, hWnd, msg, wParam, lParam);
}
  
What it does is specific to what I am designing, but that is beside the point. The problem is they aren''t rendering now. They simply don''t show up in my window. I was under the impression that by calling break; and then returning by calling CallWindowProc(), the rest of their processing would be passed onto their parent window message processing function. So what is different here that would cause them not to be rendered? BTW, parentProc is initiliazed correctly as this works with another sublcassing function I wrote. Here''s the code to initialize parentProc after creating my button.
  
            parentProc = (WNDPROC) SetWindowLong (
                hWndButton[10], 
                GWL_WNDPROC,
                (LONG) expandProc
            );
  
parentProc is a global, so both functions are dealing with the same value.

Share this post


Link to post
Share on other sites
Sandman    2210
Ive never managed to get subclassing to work in any useful way either. For some reason the only messages that ever go through my custom window proc are the ones I am not interested in. The ones I am interested in are never intercepted.

I tried your code, and I had the same problem. The button draws, but the WM_COMMAND message never passes through the expandProc. Everything else does though.

In conclusion, subclassing windows is like voodoo. Except I think voodoo works more reliably.

Share this post


Link to post
Share on other sites
bishop_pass    109
Sandman, I''m where you are now. I had another problem with my parentProc pointer being oeverwritten by something else, but I fixed that. Now I''m at the point where the button renders, but the WM_COMMAND doesn''t go through.

I think it might be because WM_COMMAND is only processed from the context of the parent window receiving messages about it''s child buttons and other items.

Somewhere there must be a message type that the button itself receives if it is being clicked.

Share this post


Link to post
Share on other sites
cgoat    132
quote:
Original post by bishop_pass
Somewhere there must be a message type that the button itself receives if it is being clicked.


I believe the WM_LBUTTONDOWN and WM_LBUTTONUP would be sent to the button itself, though I''m not 100% sure. You''re right that WM_COMMAND is only sent to the parent.

Share this post


Link to post
Share on other sites
bishop_pass    109
That''s just exactly what I have discovered.

There''s a problem with that, of course. I have to make sure that both are sent, and do my stuff on WM_LBUTTONUP. But these can get out of sync if the user moves on or off between down and up.

Share this post


Link to post
Share on other sites
Sandman    2210
quote:
Original post by cgoat
[quote]Original post by bishop_pass
Somewhere there must be a message type that the button itself receives if it is being clicked.


I believe the WM_LBUTTONDOWN and WM_LBUTTONUP would be sent to the button itself, though I''m not 100% sure. You''re right that WM_COMMAND is only sent to the parent.


I had a suspicion that was the problem, but I never got around to testing it.

Share this post


Link to post
Share on other sites
bishop_pass    109
Yeah, but it''s a pain in the ass to keep things in sync.

The user might click down on the button, move the mouse off of the button, and then click up.

The user might click down on the button, move the mouse off of the button, and then move the mouse back on the button and then click up.

The user might click down somewhere else entirely, and then move the mouse on the button and click up.

The user might click down on the button, move the mouse off and click up. He then could click down somewhere else and move the mouse over the button and click up.

Here''s how to solve it:


  
LRESULT CALLBACK expandProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
int id;
static int state = 0;
int x;
int y;
RECT rect;

id = GetWindowLong (hWnd, GWL_ID);

switch (msg) {
case WM_LBUTTONDOWN:
state = 1;

break;

case WM_LBUTTONUP:

if (state == 0)
break;

x = LOWORD(lParam);
y = HIWORD(lParam);

GetClientRect (hWnd, &rect);
if (x > rect.right || y > rect.bottom)
state = 0;
if (x < 0 || y < 0)
state = 0;

if (state == 0)
break;

toggleExpandable (Top[id - 5000]);
adjustRows (Top[1], 0);

state = 0;

return 0;

break;
}

return CallWindowProc (buttonProc, hWnd, msg, wParam, lParam);
}


Now I just have to get my static state variable to be unique for each button in this class.

Share this post


Link to post
Share on other sites