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

发布于 2024-12-04 06:01:30 字数 1240 浏览 1 评论 0原文

我有这个抽象代码: 我想在 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.

}

}

i have this abstract code :
i want to use lParam (last parameter) in CreateWindowEx() to save a pointer to a class thats declared in the begining of main - SaveArr. then, i want to use it in the function WndProc.
in the begining i did a global array, and then i could use it anywhere, but its not so "clever" as far as c++ concern, so im trying to upgrade it a bit.

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.

}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

千里故人稀 2024-12-11 06:01:30

向窗口添加调用者信息

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));
    }
}

需要在消息回调中调用此方法。

Adding caller information to the window:

m_window = CreateWindow(..., this);

Similar for the extended CreateWindowEx.

Obtaining a pointer to the caller:

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));
    }
}

This method needs to be called in your message callback.

池木 2024-12-11 06:01:30

最好的方法是

    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 时,该值将位于 savearr 中,并且可以使用。

Best way would be

    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;
           }
    }

The next time the WndProc is called the value would be in savearr, and can be used.

你列表最软的妹 2024-12-11 06:01:30

来自参考

lpParam [输入,可选]

<前><代码>类型:LPVOID

指向要通过窗口传递给窗口的值的指针

CREATESTRUCT 结构(lpCreateParams 成员)指向
lParam WM_CREATE消息的参数。此消息发送至
该函数在返回之前创建了窗口。

如果应用程序调用CreateWindow创建MDI客户端

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

您期望 lParam 始终传递到 WndProc,但它仅与 WM_CREATE 一起传递。

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

From the reference:

lpParam [in, optional]

Type: LPVOID

Pointer to a value to be passed to the window through the

CREATESTRUCT structure (lpCreateParams member) pointed to by the
lParam param of the WM_CREATE message. This message is sent to the
created window by this function before it returns.

If an application calls CreateWindow to create a MDI client

window, lpParam should point to a CLIENTCREATESTRUCT structure. If an
MDI client window calls CreateWindow to create an MDI child window,
lpParam should point to a MDICREATESTRUCT structure. lpParam may be
NULL if no additional data is needed.

You're expecting the lParam to be always passed to WndProc, but it is only passed with WM_CREATE.

Note, that even then it's not passed directly, but rather through a structure which is the actual lParam for WM_CREATE.

灼疼热情 2024-12-11 06:01:30

读取 lParam 的唯一机会是在 WM_CREATE 期间。如果您想稍后继续使用该值,则必须将其存储在某个地方。也许作为 WndProc 的静态或以其他方式将其分配给其他将被限定作用域的东西。

Your only chance to read the lParam is during WM_CREATE. If you want to keep using the value later then you must store it somewhere. Maybe as a static of the WndProc or otherwise assign it to something else which is going to be scoped.

牛↙奶布丁 2024-12-11 06:01:30

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

为什么不开门见山地这样做:
HWND H=创建窗口(.....)
SetWindowLong(H,GWL_USERDATA,X)
换句话说,您自己直接将 X 放在窗口创建语句之后。

在我的测试中它是有效的,只要您针对某些已知句柄列表测试窗口句柄,您就可以防止程序拾取一些错误消息,并防止不当使用其他用户数据。

Why all the insistence on using that last, lpParam value set to X, then catching it on WM_CREATE (through all that indirect struct stuff, no less!) and then setting GWL_USERDATA?!

Why not cut to the chase and do this:
HWND H=CreateWindow(.....)
SetWindowLong(H,GWL_USERDATA,X)
In other words, just put X there directly, yourself, right after the window creation statement.

In my tests it works, and so long as you test the window handle against some list of known handles, you can prevent some errant message picked up by your program, and prevent inappropriate use of something else's userdata.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文