#include <Windows.h>
#include "RESOURCE.H"
#define INIT_MENU_POS 0
#define HELLO_MENU_POS 2
#define RECT_MENU_POS 1
#define IDM_FIRSTCHILD 50000
//多个回调函数
LRESULT CALLBACK FrameWndProc(HWND,UINT,WPARAM,LPARAM);
BOOL CALLBACK CloseEnumProc(HWND,LPARAM);
LRESULT CALLBACK HelloWndProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK RectWndProc(HWND,UINT,WPARAM,LPARAM);
//两个结构体
typedef struct tagHELLODATA
{
UINT iColor;
COLORREF clrText;
}
HELLODATA,*PHELLODATA;
typedef struct tagRECTDATA
{
short cxClient;
short cyClient;
}
RECTDATA,*PRECTDATA;
//四个标题
TCHAR szAppName[]=TEXT("MDIDemo");
TCHAR szFrameClass[]=TEXT("MdiFrame");
TCHAR szHelloClass[]=TEXT("MdiHelloChild");
TCHAR szRectClass[]=TEXT("MdiRectChild");
//全局句柄
HINSTANCE hInst;
//全局变量
HMENU hMenuInit,hMenuHello,hMenuRect;
HMENU hMenuInitWindow,hMenuHelloWindow,hMenuRectWindow;
//入口函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
HACCEL hAccel;
HWND hwndFrame,hwndClient;
MSG msg;
WNDCLASS wndclass;
hInst=hInstance;
//主窗口注册
wndclass.style=CS_VREDRAW|CS_HREDRAW;
wndclass.lpfnWndProc=FrameWndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)(COLOR_APPWORKSPACE+1);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szFrameClass;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR);
return 0;
}
//Hello窗口注册
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=HelloWndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=sizeof(HANDLE);
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szHelloClass;
RegisterClass(&wndclass);
//矩形窗口注册
wndclass.style=CS_VREDRAW|CS_HREDRAW;
wndclass.lpfnWndProc=RectWndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=sizeof(HANDLE);
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szRectClass;
RegisterClass(&wndclass);
//载入三个菜单资源(这个是横向的,就是客户区上方那一行),获取句柄
hMenuInit=LoadMenu(hInstance,TEXT("MdiMenuInit"));
hMenuHello=LoadMenu(hInstance,TEXT("MdiMenuHello"));
hMenuRect=LoadMenu(hInstance,TEXT("MdiMenuRect"));
//返回下拉菜单句柄
hMenuInitWindow=GetSubMenu(hMenuInit,INIT_MENU_POS);
hMenuHelloWindow=GetSubMenu(hMenuHello,HELLO_MENU_POS);
hMenuRectWindow=GetSubMenu(hMenuRect,RECT_MENU_POS);
//调用指定的加速键表,可打开资源文件查看键表
hAccel=LoadAccelerators(hInstance,szAppName);
//创建主窗口
hwndFrame=CreateWindow(szFrameClass,TEXT("MDI Demonstration"),WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,hMenuInit,hInstance,NULL);
//检查指定窗口的子窗口
hwndClient=GetWindow(hwndFrame,GW_CHILD);
ShowWindow(hwndFrame,iCmdShow);
UpdateWindow(hwndFrame);
////////////////////////////////////////////////////////////////////
//TranslateMDISysAccel该函数处理与指定MDI客户窗口相联系的多文档接口(MDI)子窗口的菜单命令的加速键响应
//返回值:如果消息被转换为系统命令,则返回值为非零值。如果消息未转换为系统命令,则返回值为0。
//TranslateAccelerator翻译加速键表
////////////////////////////////////////////////////////////////////
while(GetMessage(&msg,NULL,0,0))
{
if(!TranslateMDISysAccel(hwndClient,&msg)&&!TranslateAccelerator(hwndFrame,hAccel,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
//清理工作
DestroyMenu(hMenuHello);
DestroyMenu(hMenuRect);
return msg.wParam;
}
//窗口的回调函数
LRESULT CALLBACK FrameWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static HWND hwndClient;
//客户区创建结构体
CLIENTCREATESTRUCT clientcreate;
HWND hwndChild;
//子窗口创建结构体
MDICREATESTRUCT mdicreate;
switch(message)
{
case WM_CREATE:
//创建时,设置资源菜单为hMenuInitWindow
clientcreate.hWindowMenu=hMenuInitWindow;
//设置主窗口客户区的ID
clientcreate.idFirstChild=IDM_FIRSTCHILD;
//创建
hwndClient=CreateWindow(TEXT("MDICLIENT"),NULL,WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE,0,0,
0,0,hwnd,(HMENU)1,hInst,(PSTR)&clientcreate);
return 0;
//点击菜单栏相应操作
case WM_COMMAND:
switch(LOWORD(wParam))
{
//点击NewHello后,填充结构体MDICREATESTRUCT
case IDM_FILE_NEWHELLO:
mdicreate.szClass=szHelloClass;
mdicreate.szTitle=TEXT("Hello");
mdicreate.hOwner=hInst;
mdicreate.x=CW_USEDEFAULT;
mdicreate.y=CW_USEDEFAULT;
mdicreate.cx=CW_USEDEFAULT;
mdicreate.cy=CW_USEDEFAULT;
mdicreate.style=0;
mdicreate.lParam=0;
//发送消息给hwndClient(hwndClient是客户区句柄,也可以说是一个子窗口句柄)
hwndChild=(HWND)SendMessage(hwndClient,WM_MDICREATE,0,(LPARAM)(LPMDICREATESTRUCT)&mdicreate);
return 0;
//点击NewRect后,填充结构体MDICREATESTRUCT
case IDM_FILE_NEWRECT:
mdicreate.szClass=szRectClass;
mdicreate.szTitle=TEXT("Rectangles");
mdicreate.hOwner=hInst;
mdicreate.x=CW_USEDEFAULT;
mdicreate.y=CW_USEDEFAULT;
mdicreate.cx=CW_USEDEFAULT;
mdicreate.cy=CW_USEDEFAULT;
mdicreate.style=0;
mdicreate.lParam=0;
//发送消息给hwndClient(hwndClient是客户区句柄,也可以说是一个子窗口句柄)发送的消息为WM_MDICREATE
hwndChild=(HWND)SendMessage(hwndClient,WM_MDICREATE,0,(LPARAM)(LPMDICREATESTRUCT)&mdicreate);
return 0;
case IDM_FILE_CLOSE:
//发送消息给hwndClient,发送的消息为WM_MDIGETACTIVE
hwndChild=(HWND)SendMessage(hwndClient,WM_MDIGETACTIVE,0,0);
//当结束或者一个程序调用系统关闭功能的时候,WM_QUERYENDSESSION消息会被发送给尚未终止的所有窗口。
//当程序在处理这个消息的时候,如果返回了false(0),那么系统将不结束对话或者关机(注销)。
//这个地方就是发送一个WM_QUERYENDSESSION,返回非0的话,就发送一个WM_MDIDESTROY消息
if(SendMessage(hwndChild,WM_QUERYENDSESSION,0,0))
SendMessage(hwndClient,WM_MDIDESTROY,(WPARAM)hwndChild,0);
return 0;
//下面这些是点击一些菜单时,所进行的操作
case IDM_APP_EXIT:
SendMessage(hwnd,WM_CLOSE,0,0);
return 0;
case IDM_WINDOW_TILE:
SendMessage(hwndClient,WM_MDITILE,0,0);
return 0;
case IDM_WINDOW_CASCADE:
SendMessage(hwndClient,WM_MDICASCADE,0,0);
return 0;
case IDM_WINDOW_ARRANGE:
SendMessage(hwndClient,WM_MDIICONARRANGE,0,0);
return 0;
case IDM_WINDOW_CLOSEALL:
//枚举一个父窗口的所有子窗口,CloseEnumProc回调函数地址
EnumChildWindows(hwndClient,CloseEnumProc,0);
return 0;
//如果点击其它地方,就是设为活动的
default:
hwndChild=(HWND)SendMessage(hwndClient,WM_MDIGETACTIVE,0,0);
//如果是子窗口,就向子窗口发送一个WM_COMMAND的消息
if(IsWindow(hwndChild))
SendMessage(hwndChild,WM_COMMAND,wParam,lParam);
break;
}
break;
case WM_QUERYENDSESSION:
case WM_CLOSE:
SendMessage(hwnd,WM_COMMAND,IDM_WINDOW_CLOSEALL,0);
if(NULL!=GetWindow(hwndClient,GW_CHILD))
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefFrameProc(hwnd,hwndClient,message,wParam,lParam);
}
BOOL CALLBACK CloseEnumProc(HWND hwnd,LPARAM lParam)
{
//获取指定窗口的所有者窗口
//这一块不明白什么意思,以后再想
if(GetWindow(hwnd,GW_OWNER))
return TRUE;
SendMessage(GetParent(hwnd),WM_MDIRESTORE,(WPARAM)hwnd,0);
if(!SendMessage(hwnd,WM_QUERYENDSESSION,(WPARAM)hwnd,0))
return TRUE;
SendMessage(GetParent(hwnd),WM_MDIDESTROY,(WPARAM)hwnd,0);
return TRUE;
}
//下面的注释加不加去了,不理解,以后再看
LRESULT CALLBACK HelloWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static COLORREF clrTextArray[]={RGB(0,0,0),RGB(255,0,0),RGB(0,255,0),RGB(0,0,255),RGB(255,255,255)};
static HWND hwndClient,hwndFrame;
HDC hdc;
HMENU hMenu;
PHELLODATA pHelloData;
PAINTSTRUCT ps;
RECT rect;
switch(message)
{
case WM_CREATE:
pHelloData=(PHELLODATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(HELLODATA));
pHelloData->iColor=IDM_COLOR_BLACK;
pHelloData->clrText=RGB(0,0,0);
SetWindowLong(hwnd,0,(LONG)pHelloData);
hwndClient=GetParent(hwnd);
hwndFrame=GetParent(hwndClient);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_COLOR_BLACK:
case IDM_COLOR_RED:
case IDM_COLOR_GREEN:
case IDM_COLOR_BLUE:
case IDM_COLOR_WHITE:
pHelloData=(PHELLODATA)GetWindowLong(hwnd,0);
hMenu=GetMenu(hwndFrame);
CheckMenuItem(hMenu,pHelloData->iColor,MF_UNCHECKED);
pHelloData->iColor=wParam;
CheckMenuItem(hMenu,pHelloData->iColor,MF_CHECKED);
pHelloData->clrText=clrTextArray[wParam-IDM_COLOR_BLACK];
InvalidateRect(hwnd,NULL,FALSE);
}
return 0;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
pHelloData=(PHELLODATA)GetWindowLong(hwnd,0);
SetTextColor(hdc,pHelloData->clrText);
GetClientRect(hwnd,&rect);
DrawText(hdc,TEXT("Hello,World!"),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hwnd,&ps);
return 0;
case WM_MDIACTIVATE:
if(lParam==(LPARAM)hwnd)
SendMessage(hwndClient,WM_MDISETMENU,(WPARAM)hMenuHello,(LPARAM)hMenuHelloWindow);
pHelloData=(PHELLODATA)GetWindowLong(hwnd,0);
CheckMenuItem(hMenuHello,pHelloData->iColor,(lParam==(LPARAM)hwnd)?MF_CHECKED:MF_UNCHECKED);
if(lParam!=(LPARAM)hwnd)
SendMessage(hwndClient,WM_MDISETMENU,(WPARAM)hMenuInit,(LPARAM)hMenuInitWindow);
DrawMenuBar(hwndFrame);
return 0;
case WM_QUERYENDSESSION:
case WM_CLOSE:
if(IDOK!=MessageBox(hwnd,TEXT("OK to close window!"),TEXT("Hello"),MB_ICONQUESTION|MB_OKCANCEL))
return 0;
break;
case WM_DESTROY:
pHelloData=(PHELLODATA)GetWindowLong(hwnd,0);
HeapFree(GetProcessHeap(),0,pHelloData);
return 0;
}
return DefMDIChildProc(hwnd,message,wParam,lParam);
}
LRESULT CALLBACK RectWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static HWND hwndClient,hwndFrame;
HBRUSH hBrush;
HDC hdc;
PRECTDATA pRectData;
PAINTSTRUCT ps;
int xLeft,xRight,yTop,yBottom;
short nRed,nGreen,nBlue;
switch(message)
{
case WM_CREATE:
pRectData=(PRECTDATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(RECTDATA));
SetWindowLong(hwnd,0,(long)pRectData);
SetTimer(hwnd,1,250,NULL);
hwndClient=GetParent(hwnd);
hwndFrame=GetParent(hwndClient);
return 0;
case WM_SIZE:
if(wParam!=SIZE_MINIMIZED)
{
pRectData=(PRECTDATA)GetWindowLong(hwnd,0);
pRectData->cxClient=LOWORD(lParam);
pRectData->cyClient=HIWORD(lParam);
}
break;
case WM_TIMER:
pRectData=(PRECTDATA)GetWindowLong(hwnd,0);
xLeft=rand()%pRectData->cxClient;
xRight=rand()%pRectData->cxClient;
yTop=rand()%pRectData->cyClient;
yBottom=rand()%pRectData->cyClient;
nRed=rand()&255;
nGreen=rand()&255;
nBlue=rand()&255;
hdc=GetDC(hwnd);
hBrush=CreateSolidBrush(RGB(nRed,nGreen,nBlue));
SelectObject(hdc,hBrush);
Rectangle(hdc,min(xLeft,xRight),min(yTop,yBottom),max(xLeft,xRight),max(yTop,yBottom));
ReleaseDC(hwnd,hdc);
DeleteObject(hBrush);
return 0;
case WM_PAINT:
InvalidateRect(hwnd,NULL,TRUE);
hdc=BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return 0;
case WM_MDIACTIVATE:
if(lParam==(LPARAM)hwnd)
SendMessage(hwndClient,WM_MDISETMENU,(WPARAM)hMenuRect,(LPARAM)hMenuRectWindow);
else
SendMessage(hwndClient,WM_MDISETMENU,(WPARAM)hMenuInit,(LPARAM)hMenuInitWindow);
DrawMenuBar(hwndFrame);
return 0;
case WM_DESTROY:
pRectData=(PRECTDATA)GetWindowLong(hwnd,0);
HeapFree(GetProcessHeap(),0,pRectData);
KillTimer(hwnd,1);
return 0;
}
return DefMDIChildProc(hwnd,message,wParam,lParam);
}
前面有三章只是大体看了下,没有写代码,先放一下吧,这个是多文档的,也有一些不理解的东西,在这很有纪念意义的时间,6.1,开始我觉得用处很大的多任务和多线程了。