C ++在运行时更改HWND窗口过程

时间:2015-07-27 08:23:05

标签: c++ winapi runtime wndproc hwnd

我正在使用IDE创建hwnd及其各自的WndProc LRESULT CALLBACK。我需要将WndProc更改为自定义的。

我已经读过SetWindowLong会做这个工作,但我找不到任何有用的例子。例如:

HWND hwnd; //My window

SetWindowLong(hwnd, GWL_WNDPROC, myNewWndProc);

SetWindowLong的第三个参数是Long,因为函数的名称命名它。如何从WndProc功能引用Long

我的WndProc

LRESULT CALLBACK WndProcedure(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){

msg_dev(toString(uMsg));

switch(uMsg){

    case WM_MOUSEMOVE:
        SetCursor(LoadCursor(NULL, IDC_HAND));
        break;

    case WM_LBUTTONDOWN:
        msg_dev("Button down!");
        break;

    default:
        DefWindowProc(hwnd, uMsg, wParam, lParam);
}

return 0;
};

5 个答案:

答案 0 :(得分:10)

您需要使用以下内容:

WNDPROC prevWndProc;
...
prevWndProc = (WNDPROC) SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)&myNewWndProc);
...    
LRESULT CALLBACK myNewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    msg_dev(toString(uMsg));

    switch(uMsg)
    {
        case WM_MOUSEMOVE:
            SetCursor(LoadCursor(NULL, IDC_HAND));
            break;

        case WM_LBUTTONDOWN:
            msg_dev("Button down!");
            break;
    }

    return CallWindowProc(prevWndProc, hwnd, uMsg, wParam, lParam);
}

参见这篇文章:

When you subclass a window, it's the original window procedure of the window you subclass you have to call when you want to call the original window procedure

话虽如此,您应该使用SetWindowSubclass()代替SetWindowLongPtr()。看到这篇文章:

Safer subclassing

例如:

SetWindowSubclass(hwnd, &mySubClassProc, 1, 0);
...    
LRESULT CALLBACK mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    msg_dev(toString(uMsg));

    switch(uMsg)
    {
        case WM_MOUSEMOVE:
            SetCursor(LoadCursor(NULL, IDC_HAND));
            break;

        case WM_LBUTTONDOWN:
            msg_dev("Button down!");
            break;

        case WM_NCDESTROY:
            RemoveWindowSubclass(hWnd, &mySubClassProc, 1);
            break;
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

答案 1 :(得分:0)

SetWindowLong()的MSDN文档指出GWL_WNDPROC

  

为窗口过程设置新地址。

这意味着您的第三个参数应该是指向函数的指针。因此,您的SetWindowLong()电话应如下所示:

SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR)&myNewWndProc);

另请注意备注部分:

  

应用程序必须通过调用CallWindowProc将未通过新窗口过程处理的任何消息传递给上一个窗口过程。

答案 2 :(得分:0)

一个简单的演员来完成这项工作。

SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)&myNewWndProc);

否则它将是不兼容的类型:LRESULT和LONG。

答案 3 :(得分:0)

您可以使用setWindowLong解决您的问题。

genesis_register_sidebar( array(
    'id'          => 'before-home-top',
    'name'        => __( 'Before Home Top', 'magazine-pro' ),
) );

但是您将两次设置窗口过程。使用IDE默认值,然后再使用默认值。注册窗口时,您需要做的是设置窗口过程。

setWindowLong(hwnd,GWL_WNDPROC,(LONG)newWindowProcedure);

答案 4 :(得分:0)

必须使用SetWindowLongPtr(在32位上为宏,但在64位上为单独的函数),以确保与32位和64位系统兼容。

语法如下:

SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)&myNewWndProc);

请注意,使用SetWindowLongPtr代替SetWindowLong,并将GWLP_WNDPROC用作nIndex常量。