Win32 C++ Create a Window and Procedure Within a Class

后端 未结 5 1793
刺人心
刺人心 2020-12-09 11:16

Pre-Text/ Question

I am trying to make a fairly simple tool to help debug variable values. For it to be completely self contained within the class i

5条回答
  •  借酒劲吻你
    2020-12-09 11:56

    The main message loop must not be in your class, and especially not in a "CreateTestWindow" function, as you will not return from that function until your thread receive the WM_QUIT message that makes GetMessage returns 0.

    Here is simple implementation of your viewvars class. Key points:

    • The Window Proc is a static member.
    • The link between the Window Proc and the object is made through the use of GWLP_USERDATA. See SetWindowLongPtr.
    • The class DTOR destroys the window if it still exists. The WM_DESTROY message set the HWND member to 0.
    • Adding OnMsgXXX methods to the class is simple: declare/define then and just call them from the WindowProc using the 'this' pointer stored in GWLP_USERDATA.

    EDIT:

    • As per Mr Chen suggestion, earlier binding of the HWND to the Object (in WM_NCCREATE) to allow message handler as methods during the Window Creation.

    I changed the creation styles, to show the window and to be able to move it.

    // VIEWVARS.H
    class viewvars {
    
    public:
        static viewvars* CreateTestWindow( HINSTANCE hInstance );
        viewvars() : m_hWnd( 0 ) {}
        ~viewvars();
    
    private:
        static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
        static const char * m_pszClassName;
        HWND m_hWnd;
    
    };
    
    // VIEWVARS.CPP
    #include "viewvars.h"
    
    const char * viewvars::m_pszClassName = "viewvars";
    
    viewvars * viewvars::CreateTestWindow( HINSTANCE hInst ) {
    
        WNDCLASS wincl;
        if (!GetClassInfo(hInst, m_pszClassName, &wincl)) {
            wincl.style = 0;
            wincl.hInstance = hInst;
            wincl.lpszClassName = m_pszClassName;
            wincl.lpfnWndProc = WindowProc;
            wincl.cbClsExtra = 0;
            wincl.cbWndExtra = 0;
            wincl.hIcon = NULL;
            wincl.hCursor = NULL;
            wincl.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
            wincl.lpszMenuName = NULL;
            if (RegisterClass(&wincl) == 0) {
                MessageBox(NULL,"The window class failed to register.","Error",0);
                return 0;
            }
        }
    
        viewvars * pviewvars = new viewvars;
        HWND hWnd = CreateWindow( m_pszClassName, "Test", WS_VISIBLE | WS_OVERLAPPED, 50, 50, 200, 200, NULL, NULL, hInst, pviewvars );
        if ( hWnd == NULL ) {
            delete pviewvars;
            MessageBox(NULL,"Problem creating the window.","Error",0); 
            return 0; 
        }
    
        return pviewvars;
    
    }
    
     LRESULT CALLBACK viewvars::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    
        switch ( uMsg ) {
    
            case WM_NCCREATE: {
                CREATESTRUCT * pcs = (CREATESTRUCT*)lParam;
                viewvars * pviewvars = (viewvars*)pcs->lpCreateParams;
                pviewvars->m_hWnd = hwnd;
                SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG)pcs->lpCreateParams );
                return TRUE;
            }
    
            case WM_DESTROY: {
                viewvars * pviewvars = (viewvars *)GetWindowLongPtr( hwnd, GWLP_USERDATA );
                if ( pviewvars ) pviewvars->m_hWnd = 0;
                break;
            }
    
            default:
                return DefWindowProc( hwnd, uMsg, wParam, lParam );
    
        }
    
        return 0;
    
    }
    
    viewvars::~viewvars() {
        if ( m_hWnd ) DestroyWindow( m_hWnd );
    }
    

    Finally, a "main" sample, but beware that there is here no way to end the process. That should be taken care by regular code (another windows).

    // MAIN.CPP
    #include 
    #include "viewvars.h"
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
        viewvars * pviewvars = viewvars::CreateTestWindow( hInstance );
        if ( pviewvars == 0 ) return 0;
    
        BOOL bRet;
        MSG msg;
        while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0)
        { 
            if (bRet == -1)
            {
                // handle the error and possibly exit
            }
            else
            {
                TranslateMessage(&msg); 
                DispatchMessage(&msg); 
            }
        }
    
        delete pviewvars;
    
        return 0;
    
    }
    

提交回复
热议问题