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

时光怂恿深爱的人放手 提交于 2020-01-03 17:31:23

问题


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.

}

}

回答1:


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.




回答2:


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.




回答3:


I believe this article is what you are looking for

http://msdn.microsoft.com/en-us/library/ff381400%28d=printer,v=vs.85%29.aspx




回答4:


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.




回答5:


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.




回答6:


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]] inline CallerT *GetWindowCaller(HWND window,
                                              UINT message, 
                                              [[maybe_unused]] WPARAM wParam, 
                                              LPARAM lParam) noexcept {
    if (WM_NCCREATE != message) {
        // Retrieves information about the specified window.
        // 1. A handle to the window and, indirectly, the class to which 
        // the window belongs.
        // 2. Retrieves the user data associated with the window.
        return reinterpret_cast< CallerT * >(GetWindowLongPtr(window, GWLP_USERDATA));
    }

    const auto caller = reinterpret_cast< CallerT * >(
                        reinterpret_cast< CREATESTRUCT * >(lParam)->lpCreateParams);

    // Changes an attribute of the specified window.
    // 1. A handle to the window and, indirectly, the class to which the 
    // window belongs.
    // 2. Sets the user data associated with the window.
    // 3. The replacement value.
    SetWindowLongPtr(window, 
                     GWLP_USERDATA, 
                     reinterpret_cast< LONG_PTR >(caller));

    return caller;
}

This method needs to be called in your message callback.



来源:https://stackoverflow.com/questions/7384823/sending-lparam-as-a-pointer-to-class-and-use-it-in-wndproc

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!