Jump to content
  • Advertisement
AireSpringfield

DX11 Member function as callback

This topic is 506 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

  I started reading Introduction to 3D Game Programming with Direct3D 11.0 and have a little question about callback function. In author's example code d3dApp.cpp, he managed to assign a member function to WNDCLASS::lpfnWndProc

namespace
{
    // This is just used to forward Windows messages from a global window
    // procedure to our member function window procedure because we cannot
    // assign a member function to WNDCLASS::lpfnWndProc.
    D3DApp* gd3dApp = 0;
}

LRESULT CALLBACK
MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // Forward hwnd on because we can get messages (e.g., WM_CREATE)
    // before CreateWindow returns, and thus before mhMainWnd is valid.
    return gd3dApp->MsgProc(hwnd, msg, wParam, lParam);
}

in constructor D3DApp::D3DApp()

gd3dApp = this;

and in bool D3DApp::InitMainWindow()

wc.lpfnWndProc   = MainWndProc; 

Notice that D3DApp::MsgProc is a virtual function. 

As far as I'm concerned, I would find it convenient to declare MsgProc member function as static. However, a static member can't be virtual. Is there any solution so that I can overcome the contradiction except author's method?

 
Edited by AireSpringfield

Share this post


Link to post
Share on other sites
Advertisement

As far as I know there is no way to assign a member function to lpfnWndProc. The author of the book assigned a proxy function to lpfnWndProc, and that function calls the member function MsgProc.

Static member functions, as you said, can't be virtual but you can design it so that it calls virtual member functions for each message type (OnCreate, OnPaint, OnDestroy, etc).

Share this post


Link to post
Share on other sites

The classic trick for doing this (it's from back in the old MFC days in the 90's) is to associate a pointer with your window using SetWindowLongPtr with GWLP_USERDATA. Then you set up a free function that's a proxy message handler, and that proxy handler grabs the pointer using GetWindowLongPtr. Here's an example from my very simple window wrapper class:

LRESULT WINAPI Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_NCCREATE:
        {
            LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
            ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
            return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
        }
    }
    Window* pObj = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
    if(pObj)
        return pObj->MessageHandler(hWnd, uMsg, wParam, lParam);
    else
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

Share this post


Link to post
Share on other sites
15 hours ago, MJP said:

The classic trick for doing this (it's from back in the old MFC days in the 90's) is to associate a pointer with your window using SetWindowLongPtr with GWLP_USERDATA. Then you set up a free function that's a proxy message handler, and that proxy handler grabs the pointer using GetWindowLongPtr. Here's an example from my very simple window wrapper class:

 


LRESULT WINAPI Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_NCCREATE:
        {
            LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
            ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
            return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
        }
    }
    Window* pObj = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
    if(pObj)
        return pObj->MessageHandler(hWnd, uMsg, wParam, lParam);
    else
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

 

OK, I'd say that I prefer the author's method... Thanks for your help!

Share this post


Link to post
Share on other sites
1 hour ago, AireSpringfield said:

OK, I'd say that I prefer the author's method... Thanks for your help!

Until you ever need two windows in your program ;)

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!