windows API 的 C++封装
// windows API 的 C++封装
//
// WndProc 是静态函数,可以被子类隐藏。
// 调用取决于创建窗口的注册结构。CXMDIView 进行了重定义隐藏。
// CXMDIFrame 使用CWnd的create创建窗口,因此无需定义WndProc函数,但是消息处理虚函数是需要的,
// 因为默认消息处理函数是不同的。
//
// 在WndProc中处理消息映射表,有三种,DefWindowProc; DefFrameProc;DefMDIChildProc;
//
// create 是虚函数,无论对象指针类是谁,创建的窗口是子类。
//
// 消息映射链表中的消息响应函数:基类函数,子类同名函数,虚函数等。
// 对这些函数的查询从子类向基类方向遍历,查到了就执行并返回。
// 实际上子类消息响应同名函数,要执行就必须加进消息映射表,否则消息向基类查询,执行基类的函数,
// 如果消息响应函数是虚函数,在子类中即使不加到消息映射表也是执行子类函数。
//
// this指针是窗口创建时传入的,CXWnd 和 CXMDIView 的传入方式有一点区别。
// 需要this调用成员函数。this是指向子类的基类指针,消息处理函数是虚函数。调用的函数取决于消息映射表。
//
// 宏在使用上比较方便,但是调试非常麻烦,最好把代码展开来调试。
//
程序运行的效果如下图:
主要的封装代码:
CXWnd 为窗口基类,派生出框架窗口,子窗口,主要功能是创建窗口,消息响应函数
XWnd.h
// windows API 的 C++封装 // // WndProc 是静态函数,可以被子类隐藏。 // 调用取决于创建窗口的注册结构。CXMDIView 进行了重定义隐藏。 // CXMDIFrame 使用CWnd的create创建窗口,因此无需定义WndProc函数,但是消息处理虚函数是需要的, // 因为默认消息处理函数是不同的。 // // 在WndProc中处理消息映射表,有三种,DefWindowProc; DefFrameProc;DefMDIChildProc; // // create 是虚函数,无论对象指针类是谁,创建的窗口是子类。 // // 消息映射链表中的消息响应函数:基类函数,子类同名函数,虚函数等。 // 对这些函数的查询从子类向基类方向遍历,查到了就执行并返回。 // 实际上子类消息响应同名函数,要执行就必须加进消息映射表,否则消息向基类查询,执行基类的函数, // 如果消息响应函数是虚函数,在子类中即使不加到消息映射表也是执行子类函数。 // // this指针是窗口创建时传入的,CXWnd 和 CXMDIView 的传入方式有一点区别。 // 需要this调用成员函数。this是指向子类的基类指针,消息处理函数是虚函数。调用的函数取决于消息映射表。 // // 宏在使用上比较方便,但是调试非常麻烦,最好把代码展开来调试。 // // #pragma once #include "xobj.h" #include "resource.h" extern int XSprintfMsg(char *fmt, ...); class CXWnd; typedef int (CXWnd::*X_PMSG)(HWND, UINT, WPARAM, LPARAM); #define dim(x) (sizeof(x)/sizeof(x[0])) enum XSig { XSig_end = 0, // [marks end of message map] XSig_lwl, // LRESULT (WPARAM, LPARAM) XSig_vv, // void (void) }; struct X_MSGMAP_ENTRY { UINT nMessage; // windows message UINT nCode; // control code or WM_NOTIFY code UINT nID; // control ID (or 0 for windows messages) UINT nLastID; // used for entries specifying a range of control id's UINT nSig; // signature type (action) or pointer to message # X_PMSG pfn; // routine to call (or special value) }; // the struct quote itself struct X_MSGMAP{ X_MSGMAP* pBaseMsgMap; X_MSGMAP_ENTRY* lpEntries; }; #define XDECLARE_MESSAGE_MAP() \ static X_MSGMAP_ENTRY _xmessageEntries[]; \ static X_MSGMAP xmessageMap; \ virtual X_MSGMAP* XGetMessageMap() const; #define XBEGIN_MESSAGE_MAP(theClass, baseClass) \ X_MSGMAP* theClass::XGetMessageMap() const \ { return &theClass::xmessageMap; } \ X_MSGMAP theClass::xmessageMap = \ { &(baseClass::xmessageMap), \ (X_MSGMAP_ENTRY*) &(theClass::_xmessageEntries) }; \ X_MSGMAP_ENTRY theClass::_xmessageEntries[]= \ { #define XON_MESSAGE(message, memberFxn) \ { message, 0, 0, 0, XSig_lwl, (X_PMSG)&memberFxn }, #define XON_COMMAND(id, memberFxn) \ { WM_COMMAND, 0, (WORD)id, (WORD)id, XSig_vv, (X_PMSG)&memberFxn }, #define XEND_MESSAGE_MAP() \ {0, 0,0,0, XSig_end, (X_PMSG) 0 } \ }; class CXWnd : public CXObj { public: CXWnd(void); ~CXWnd(void); XDECLARE_DYNCREATE(CXWnd) TCHAR szWindowClass[256]; // The title bar text TCHAR szTitle[256]; // The title bar text HINSTANCE m_hInst; HINSTANCE m_hPrevInstance; HWND m_hWnd; // HWND m_hWndClient; HMENU m_hMenu, m_hMenuWindow; virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, HINSTANCE hInstance, LPVOID lpParam); virtual BOOL PreCreateWindow(WNDCLASSEX &cs); virtual LRESULT Create(HINSTANCE hInstance, HINSTANCE Phinstance, LPTSTR lpstr, int nCmdShow); //frame virtual LRESULT Create(HINSTANCE hInstance, HWND hParent, int nCmdShow); // plane virtual LRESULT Create(HINSTANCE hInstance, HWND hParent); //child static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //======WM================ virtual int HandleMessage(HWND, UINT, WPARAM, LPARAM); virtual int OnCommand(HWND, UINT, WPARAM, LPARAM); virtual int OnNotify(HWND, UINT, WPARAM, LPARAM); int OnDestroy(HWND, UINT, WPARAM, LPARAM); int OnSize(HWND, UINT, WPARAM, LPARAM); virtual int OnHookMessage(HWND, UINT, WPARAM, LPARAM); XDECLARE_MESSAGE_MAP() };
XWnd.cpp
#include "StdAfx.h" #include "XWnd.h" X_MSGMAP* CXWnd::XGetMessageMap() const { return &CXWnd::xmessageMap; } X_MSGMAP CXWnd::xmessageMap = { NULL, (X_MSGMAP_ENTRY*) &(CXWnd::_xmessageEntries) }; X_MSGMAP_ENTRY CXWnd::_xmessageEntries[]= { // { message, 0, 0, 0, XSig_lwl, (X_PMSG)&memberFxn }, XON_MESSAGE(WM_SIZE, OnSize) XON_MESSAGE(WM_DESTROY, OnDestroy) XEND_MESSAGE_MAP() CXWnd::CXWnd(void) { m_hMenu = NULL; m_hMenuWindow = NULL; } CXWnd::~CXWnd(void) { } XIMPLEMENT_DYNCREATE(CXWnd, CXObj) BOOL CXWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, HINSTANCE hInstance, LPVOID lpParam) { // allow modification of several common create parameters CREATESTRUCT cs; cs.dwExStyle = dwExStyle; cs.lpszClass = lpszClassName; cs.lpszName = lpszWindowName; cs.style = dwStyle; cs.x = x; cs.y = y; cs.cx = nWidth; cs.cy = nHeight; cs.hwndParent = hWndParent; cs.hMenu = nIDorHMenu; cs.hInstance = hInstance; //xgz cs.lpCreateParams = lpParam; if (!PreCreateWindow(cs)) { return FALSE; } HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams); if (hWnd == NULL) return FALSE; m_hWnd = hWnd; //xgz return TRUE; } // for child windows BOOL CXWnd::PreCreateWindow(CREATESTRUCT& cs) { if (cs.lpszClass == NULL) { // make sure the default window class is registered cs.lpszClass = _T("X_defaultWnd"); } return TRUE; } BOOL CXWnd::PreCreateWindow(WNDCLASSEX& wcex) { return TRUE; } LRESULT CXWnd::Create(HINSTANCE hInstance, HINSTANCE Phinstance, LPTSTR lpstr, int nCmdShow) { WNDCLASSEX wcex; m_hInst = hInstance; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)(CXWnd::WndProc); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_XT); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //wcex.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); PreCreateWindow(wcex); RegisterClassEx(&wcex); m_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, m_hMenu, hInstance, this); if (!m_hWnd) { return FALSE; } ShowWindow(m_hWnd, nCmdShow); UpdateWindow(m_hWnd); return 0; } LRESULT CXWnd::Create(HINSTANCE hInstance, HWND hParent) { WNDCLASSEX wcex; m_hInst = hInstance; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)(CXWnd::WndProc); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_XT); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // wcex.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); PreCreateWindow(wcex); RegisterClassEx(&wcex); m_hWnd = CreateWindow(szWindowClass, szTitle, WS_CHILD|WS_BORDER|WS_VISIBLE|WS_THICKFRAME, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hParent, m_hMenu, hInstance, this); if (!m_hWnd) { return FALSE; } return 0; } LRESULT CXWnd::Create(HINSTANCE hInstance, HWND hParent, int nCmdShow) { WNDCLASSEX wcex; m_hInst = hInstance; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)(CXWnd::WndProc); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_XT); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // wcex.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); PreCreateWindow(wcex); RegisterClassEx(&wcex); m_hWnd = CreateWindow(szWindowClass, szTitle, WS_CHILD|WS_BORDER|WS_VISIBLE|WS_THICKFRAME, //WS_CHILD|WS_BORDER|WS_VISIBLE|WS_THICKFRAME, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hParent, m_hMenu, hInstance, this); if (!m_hWnd) { return FALSE; } ::ShowWindow(m_hWnd, nCmdShow); ::UpdateWindow(m_hWnd); return 0; } //return ::DefWindowProc(hWnd, message, wParam, lParam); // for normal windows //return ::DefFrameProc(hWnd, m_hWndClient, message, wParam, lParam); // for MDIFrame //return ::DefMDIChildProc(hWnd, message, wParam, lParam); // for MDIChild LRESULT CALLBACK CXWnd::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CXWnd* pThis = NULL; if( message == WM_NCCREATE ) { LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); pThis = static_cast<CXWnd*>(lpcs->lpCreateParams); pThis->m_hWnd = hWnd; SetWindowLong(hWnd, GWL_USERDATA, reinterpret_cast<LPARAM>(pThis)); } else { pThis = reinterpret_cast<CXWnd*>(GetWindowLong(hWnd, GWL_USERDATA)); if( message == WM_NCDESTROY && pThis != NULL ) { return 0; } } if( pThis != NULL ) { return pThis->HandleMessage(hWnd, message, wParam, lParam); } else { return ::DefWindowProc(hWnd, message, wParam, lParam); } return 0; } int CXWnd::OnCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { if(LOWORD(wParam) == (pMap->lpEntries+i)->nID) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } return ::DefWindowProc(hWnd, message, wParam, lParam); } int CXWnd::OnNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { if(LOWORD(wParam) == (pMap->lpEntries+i)->nID) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } return ::DefWindowProc(hWnd, message, wParam, lParam); } int CXWnd::OnHookMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // PRINT("CXWnd::OnHookProc %d, %d, %d, %d\r\n", hWnd, message, wParam, lParam); return 0; } int CXWnd::HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; OnHookMessage( hWnd, message, wParam, lParam); if(WM_COMMAND == message) return OnCommand(hWnd, message, wParam, lParam); // command table is same as WM table if(WM_NOTIFY == message) return OnNotify(hWnd, message, wParam, lParam); // command table is same as WM table X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { if(message == (pMap->lpEntries+i)->nMessage) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } return ::DefWindowProc(hWnd, message, wParam, lParam); } int CXWnd::OnSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hWnd, message, wParam, lParam); } int CXWnd::OnDestroy(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // PostQuitMessage(0); //the default not quite. return 0; }
CXMDIFrame 框架窗口,主要是是创建客户窗口,复写消息处理,另外还有框架的基本消息响应。
XMDIFrame.h
#pragma once #include "xwnd.h" #include "stdio.h" #define IDM_FIRSTCHILD 50000 //larger than other menu id. it is child windows dynamic menu id class CXMDIFrame : public CXWnd { public: CXMDIFrame(void); ~CXMDIFrame(void); XDECLARE_DYNCREATE(CXMDIFrame) public: HWND m_hWndClient; virtual BOOL PreCreateWindow(WNDCLASSEX &wcex); static BOOL CALLBACK CloseEnumProc(HWND hWnd, LPARAM lParam); //======WM================ virtual int HandleMessage(HWND, UINT, WPARAM, LPARAM); virtual int OnCommand(HWND, UINT, WPARAM, LPARAM); virtual int OnNotify(HWND, UINT, WPARAM, LPARAM); int OnQueryEndSession(HWND, UINT, WPARAM, LPARAM); int OnClose(HWND, UINT, WPARAM, LPARAM); int OnDestroy(HWND, UINT, WPARAM, LPARAM); int OnCreate(HWND, UINT, WPARAM, LPARAM); int OnSize(HWND, UINT, WPARAM, LPARAM); virtual int Init(void); //========command======== int OnNew(HWND, UINT, WPARAM, LPARAM); int OnAppExit(HWND, UINT, WPARAM, LPARAM); int OnFileClose(HWND, UINT, WPARAM, LPARAM); int OnCascade(HWND, UINT, WPARAM, LPARAM); int OnArrange(HWND, UINT, WPARAM, LPARAM); int OnTile(HWND, UINT, WPARAM, LPARAM); int OnCloseAll(HWND, UINT, WPARAM, LPARAM); virtual int OnAbout(HWND, UINT, WPARAM, LPARAM); XDECLARE_MESSAGE_MAP() };
XMDIFrame.cpp
#include "StdAfx.h" #include "XMDIFrame.h" #include "XMDIView.h" XIMPLEMENT_DYNCREATE(CXMDIFrame, CXWnd) XBEGIN_MESSAGE_MAP(CXMDIFrame, CXWnd) XON_MESSAGE(WM_CREATE, OnCreate) XON_MESSAGE(WM_SIZE, OnSize) XON_MESSAGE(WM_DESTROY, OnDestroy) XON_MESSAGE(WM_COMMAND, OnCommand) XON_MESSAGE(WM_QUERYENDSESSION, OnQueryEndSession) XON_MESSAGE(WM_CLOSE, OnClose) XON_COMMAND(IDM_ABOUT, OnAbout) XON_COMMAND(IDM_FILE_NEWHELLO, OnNew) XON_COMMAND(IDM_FILE_CLOSE, OnFileClose) XON_COMMAND(IDM_WINDOW_CASCADE, OnCascade) XON_COMMAND(IDM_WINDOW_ARRANGE, OnArrange) XON_COMMAND(IDM_WINDOW_TILE, OnTile) XON_COMMAND(IDM_WINDOW_CLOSEALL, OnCloseAll) XON_COMMAND(IDM_APP_EXIT, OnAppExit) XEND_MESSAGE_MAP() CXMDIFrame::CXMDIFrame(void) { wcscpy_s(szWindowClass,_T("MT_FrameWnd")); // The title bar text wcscpy_s(szTitle,_T("XT")); // The title bar text m_hWnd = NULL; m_hWndClient = NULL; //xgz important for msg loop } CXMDIFrame::~CXMDIFrame(void) { } BOOL CXMDIFrame::PreCreateWindow(WNDCLASSEX &wcex) //cs { wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)(CXWnd::WndProc); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = m_hInst; wcex.hIcon = LoadIcon(m_hInst, (LPCTSTR)IDI_XT); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return TRUE; } int CXMDIFrame::OnCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; PRINT(_T("CXFrame::OnCommand %d, %d, %d, %d\r\n"), hWnd, message, wParam, lParam); X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { if(LOWORD(wParam) == (pMap->lpEntries+i)->nID) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } HWND hwndChild = (HWND) SendMessage(m_hWndClient, WM_MDIGETACTIVE,0,0); if(IsWindow(hwndChild)) SendMessage(hwndChild, WM_COMMAND, wParam, lParam); // some menu ID is for child window. return ::DefFrameProc(hWnd, m_hWndClient, message, wParam, lParam); } int CXMDIFrame::OnNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { if(LOWORD(wParam) == (pMap->lpEntries+i)->nID) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } return ::DefFrameProc(hWnd, m_hWndClient, message, wParam, lParam); } int CXMDIFrame::HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; if(WM_COMMAND == message) return OnCommand(hWnd, message, wParam, lParam); // command table is same as WM table if(WM_NOTIFY == message) return OnNotify(hWnd, message, wParam, lParam); // command table is same as WM table X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { if(message == (pMap->lpEntries+i)->nMessage) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } return ::DefFrameProc(hWnd, m_hWndClient, message, wParam, lParam); } int CXMDIFrame::OnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CLIENTCREATESTRUCT clientcreate; clientcreate.hWindowMenu = m_hMenuWindow; clientcreate.idFirstChild = IDM_FIRSTCHILD; m_hWndClient = CreateWindow(TEXT("MDICLIENT"), NULL, WS_CHILD|WS_CLIPCHILDREN |WS_VISIBLE, 0,0,0,0, m_hWnd, (HMENU) 1, m_hInst, (PSTR) &clientcreate); Init(); return 0; } int CXMDIFrame::OnSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefFrameProc(hWnd, m_hWndClient, message, wParam, lParam); } int CXMDIFrame::OnDestroy(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PostQuitMessage(0); //frame 退出则程序退出 return 0; } int CXMDIFrame::OnNew(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CXMDIView* WndView = new CXMDIView(); if (WndView == NULL)return 0; WndView->Create(m_hInst, m_hWndClient); return 0; } int CXMDIFrame::OnFileClose(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HWND hwndChild =(HWND) SendMessage(m_hWndClient, WM_MDIGETACTIVE, 0,0); //SendMessage is call proc if(SendMessage(hwndChild, WM_QUERYENDSESSION,0,0)) // The command did not come from the target app, so need confirm SendMessage(m_hWndClient,WM_MDIDESTROY, (WPARAM) hwndChild,0); return 0; } int CXMDIFrame::OnClose(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { SendMessage(hWnd, WM_COMMAND, IDM_WINDOW_CLOSEALL,0); if(NULL != GetWindow(m_hWndClient,GW_CHILD)) return 0; return DefFrameProc(hWnd, m_hWndClient, message, wParam, lParam);; } int CXMDIFrame::OnQueryEndSession(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return OnClose(hWnd, message, wParam, lParam);; } BOOL CALLBACK CXMDIFrame::CloseEnumProc(HWND hWnd, LPARAM lParam) { if(GetWindow(hWnd,GW_OWNER)) // it is not for minimized win. never return. mybe for ctrl wnd. eg, Edit,Button. return TRUE; SendMessage(GetParent(hWnd), WM_MDIRESTORE, (WPARAM)hWnd, 0); if(!SendMessage(hWnd, WM_QUERYENDSESSION,0,0)) // this child can not close, will block here until ready close, Sendmessage return == case return from child wnd return TRUE; SendMessage(GetParent(hWnd), WM_MDIDESTROY, (WPARAM)hWnd, 0); return TRUE; } int CXMDIFrame::OnCloseAll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { EnumChildWindows(m_hWndClient, CloseEnumProc, 0); // return after enumerated or func return false return 0; } int CXMDIFrame::OnAppExit(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { SendMessage(hWnd, WM_CLOSE, 0,0); return 0; } int CXMDIFrame::OnCascade(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { SendMessage(m_hWndClient, WM_MDICASCADE,0,0); return 0; } int CXMDIFrame::OnArrange(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { SendMessage(m_hWndClient, WM_MDIICONARRANGE,0,0); //ArrangeIconicWindows(hwndClient); return 0; } int CXMDIFrame::OnTile(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { SendMessage(m_hWndClient, WM_MDITILE,0,0); return 0; } int CXMDIFrame::Init(void) { return 0; } int CXMDIFrame::OnAbout(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { MessageBox(hWnd, _T("Frame"),_T("About"),MB_OK); return 0; } //===============================================
CXMDIView 为子窗口
XMDIView.h
#pragma once #include "xwnd.h" #include "stdio.h" class CXMDIView : public CXWnd { public: CXMDIView(void); ~CXMDIView(void); XDECLARE_DYNCREATE(CXMDIView) public: virtual LRESULT Create(HINSTANCE hInstance, HWND hWndParent); HMENU m_hMenuMDIInit, m_hMenuMDIInitWindow; // When View closed HWND m_hWndClient, m_hWndFrame; virtual BOOL PreCreateWindow(WNDCLASSEX &cs); virtual BOOL PreCreateWindow(MDICREATESTRUCT &mdicreate); static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); virtual int HandleMessage(HWND, UINT, WPARAM, LPARAM); virtual int OnCommand(HWND, UINT, WPARAM, LPARAM); virtual int OnNotify(HWND, UINT, WPARAM, LPARAM); int OnCreate(HWND, UINT, WPARAM, LPARAM); int OnPaint(HWND, UINT, WPARAM, LPARAM); int OnSize(HWND, UINT, WPARAM, LPARAM); int OnChar(HWND, UINT, WPARAM, LPARAM); int OnClose(HWND, UINT, WPARAM, LPARAM); int OnDestroy(HWND, UINT, WPARAM, LPARAM); int OnMdiActive(HWND, UINT, WPARAM, LPARAM); int OnExit(HWND, UINT, WPARAM, LPARAM); XDECLARE_MESSAGE_MAP() };
XMDIView.cpp
#include "StdAfx.h" #include "XMDIView.h" XIMPLEMENT_DYNCREATE(CXMDIView, CXWnd) XBEGIN_MESSAGE_MAP(CXMDIView, CXWnd) XON_MESSAGE(WM_CREATE, OnCreate) XON_MESSAGE(WM_SIZE, OnSize) XON_MESSAGE(WM_DESTROY, OnDestroy) XON_MESSAGE(WM_COMMAND, OnCommand) XON_MESSAGE(WM_PAINT, OnPaint) XON_MESSAGE(WM_CHAR, OnChar) XON_MESSAGE(WM_CLOSE, OnClose) XON_MESSAGE(WM_MDIACTIVATE, OnMdiActive) XEND_MESSAGE_MAP() CXMDIView::CXMDIView(void) { wcscpy_s(szWindowClass,_T("XMDIView")); // The title bar text wcscpy_s(szTitle,_T("XMDIView")); m_hWnd = NULL; } CXMDIView::~CXMDIView(void) { } BOOL CXMDIView::PreCreateWindow(WNDCLASSEX &cs) { return TRUE; } BOOL CXMDIView::PreCreateWindow(MDICREATESTRUCT &mdicreate) { return TRUE; } LRESULT CXMDIView::Create(HINSTANCE hInstance, HWND hWndParent) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)(CXMDIView::WndProc); //(WNDPROC)(CXWnd::WndProc);// wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(HANDLE); //XGZ???? wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_XT); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //wcex.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); RegisterClassEx(&wcex); MDICREATESTRUCT mdicreate; mdicreate.szClass = szWindowClass; mdicreate.szTitle = szTitle; mdicreate.hOwner = hInstance; mdicreate.x = CW_USEDEFAULT; mdicreate.y = CW_USEDEFAULT; mdicreate.cx = CW_USEDEFAULT; mdicreate.cy = CW_USEDEFAULT; mdicreate.style = 0; mdicreate.lParam = (LPARAM)this; // xgz m_hInst = hInstance; m_hWndClient = hWndParent; m_hWndFrame = GetParent(m_hWndClient); PreCreateWindow(mdicreate); m_hWnd = (HWND) SendMessage(m_hWndClient, WM_MDICREATE,0, (LPARAM)(LPMDICREATESTRUCT) &mdicreate); return 0; } LRESULT CALLBACK CXMDIView::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CXMDIView* pThis = NULL; if( message == WM_NCCREATE ) { LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); LPMDICREATESTRUCT lpms = reinterpret_cast<LPMDICREATESTRUCT>(lpcs->lpCreateParams); //pThis = static_cast<CXMDIView*>(lpcs->lpCreateParams); pThis = reinterpret_cast<CXMDIView*>(lpms->lParam); pThis->m_hWnd = hWnd; SetWindowLong(hWnd, GWL_USERDATA, reinterpret_cast<LPARAM>(pThis)); } else { pThis = reinterpret_cast<CXMDIView*>(GetWindowLong(hWnd, GWL_USERDATA)); if( message == WM_NCDESTROY && pThis != NULL ) { return 0; } } if( pThis != NULL ) { return pThis->HandleMessage(hWnd, message, wParam, lParam); } else { //return ::DefWindowProc(hWnd, message, wParam, lParam); return ::DefMDIChildProc(hWnd, message, wParam, lParam); } return 0; } int CXMDIView::OnCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; // PRINT("CXMDIView::OnCommand %d, %d, %d, %d\r\n", hWnd, message, wParam, lParam); X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { if(LOWORD(wParam) == (pMap->lpEntries+i)->nID) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } return ::DefMDIChildProc(hWnd, message, wParam, lParam); } int CXMDIView::OnNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; // PRINT("CXMDIView::OnNotify %d, %d, %d, %d\r\n", hWnd, message, wParam, lParam); X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { // if(LOWORD(wParam) == (pMap->lpEntries+i)->nID) if(message == (pMap->lpEntries+i)->nMessage) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } return ::DefMDIChildProc(hWnd, message, wParam, lParam); } int CXMDIView::HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int i; OnHookMessage( hWnd, message, wParam, lParam); // PRINT("CXMDIView::HandleMessage %d, %d, %d, %d\r\n", hWnd, message, wParam, lParam); if(WM_COMMAND == message) return OnCommand(hWnd, message, wParam, lParam); // command table is same as WM table if(WM_NOTIFY == message) return OnNotify(hWnd, message, wParam, lParam); // command table is same as WM table X_MSGMAP* pMap = this->XGetMessageMap(); for(; pMap != NULL; pMap = pMap->pBaseMsgMap) { for(i=0; (pMap->lpEntries+i)->nSig != XSig_end; i++) { if(message == (pMap->lpEntries+i)->nMessage) { return (this->*((pMap->lpEntries+i)->pfn))( hWnd, message, wParam, lParam); } } } //return ::DefWindowProc(hWnd, message, wParam, lParam); //return ::DefFrameProc(hWnd, m_hwndClient, message, wParam, lParam); return ::DefMDIChildProc(hWnd, message, wParam, lParam); } int CXMDIView::OnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return 0; } int CXMDIView::OnPaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... RECT rt; GetClientRect(hWnd, &rt); DrawText(hdc, _T("CXMDIView"), wcslen(_T("CXMDIView")), &rt, DT_CENTER); EndPaint(hWnd, &ps); return 0; } int CXMDIView::OnSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefMDIChildProc(hWnd, message, wParam, lParam); } int CXMDIView::OnChar(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefMDIChildProc(hWnd, message, wParam, lParam); } int CXMDIView::OnDestroy(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { m_hWnd = NULL; // PostQuitMessage(0); return 0; } int CXMDIView::OnExit(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { DestroyWindow(hWnd); return 0; } int CXMDIView::OnMdiActive(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { //wParam is deactivated Handle, lParam is activated Handle //PRINT(_("\r\nCXMDIView::OnActive")); if(lParam == (LPARAM) hWnd) //active { SendMessage(m_hWndClient, WM_MDISETMENU, (WPARAM)m_hMenu, (LPARAM) m_hMenuWindow); } else { SendMessage(m_hWndClient, WM_MDISETMENU, (WPARAM) m_hMenuMDIInit, (LPARAM)m_hMenuMDIInitWindow); } DrawMenuBar(m_hWndFrame); return 0; } int CXMDIView::OnClose(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefMDIChildProc(hWnd, message, wParam, lParam); }