发送lparam作为指向类的指针,并在windowproc()中使用它

sending lparam as a pointer to class, and use it in WndProc()

本文关键字:windowproc 并在 指针 lparam 发送      更新时间:2023-10-16

我有这个抽象代码:我想在CreateWindowEx()中使用lParam(最后一个参数)来保存一个指向main - SaveArr开头声明的类的指针。然后,我想在函数WndProc中使用它。一开始我做了一个全局数组,然后我可以在任何地方使用它,但就c++而言,它不是那么"聪明",所以我试图升级它。

class Samples
{
        int arr[ITERATIONS+1];
        int index;
        ...
}
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow)
{
        Samples * SaveArr;
        ...
    hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
                          ClsName,
                          WindowCaption,
                          WS_OVERLAPPEDWINDOW,
                          INITIAL_WIN_LOCAT_X,
                          INITIAL_WIN_LOCAT_Y,
                          WIN_WIDTH,
                          WIN_HIGHT,
                          NULL,
                          NULL,
                          hInstance,
                          NULL);    //here i want to pass SaveArr, so that i can use it in the WndProc(...) function
...
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
   ...      //here i would like to use lParam as the class pointer, meaning using the 
              SaveArr declared in the main function.
}
}

向窗口添加调用者信息:

m_window = CreateWindow(..., this);

与扩展的CreateWindowEx相似。

获取调用者的指针:

template< typename CallerT >
[[nodiscard]]
CallerT* WindowCaller(HWND window, UINT message, LPARAM lParam) noexcept
{
    if (message == WM_NCCREATE) [[unlikely]]
    {
        const auto caller = reinterpret_cast< CallerT* >(
                            reinterpret_cast< CREATESTRUCT* >(lParam)->lpCreateParams);
        // Change the user data of the window for subsequent messages.
        ::SetWindowLongPtr(window, GWLP_USERDATA,
                           reinterpret_cast< LONG_PTR >(caller));
        return caller;
    }
    else
    {
        // Retrieve the user data of the window.
        return reinterpret_cast< CallerT* >(
                    ::GetWindowLongPtr(window, GWLP_USERDATA));
    }
}

这个方法需要在你的消息回调中调用。

最好的办法是

    LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
           Samples *savearr = (Samples*)GetWindowLong(hWnd,GWL_USERDATA)
           switch(Msg)
           {
                case WM_CREATE:
                    SetWindowLong(hWnd, GWL_USERDATA, (LONG)lParam);
                    break;
           }
    }

下次调用WndProc时,该值将保存在保存文件中,并且可以使用

来自参考:

lpParam [in, optional]

Type: LPVOID
Pointer to a value to be passed to the window through the
对象所指向的CREATESTRUCT结构(lpCreateParams成员)lParam WM_CREATE消息的参数。此消息被发送到在此函数返回之前创建的窗口。
If an application calls CreateWindow to create a MDI client

窗口,lpParam应该指向一个CLIENTCREATESTRUCT结构。如果一个MDI客户端窗口调用CreateWindow来创建一个MDI子窗口。lpParam应该指向一个MDICREATESTRUCT结构。lpParam可能是如果不需要额外的数据,则为NULL。

你期望lParam总是传递给WndProc,但它只与WM_CREATE传递。

请注意,即使这样,它也不是直接传递的,而是通过一个结构体传递的,这个结构体是WM_CREATE的实际lParam。

读取lParam的唯一机会是在WM_CREATE期间。如果您希望以后继续使用该值,则必须将其存储在某个地方。可能是作为WndProc的静态变量或者将它赋值给其他有作用域的东西

为什么坚持使用最后一个lpParam值设置为X,然后在WM_CREATE上捕获它(通过所有间接的结构体的东西,不低于!),然后设置GWL_USERDATA?!

为什么不开门见山,这样做:HWND H = CreateWindow(…)SetWindowLong (H, GWL_USERDATA, X)换句话说,你自己直接把X放在窗口创建语句后面。

在我的测试中,它工作,只要你测试窗口句柄的一些已知的句柄列表,你可以防止一些错误的消息被你的程序,并防止不适当地使用其他的userdata。

相关文章: