《Windows程序设计》之多文档

#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,开始我觉得用处很大的多任务和多线程了。

你可能感兴趣的:(windows,command,null,application,callback,menu)