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

xpszyzbs  于 2023-01-03  发布在  其他
关注(0)|答案(5)|浏览(212)

我正在一个IDE中工作,它创建了一个hwnd和它各自的WndProcLRESULT 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;
};
cbwuti44

cbwuti441#

您需要使用类似于以下内容的内容:

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
例如:

#define MY_SUBCLASS_ID 1

SetWindowSubclass(hwnd, &mySubClassProc, MY_SUBCLASS_ID, 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, uIdSubclass);
            break;
    }

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

ovfsdjhp2#

一个简单的演员阵容就可以完成这项工作。
第一个月
否则将是不兼容的类型:结果和长期。

vd8tlhqk

vd8tlhqk3#

SetWindowLong()的MSDN文档指出GWL_WNDPROC
设置窗口过程的新地址。
这意味着你的第三个参数应该是一个指向函数的指针,因此你的SetWindowLong()调用应该如下所示:

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

另请注意备注部分,其中指出:
应用程序必须通过调用CallWindowProc将新窗口过程未处理的任何消息传递给上一个窗口过程。

w8rqjzmb

w8rqjzmb4#

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

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

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

#include <windows.h>

void registerWindow();
void createWindow();
void messageLoop();

int main()
{
 registerWindow();
 createWindow();
 messageLoop();
}

LRESULT CALLBACK myWindowProcedure(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
 return DefWindowProc(hwnd,msg,wparam,lparam);
}

void registerWindow()
{
 /** This is the important part.
    * Find this part in your code.
    * Set WNDCLASS::lpfnWndProc to what ever 
    * window procedure you want.
 **/

 WNDCLASS wc = {};

 wc.lpfnWndProc   = myWindowProcedure;
 wc.hInstance     = hInstance;
 wc.lpszClassName = "CLASS NAME";

 RegisterClass(&wc);

 // WARNING: Your app will crash at runtime if the 
 // windows procedure is "NOT PROPER"
}

void createWindow()
{
 auto hwnd = CreateWindowEx(
    0,                              // Optional window styles.
    "CLASS NAME",                     // Window class
    "Learn to Program Windows",    // Window text
    WS_OVERLAPPEDWINDOW,            // Window style

    // Size and position
    CW_USEDEFAULT, 
    CW_USEDEFAULT, 
    CW_USEDEFAULT, 
    CW_USEDEFAULT,

    NULL,       // Parent window    
    NULL,       // Menu
    HINSTANCE(),  // Instance handle
    NULL        // Additional application data
    );

   ShowWindow(hwnd, nCmdShow
}

void messageLoop()
{
    MSG msg;
    while( GetMessage(&msg, NULL, 0, 0) )
   {
    TranslateMessage(&msg); 
    DispatchMessage(&msg);
   }
}
ykejflvf

ykejflvf5#

您必须使用SetWindowLongPtr(在32位上是一个宏,但在64位上是一个单独的函数)来确保与32位和64位系统的兼容性。
语法如下所示:

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

注意SetWindowLongPtr被用来代替SetWindowLong,GWLP_WNDPROC被用作nIndex常量。

相关问题