#include<Windows.h>
#include<tchar.h>
#include"resource.h"
//全局变量
LPSTR g_MainFrame = "主框架";
LPSTR g_ClientFrame = "客户区框架";
LPSTR g_ChildFrame[] = { "子框架1","子框架2" };
//主窗口和子窗口回调函数,本程序子窗口公用一个子窗口回调函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ChildProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
//函数执行的入口函数
int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nShowCmd)
{
//1.初始化需要注册的窗口信息
WNDCLASS MainFrame = { 0 };
MainFrame.hbrBackground = (HBRUSH)::GetStockObject(GRAY_BRUSH);//背景
MainFrame.hCursor = ::LoadCursor(NULL, IDC_ARROW);
MainFrame.hInstance = hInstance;
MainFrame.lpfnWndProc = WndProc;
MainFrame.lpszClassName = g_MainFrame;
MainFrame.lpszMenuName = MAKEINTRESOURCE(IDR_MainFrame);//主菜单ID
MainFrame.style = CS_VREDRAW | CS_HREDRAW;
//2.注册MainFrame窗口类
if (!RegisterClass(&MainFrame))
{
MessageBox(NULL, _T("主框架注册失败!"), _T("Error"), MB_OK | MB_ICONERROR);//_T() 需用用到tchar.h头文件
}
//附:注册俩个子窗口类,在子窗口中通过类名来调度
MainFrame.lpfnWndProc = ChildProc;
MainFrame.lpszClassName = g_ChildFrame[0];
MainFrame.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
MainFrame.lpszMenuName = MAKEINTRESOURCE(IDR_ChildMenu);//子菜单
if (!RegisterClass(&MainFrame))
{
MessageBox(NULL, _T("子窗口1注册失败!"), _T("Error"), MB_OK | MB_ICONERROR);//_T() 需用用到tchar.h头文件
}
MainFrame.lpfnWndProc = ChildProc;
MainFrame.lpszClassName = g_ChildFrame[1];
MainFrame.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
MainFrame.lpszMenuName = MAKEINTRESOURCE(IDR_ChildMenu);;
if (!RegisterClass(&MainFrame))
{
MessageBox(NULL, _T("子窗口2注册失败!"), _T("Error"), MB_OK | MB_ICONERROR);//_T() 需用用到tchar.h头文件
}
//3.创建窗口
HWND mainframe_hwnd;
mainframe_hwnd= CreateWindow(
g_MainFrame,
g_MainFrame,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if(!mainframe_hwnd)
MessageBox(NULL, _T("主框架创建失败!"), _T("Error"), MB_OK | MB_ICONERROR);
//4.显示窗口
ShowWindow(mainframe_hwnd, nShowCmd);
//5.刷新窗口
UpdateWindow(mainframe_hwnd);
//6.信息捕获
MSG mainframe_msg;
while (::GetMessage(&mainframe_msg, NULL, 0, 0))
{
::TranslateMessage(&mainframe_msg);//TranslateMessage是用来把虚拟键消息转换为字符消息。
::DispatchMessage(&mainframe_msg);//消息调度
}
return mainframe_msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//处理消息
static HWND hClient = NULL,hChild=NULL;
static HINSTANCE hInstance = NULL;
CLIENTCREATESTRUCT cs = { 0 };
switch (message)
{
/*1.关不窗口时,会收到该消息,PostQuitMessage()像系统表明终止当前线程,没有这个函数的话,窗口不会关闭*/
case WM_DESTROY:
PostQuitMessage(0);//用于相应关闭消息,否则线程不会关闭,导致系统阻塞
return 0;
case WM_CREATE:
cs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 10);
cs.idFirstChild = 10;//第一个子窗口与之关联的菜单项ID
hInstance = GetModuleHandle(NULL);
hClient = CreateWindow(_T("MDICLIENT"), g_ClientFrame, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0,100,100,
hwnd, (HMENU)IDR_ClientMenu, hInstance, &cs);//第一个参数为MDICLIENT
if (!hClient)
MessageBox(NULL, _T("客户区创建失败!"), _T("Error"), MB_OK | MB_ICONERROR);
return 0;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case ID_MCS1:
{
//创建子窗口
MDICREATESTRUCT mcs = { 0 };
mcs.x = CW_USEDEFAULT;
mcs.y = CW_USEDEFAULT;
mcs.cx =CW_USEDEFAULT;
mcs.cy = CW_USEDEFAULT;//设置子窗口的大小
mcs.hOwner = hInstance;
mcs.style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN;//设置了为子窗口WS_CHILD
mcs.szClass = g_ChildFrame[0];
mcs.szTitle = g_ChildFrame[0];
hChild = (HWND)::SendMessage(hClient, WM_MDICREATE,
0, (LPARAM)(LPMDICREATESTRUCT)&mcs);
if (!hChild)
MessageBox(NULL, _T(" 子窗口创建失败!"), _T("Error"), MB_OK | MB_ICONERROR);
return 0;
}
return 0;
default: return 0;
}
}
return 0;
}
//将不需要处理的消息传递给系统作默认处理
return DefFrameProc(hwnd, hClient,message, wParam, lParam);
//return DefWindowProc(hwnd, message, wParam, lParam);在窗口程序中使用
}
LRESULT CALLBACK ChildProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hInstance;
HMENU hMenu, hSubMenu;
switch (message)
{
case WM_CREATE:
{
//关联对应的菜单,本程序只拥有一个菜单,如果想每个子文档关联不同的菜单也是可以的,最后需要重绘菜单 DrawMenu
hInstance = ::GetModuleHandle(NULL);
hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MainFrame));
hSubMenu = ::GetSubMenu(hMenu, 0);
SendMessage(GetParent(hwnd), WM_MDISETMENU, (WPARAM)hMenu, (LPARAM)hSubMenu);
}
return 0;
case WM_QUERYENDSESSION:
case WM_CLOSE:
{
if (IDOK == MessageBox(hwnd, _T("确定?"), _T("关闭"), MB_ICONQUESTION | MB_OK))
{
break;
}
}
return 0;
default:
break;
}
return DefMDIChildProc(hwnd, message, wParam, lParam);
}
注意:程序需要添加菜单资源,将本程序加黑的菜单ID更改为添加的菜单ID值。