tags:

views:

313

answers:

2

I am trying to catch messages from an application for which I have no source code.
I install a Windows hook like this:

hhk = SetWindowsHookEx(WH_CALLWNDPROCRET, HookProcSetTextRet, hinst, threadID);

(The hhk variable is in shared data.)
I don't understand some of the behavior, though, specifically:

LRESULT CALLBACK HookProcSetTextRet(int code,WPARAM wParam,LPARAM lParam) {  
PCWPRETSTRUCT st = (PCWPRETSTRUCT)lParam;
switch (HIWORD(st->wParam)) {
    case WM_COMMAND: {
        /*
        For lbn_xxx:
        wParam
        The low-order word is the list box identifier. 
        The high-order word is the notification message.

        lParam
        Handle to the list box. 
        */
            switch (HIWORD(st->wParam)) {
                case LBN_DBLCLK: {
                        log << L"\tWM_COMMAND ---  LBN_DBLCLK" << endl;
                    }
                    break;

                case LBN_SELCHANGE: {
                        log <<  L"\t+++ WM_COMMAND -LBN_SELCHANGE" << endl;
                        log << L"\t\tHandle to list box : " << st->lParam << endl;

                        HWND lbHwnd = (HWND) st->lParam;

                        res = SendMessage(lbHwnd, LB_GETCOUNT, 0, 0);
                        curSel = SendMessage(lbHwnd, LB_GETCURSEL, 0, 0);
                        log << L"\t\t\tLB_GETCURSEL returned : " << curSel << endl;
                        if (LB_ERR != curSel) {
                            res = SendMessage(lbHwnd, LB_GETTEXT, curSel,  
                                     (LPARAM)(LPTSTR) szBuf);
                                log << L"\t\tLB_GETTEXT returned : " << res <<                  
                                       L"\t\tszBuf: " << szBuf << endl;
                        }
                    }
                    break;

                default:
                    break;
            }
        }  // WM_COMMAND
    /* snip */
}
return CallNextHookEx(0, code, wParam, lParam); 
}

LBN_SELCHANGE is caught, but the value returned by LB_GETCURSEL and LB_GETTEXT is always the same.
LBN_DBLCLK is never caught.

There is similar inconsistnecy with other WM_ messages, as well. Is the app itself somehow eating these messages?
Thanks for any ideas...

UPDATE:
Following a suggestion made below, I implemented a WH_GETMESSAGE hook. It appears to be getting the doubleclick message from the listbox.
Unfortunately, LB_GETCOUNT returns the correct number, but LB_GETCURSEL always returns 0, and LB_GETTEXT still returns nothing...

    case WM_LBUTTONDBLCLK: {
        const unsigned int BUFFER_SIZE = 1024;
        wchar_t titleBuffer[BUFFER_SIZE];
        UINT curSel = LB_ERR;
        LRESULT res = LB_ERR;

        MSG * pMsg = (MSG *) lParam;
        HWND lbHwnd = pMsg->hwnd;

        log << L"\tGetMsgProc\t\tWM_LBUTTONDBLCLK" << endl;

  // Sanity check
        HWND parent = GetParent(lbHwnd);
        GetWindowText(parent, titleBuffer, BUFFER_SIZE - 1);
        log << L"\t\tParent Title : " << titleBuffer << L"\tParent HWND : " << parent << endl;

  // Sanity check
        GetClassName(lbHwnd, titleBuffer, BUFFER_SIZE - 1);
        log << L"\t\tList box class name: " << titleBuffer << L"\tList box hwnd: " << pMsg->hwnd << endl;

        res = SendMessage(lbHwnd, LB_GETCOUNT, 0, 0);
        if (LB_ERR != res) { log << L"\t\t\tLB_GETCOUNT : " << res << endl; }

        curSel = SendMessage(lbHwnd, LB_GETCURSEL, 0, 0);
        log << L"\t\t\tLB_GETCURSEL returned : " << curSel << endl;
        if (LB_ERR != curSel) {
            res = SendMessage(lbHwnd, LB_GETTEXT, curSel, (LPARAM)(LPTSTR) titleBuffer);
            if (LB_ERR == res ) { log << L"\t\t\tLB_GETTEXT Error -- invalid index" << endl; }
            else {
                log << L"\t\tLB_GETTEXT returned : " << res << L"\t\tszBuf: " << titleBuffer << endl;
            }
        }
        else { log << L"\t\tLB_GETCURSEL returned LB_ERR" << endl; }
    }
A: 

LBN_DBLCLK will not get sent if the list box doesn't have the LBS_NOTIFY state set on it. Dunno why LB_GETCURSEL and LB_GETTEXT aren't working though ...

Goz
A: 

I've always found the documentation on window hooks severely lacking.

From their names, I think that the WH_CALLWNDPROCRET hook would always get called somewhere after a corresponding WH_CALLWNDPROC hook. The documentation of SendWindowsHookEx says about WH_CALLWNDPROC:

Installs a hook procedure that monitors messages before the system sends them to the destination window procedure.

This suggests that it only gets messages that are sent (SendMessage, which calls the window procedure directly), not posted (PostMessage, which puts the message in the message queue).

If this is indeed the issue at hand, then you could try installing a WH_GETMESSAGE hook along with your existing hook. This hook gets called when messages are removed from the message queue (by the window procedure, usually). Try and see if that hook catches the lost messages.

Thomas
Thanks, I'll try that...
Number8
See update in OP.
Number8
Sorry, I'm at a loss too. Maybe try disabling your `WH_CALLWNDPROCRET` hook, see if that makes a difference?
Thomas