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

来源:互联网 发布:windows程序设计epub 编辑:程序博客网 时间:2024/05/16 05:23

 窗口(框架/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 50000LRESULT 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);}




 

原创粉丝点击