Subclassed buttons aren't being rendered. Why?

Started by
6 comments, last by bishop_pass 21 years, 11 months ago
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.
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
Advertisement
Problem solved. Now I have a new set of problems...
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
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.
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.
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
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.
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.

_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.
quote:Original post by cgoat
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.

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.
_______________________________
"To understand the horse you'll find that you're going to be working on yourself. The horse will give you the answers and he will question you to see if you are sure or not."
- Ray Hunt, in Think Harmony With Horses
ALU - SHRDLU - WORDNET - CYC - SWALE - AM - CD - J.M. - K.S. | CAA - BCHA - AQHA - APHA - R.H. - T.D. | 395 - SPS - GORDIE - SCMA - R.M. - G.R. - V.C. - C.F.

This topic is closed to new replies.

Advertisement