挂钩时挂钩窗口未正确绘制

时间:2009-06-03 12:46:45

标签: winapi hook overlay

要求是在另一个应用程序窗口的一侧绘制我的信息。 为了照顾z顺序等等,挂钩WH_GETMESSAGE并在WM_PAINT上绘图似乎很好。

然而,一些WM_PAINT用于我关注的窗口区域,但其他WM_PAINT用于完全不同的东西,如上下文菜单或按钮。

示例记事本与记事本屏幕中写入“Hello”的叠加层挂钩。这很好用。但是,当右键单击记事本时,上下文菜单会覆盖Hello。基本上,上下文菜单已被破坏。

是否有一种优雅的方法来确定WM_PAINT是什么上下文菜单?

LRESULT CALLBACK overlayHook(int code, WPARAM wParam, LPARAM lParam) {
    //Try and be the LAST responder to WM_PAINT messages;
    LRESULT retCode = CallNextHookEx(hhk, code, wParam, lParam);

    //Per GetMsgProc documentation, don't do anything fancy
    if(code < 0) {
        return retCode;
    }

    //Assumes that target application only draws when WM_PAINT message is
    //removed from input queue.
    if(wParam == PM_NOREMOVE) {
        return retCode;
    }

    MSG* message = (MSG*)lParam;
    if(message->message != WM_PAINT) {
        //Ignore everything that isn't a paint request
        return retCode;
    }

    PAINTSTRUCT psPaint;    
    BeginPaint(message->hwnd, &psPaint);
    HDC hdc = psPaint.hdc;
    RECT r = psPaint.rcPaint;           
    TextOut(hdc, 10, 10, "Hello", 4);
    EndPaint(message->hwnd, &psPaint);
    return retCode;
}

仅测试绘图更新区域是不够的,因为上下文菜单可以在任何地方并且包含我关注的区域。

1 个答案:

答案 0 :(得分:0)

我不知道有什么优雅的方法可以做到这一点,但你可以使用GetWindowLong()来获取窗口的样式或GetClassName()来获取它的类名,然后根据这些值做出过滤决策。