窗口客户区和视图客户区的区别

 窗口(框架/frame)的客户区和视图(view)的客户区的区别?

这些都是初学者很容易迷惑的地方,我也是很迷惑,不过经过一番折腾终于弄明白这些问题了.对于这些问题,我想只用两个图片来说明最直观!如下:

1,在一个MDI(多文档)应用程序中每个概念如下图所标示:


效果如下图


1,窗口框架的客户区就是指图中的灰色部分:即蓝色方框内区域,框架的非客户区就是指蓝色方框之外的窗口区域,包括程序图标,标题栏,菜单,最大最小/关闭按纽,左右两个框和底下的状态条.

2,视图的客户区就是指图中绿色部分:即红色方框内的区域,视图的非客户区就是指视图部分红色方框之外的区域,包括:文件图标,标题栏,三个按纽和两个滚动条.

3,从图中可以看出,工具栏(工具条)不属于框架的非客户区,它跟视图是框架客户区内的"兄弟".它也是一个窗口,

**************************************

一个MDI的应用拥有下面三种窗口:框架窗口(frame window),MDI客户区窗口(MDI client window,即上图2中蓝色框,注意它也是一个窗口,故需要创建,在内存中药分配空间的,以句柄返回)以及一些子窗口(child window)。

框架窗口就像应用的主窗口,它的外观就是我们看到的拥有边框、标题栏、窗口菜单的那个窗口。

MDI应用并不使用框架窗口的客户区来直接输出,而是用客户区来显示MDI客户区窗口。这是一种特殊类型的子窗口,预先以窗口类名MDICLIENT注册过。它是框架窗口的一个子窗口,作为其他子窗口的背景而起作用,还提供创建和操纵其他子窗口的支持。例如,一个MDI的应用可以通过发送消息给MDI client window来创建、激活或者最大化子窗口。

当用户打开或者创建一个文档,客户区窗口为这个文档创建一个子窗口,它本身是所有其他子窗口的父窗口。所有的子窗口依附于客户区窗口,不能超出它的大小。

为了创建一个子窗口,一个MDI应用可以有两种选择,调用CreateMDIWindow()或者向MDI客户区窗口发送WM_MDICREATE消息。一种更有效地的方法是调用CreateWindowEx(),指定WS_EX_MDICHILD扩展风格。一个MDI应用中的线程可以使用CreateMDIWindow()或者CreateWindowEx()来创建另一个线程中的子窗口,而
WM_MDICREATE消息只是在同一线程中才能使用。

#include <Windows.h>
#include "resource.h"

#define INIT_MENU_POS 0
#define RECT_MENU_POS 1
#define HELLO_MENU_POS 2

#define IDM_FIRSTCHILD 50000

LRESULT CALLBACK FrameWndProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK HelloWndProc(HWND,UINT,WPARAM,LPARAM);
BOOL CALLBACK CloseEnumProc(HWND,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_HREDRAW | CS_VREDRAW;
	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 ;
	}

	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.lpfnWndProc = RectWndProc;
	wndclass.lpszClassName = szRectClass;
	RegisterClass(&wndclass);

	hAccel = LoadAccelerators(hInst,szAppName);
	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);

	hwndFrame = CreateWindow(szFrameClass,TEXT("MDI Demonstration"),WS_OVERLAPPEDWINDOW |
		WS_CLIPCHILDREN,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,
		hMenuInit,hInstance,NULL);
	//因为已经将WM_CREATE消息直接发送到了窗口函数,故hwndClient = CreateWindow(TEXT("MDICLIENT"),NULL,WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,0,0,0,0,hwnd,(HMENU)1,hInst,(PSTR)&clientcreate);执行了。
	//所以下面能够正确获取MDI Client Window句柄
	hwndClient = GetWindow(hwndFrame,GW_CHILD);

	ShowWindow(hwndFrame,iCmdShow);
	UpdateWindow(hwndFrame);

	while(GetMessage(&msg,NULL,0,0))
	{
		if(!TranslateMDISysAccel(hwndClient,&msg) && !TranslateAccelerator(hwndFrame,hAccel,&msg))
		{		
			TranslateMessage(&msg);
			DispatchMessage(&msg);		
		}
	}
	
	DestroyMenu(hMenuHello);
	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:
		clientcreate.hWindowMenu = hMenuInitWindow;
		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);//"MDICLIENT"是预定义的类,
		return 0;
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		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;

			hwndChild = (HWND)SendMessage(hwndClient,WM_MDICREATE,0,(LPARAM)(LPMDICREATESTRUCT)&mdicreate);//SendMessage消息的处理结果依赖于所发送的消息。
			return 0;
		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;

			SendMessage(hwndClient,WM_MDICREATE,0,(LPARAM)&mdicreate);
			return 0;
		case IDM_FILE_CLOSE:
			hwndChild = (HWND)SendMessage(hwndClient,WM_MDIGETACTIVE,0,0);
			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_CASCADE:
			SendMessage(hwndClient,WM_MDICASCADE,0,0);
			return 0;
		case IDM_WINDOW_TILE:
			SendMessage(hwndClient,WM_MDITILE,0,0);
			return 0;
		case IDM_WINDOW_ARRANGE:
			SendMessage(hwndClient,WM_MDIICONARRANGE,0,0);
			return 0;
		case IDM_WINDOW_CLOSEALL:
			EnumChildWindows(hwndClient,CloseEnumProc,0);
			return 0;
		default:
			hwndChild = (HWND)SendMessage(hwndClient,WM_MDIGETACTIVE,0,0);
			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,0,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_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_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_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;
	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);
		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_MDIACTIVATE:
		if((LPARAM)hwnd == lParam)
		{
			SendMessage(hwndClient,WM_MDISETMENU,(WPARAM)hMenuRect,(LPARAM)hMenuRectWindow);
		}
		else
		{
			SendMessage(hwndClient,WM_MDISETMENU,(WPARAM)hMenuInit,(LPARAM)hMenuInitWindow);
		}
		DrawMenuBar(GetParent(hwndClient));
		return 0;
	case WM_PAINT:                     
        InvalidateRect (hwnd, NULL, TRUE) ;
        hdc = BeginPaint (hwnd, &ps) ;
        EndPaint (hwnd, &ps) ;
        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);
}




 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值