本文主要是在一个主窗口下创建一个子窗口。主窗口有一个菜单,菜单下只有设置一个选项,点击设置选项,弹出设置界面,点击设置界面关闭则关闭。我在开发的时候遇到两个问题,第一就是一点设置关闭就整个应用都关了,原来是destroy消息共用了。然后第二个是点击关闭后,设置界面再也显示不出来了,原来是close消息也要分拣。
菜单志愿为IDR_MENU,设置ID选项为ID_SETTING。
文件如下:
Main.cpp
#include "resource.h" #include<tchar.h> #include<stdio.h> #include<windows.h> #include "SettingMgr.h" #define ClassName _T("sunxin2006") HINSTANCE g_hInstance = 0; LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wndcls; wndcls.cbClsExtra = 0; wndcls.cbWndExtra = 0; wndcls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndcls.hCursor = LoadCursor(NULL,IDC_ARROW); wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndcls.hInstance = hInstance; wndcls.lpfnWndProc = WinSunProc; wndcls.lpszClassName = _T("sunxin2006"); wndcls.lpszMenuName = NULL; wndcls.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&wndcls); g_hInstance = hInstance; HWND hwnd = CreateWindow(ClassName,_T("helloworld"),WS_OVERLAPPEDWINDOW, 0,0,600,400,NULL,LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU)),hInstance,NULL); ShowWindow(hwnd,SW_SHOW); UpdateWindow(hwnd); MSG msg; while(GetMessage(&msg,NULL,0,0)>0) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } void OnCreate(HWND hwnd,WPARAM wParam,LPARAM lParam) { int scrWidth,scrHeight; RECT rect; //获得屏幕尺寸 scrWidth = GetSystemMetrics(SM_CXSCREEN); scrHeight = GetSystemMetrics(SM_CYSCREEN); //取得窗口尺寸 GetWindowRect(hwnd,&rect); //重新设置rect里的值 rect.left = (scrWidth-rect.right)/2; rect.top = (scrHeight-rect.bottom)/2; //移动窗口到指定的位置 SetWindowPos(hwnd,HWND_TOP,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW); } void OnComand(HWND hwnd,WPARAM wParam,LPARAM lParam) { WORD uID = LOWORD(wParam); switch(uID) { case ID_SETTING: { if(SettingMgr::GetIntance()->m_SettingWnd) { ShowWindow(SettingMgr::GetIntance()->m_SettingWnd,SW_SHOW); } else { SettingMgr::GetIntance()->m_SettingWnd = CreateWindow(ClassName, "子窗口", WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE|WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, hwnd, NULL, g_hInstance, NULL); ShowWindow(SettingMgr::GetIntance()->m_SettingWnd,SW_SHOW); } } break; } } VOID OnPaint(HWND hwnd,WPARAM wParam,LPARAM lParam) { PAINTSTRUCT ps; RECT rtClient; GetClientRect(hwnd,&rtClient); HDC hdc = BeginPaint(hwnd, &ps); HDC hMemDC = CreateCompatibleDC(hdc); HBITMAP hBitmap = CreateCompatibleBitmap(hdc, rtClient.right - rtClient.left, rtClient.bottom - rtClient.top);//rt为RECT变量; SelectObject(hMemDC, hBitmap); FillRect(hMemDC, &rtClient,WHITE_BRUSH); char strText[100]; if(hwnd == SettingMgr::GetIntance()->m_SettingWnd) { strcpy(strText,_T("我是子窗口!!!")); } else { strcpy(strText,_T("我是父窗口!!!")); } RECT rt={10,10,100,100}; DrawText(hMemDC,strText,strlen(strText),&rt,DT_LEFT|DT_TOP); BitBlt(hdc, 0, 0,rtClient.right - rtClient.left, rtClient.bottom - rtClient.top, hMemDC, 0, 0, SRCCOPY); DeleteDC(hMemDC); DeleteObject(hBitmap); ReleaseDC(hwnd,hdc); } LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch(uMsg) { case WM_CREATE: OnCreate(hwnd,wParam,lParam); break; case WM_COMMAND: OnComand(hwnd,wParam,lParam); break; case WM_PAINT: OnPaint(hwnd,wParam,lParam); break; case WM_CLOSE: if(hwnd == SettingMgr::GetIntance()->m_SettingWnd) { ShowWindow(SettingMgr::GetIntance()->m_SettingWnd,SW_HIDE); } else { DefWindowProc(hwnd,uMsg,wParam,lParam); } break; case WM_DESTROY: if(hwnd == SettingMgr::GetIntance()->m_SettingWnd) { } else { PostQuitMessage(0); } break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; }
SettingMgr.h
#pragma once #include<Windows.h> class SettingMgr { protected: static SettingMgr* _Intance; public: HWND m_SettingWnd; public: SettingMgr(void); ~SettingMgr(void); static SettingMgr* GetIntance(); };
SettingMgr.cpp
#include "SettingMgr.h" SettingMgr* SettingMgr::_Intance = new SettingMgr(); SettingMgr::SettingMgr(void):m_SettingWnd(NULL) { } SettingMgr::~SettingMgr(void) { } SettingMgr* SettingMgr::GetIntance() { return _Intance; }
由于例子很简单,所以用没用SettingMgr类效果不明显,如果结果比较麻烦,最好使用管理类。
注:修正一下错误,释放BeginPaint,需要调用EndPaint(hwnd,&ps),而不是ReleaseDC,失误了。。。抱歉。。。。
2、第二种方法,比较简单。创建时可以用不同的窗口类,注册时写一个另外的窗口函数。