C++[类设计]静态窗口过程调用非静态成员函数

来源:互联网 发布:java list排序算法 编辑:程序博客网 时间:2024/05/20 00:17
当自定义一个窗口类时,通常将类的某一个成员函数作为窗口过程。但在C++类中,所有的窗口过程或者回调函数只能是静态的。如此一来,在窗口过程或回调函数中被访问到的所有成员均被迫定义成静态的(因为静态函数只能调用同样为静态的函数或访问静态的变量),这往往不能满足我们的程序设计要求。下面我们以窗口过程为例介绍如何避免这种限制,即实现在静态的窗口过程函数中调用非静态的成员函数。
//in MainProgram.cpp#include <windows.h>#include "CustomWnd.h"int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){CCustomWnd wnd,wnd2;wnd.Create();wnd2.Create();MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}//in CustomWnd.h#pragma once#include <windows.h>#include <tchar.h>#include <assert.h>#define CLASSNAME_T("CUSTOM_CLASS_NAME")#define WINDOWNAME_T("CustomWnd")class CCustomWnd{public:CCustomWnd(HWND hParentWnd=NULL);~CCustomWnd(void);private://the count of windowsstatic int cWnd;private:HWND m_hWnd;HWND m_hParentWnd;WNDCLASS m_wndClass;private://Register Windows Class.bool Init(void);public://Create and show a window.HWND Create(void);int ShowMessageBox(void);public:static LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);};//in CustomWnd.cpp#include "CustomWnd.h"int CCustomWnd::cWnd=0;CCustomWnd::CCustomWnd(HWND hParentWnd){++cWnd;m_hWnd=NULL;m_hParentWnd=hParentWnd;Init();}CCustomWnd::~CCustomWnd(void){}//Register Windows Class.bool CCustomWnd::Init(void){m_wndClass.style=CS_HREDRAW | CS_VREDRAW;m_wndClass.lpfnWndProc=&CCustomWnd::WndProc;m_wndClass.cbClsExtra=0;m_wndClass.cbWndExtra=0;m_wndClass.hInstance=NULL;m_wndClass.hIcon=LoadIcon(NULL, IDI_APPLICATION);m_wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);m_wndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);m_wndClass.lpszMenuName=NULL;m_wndClass.lpszClassName=CLASSNAME;int nRet=RegisterClass(&m_wndClass);if(0==nRet){DWORD dwErr=GetLastError();switch(dwErr){case ERROR_CLASS_ALREADY_EXISTS:{return true;}break;}}assert(nRet!=0);return true;}//Create and show a window.HWND CCustomWnd::Create(void){m_hWnd=CreateWindow(CLASSNAME,WINDOWNAME,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,m_hParentWnd,NULL,NULL,/*如果创建的是单文档应用程序,传递的这个参数将被放置到CREATESTRUCT结构体中的lpCreateParams成员中。之后可以在相应的消息如WM_NCCREATE或WM_CREATE处理程序中取回该参数的值。*/(LPVOID)this);ShowWindow(m_hWnd,SW_SHOW);UpdateWindow(m_hWnd);return m_hWnd;}int CCustomWnd::ShowMessageBox(void){return MessageBox(m_hWnd,_T("这个弹窗来自非静态成员函数,它在静态窗口过程中被调用"),_T("确定要退出吗?"),MB_YESNO);}LRESULT CCustomWnd::WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){switch(uMsg){case WM_NCCREATE:{CREATESTRUCT* pCREATESTRUCT=(CREATESTRUCT*)lParam;/*由于窗口过程WndProc是静态的,因此如果想将前面传递的值保存到成员变量中,那么这个成员变量必须也是静态的。但静态成员不符合我们的设计要求。办法是将该值保存到窗口中,使用时再取出。*/CCustomWnd* pThis=(CCustomWnd*)pCREATESTRUCT->lpCreateParams;SetWindowLong(hWnd,GWL_USERDATA,(long)pThis);return true;}break;case WM_CLOSE:{CCustomWnd* pThis=(CCustomWnd*)GetWindowLong(hWnd,GWL_USERDATA);if(IDYES == pThis->ShowMessageBox() )DestroyWindow(hWnd);break;return 0;}break;case WM_DESTROY:{--cWnd;if(0==cWnd)PostQuitMessage(0);}break;default:return DefWindowProc(hWnd,uMsg,wParam,lParam);}}


以上是使用 SetWindowLong和GetWindowLong的情况。实际上还可以使用SetProp和GetProp来代替,并且实现上述同样的功能更简单。在此不举例。
0 0