windows程序设计——多重文件介面
来源:互联网 发布:米尔斯海默 知乎 编辑:程序博客网 时间:2024/06/05 21:52
简单地说,就像Windows 在一个萤幕上维护多个应用程式视窗一样,MDI 应用程式在一个显示区域内维护多个文件视窗。
框架窗口与客户窗口显示如下:
每个窗口激活时会对应各自的菜单:
frame,clientwind,childwind关系如下:
以上窗口的实现如下:
/*-------------------------------------------------------- MDIDEMO.C -- Multiple-Document Interface Demonstration (c) Charles Petzold, 1998 --------------------------------------------------------*/#include <windows.h>#include "resource.h"//window菜单在主菜单中的index,打开的文件列表会被系统添加到这个菜单下#define INIT_MENU_POS 0#define HELLO_MENU_POS 2#define RECT_MENU_POS 1//文件列表中第一个文件对应的ID,用于wm_command中显示对应的文件窗口#define IDM_FIRSTCHILD 50000//框架回调LRESULT CALLBACK FrameWndProc (HWND, UINT, WPARAM, LPARAM) ;//关闭所有文件窗口时的回调BOOL CALLBACK CloseEnumProc (HWND, LPARAM) ;//hello文件窗口回调LRESULT CALLBACK HelloWndProc (HWND, UINT, WPARAM, LPARAM) ;//画矩形窗口的回调LRESULT CALLBACK RectWndProc (HWND, UINT, WPARAM, LPARAM) ;// structure for storing data unique to each Hello child windowtypedef struct tagHELLODATA{ UINT iColor ; COLORREF clrText ;}HELLODATA, * PHELLODATA ;// structure for storing data unique to each Rect child windowtypedef struct tagRECTDATA{ short cxClient ; short cyClient ;}RECTDATA, * PRECTDATA ;// global variablesTCHAR szAppName[] = TEXT ("MDIDemo") ;TCHAR szFrameClass[] = TEXT ("MdiFrame") ;TCHAR szHelloClass[] = TEXT ("MdiHelloChild") ;TCHAR szRectClass[] = TEXT ("MdiRectChild") ;//应用句柄,三个菜单,并三个菜单中附带的window菜单项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 ; // Register the frame window class 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 ; } // Register the Hello child window class 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) ; // Register the Rect child window class wndclass.style = CS_HREDRAW | CS_VREDRAW ; 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) ; // Obtain handles to three possible menus & submenus hMenuInit = LoadMenu (hInstance, TEXT ("MdiMenuInit")) ; hMenuHello = LoadMenu (hInstance, TEXT ("MdiMenuHello")) ; hMenuRect = LoadMenu (hInstance, TEXT ("MdiMenuRect")) ; //虽然hMenuInitWindow存在,但是只有在所有文件都被关闭的时候才显示在hMenuInitWindow后个数永远为0 hMenuInitWindow = GetSubMenu (hMenuInit, INIT_MENU_POS) ; hMenuHelloWindow = GetSubMenu (hMenuHello, HELLO_MENU_POS) ; hMenuRectWindow = GetSubMenu (hMenuRect, RECT_MENU_POS) ; // Load accelerator table hAccel = LoadAccelerators (hInstance, szAppName) ; // Create the frame window,会在这个过程里边收到wm_create消息创建client_windows hwndFrame = CreateWindow (szFrameClass, TEXT ("MDI Demonstration"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, hMenuInit, hInstance, NULL) ; //获得在wm_create消息中创建的client_windows hwndClient = GetWindow (hwndFrame, GW_CHILD) ; ShowWindow (hwndFrame, iCmdShow) ; UpdateWindow (hwndFrame) ; // Enter the modified message loop while (GetMessage (&msg, NULL, 0, 0)) { //需要先经过两个转化 if (!TranslateMDISysAccel (hwndClient, &msg) && !TranslateAccelerator (hwndFrame, hAccel, &msg)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } } // Clean up by deleting unattached menus DestroyMenu (hMenuHello) ; DestroyMenu (hMenuRect) ; return msg.wParam ;}//frame处理回调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: // Create the client window //设置hWindowMenu和idFirstChild 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) ; return 0 ; case WM_COMMAND: switch (LOWORD (wParam)) { case IDM_FILE_NEWHELLO: // Create a Hello child window //设置CLIENTCREATESTRUCT中的字段 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 ; //给client窗口发送WM_MDICREATE消息创建HelloClass类型的子窗口 hwndChild = (HWND) SendMessage (hwndClient, WM_MDICREATE, 0, (LPARAM) (LPMDICREATESTRUCT) &mdicreate) ; return 0 ; case IDM_FILE_NEWRECT: // Create a Rect child window //设置CLIENTCREATESTRUCT中的字段 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 ; //给client窗口发送WM_MDICREATE消息创建RectClass类型的子窗口 hwndChild = (HWND) SendMessage (hwndClient, WM_MDICREATE, 0, (LPARAM) (LPMDICREATESTRUCT) &mdicreate) ; return 0 ; case IDM_FILE_CLOSE: // Close the active window //先获取当前活动窗口的句柄 hwndChild = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, 0, 0) ; // 先看是否能被关闭,再给client发送WM_MDIDESTROY销毁参数中指定的窗体 if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0)) SendMessage (hwndClient, WM_MDIDESTROY, (WPARAM) hwndChild, 0) ; return 0 ; case IDM_APP_EXIT: // Exit the program SendMessage (hwnd, WM_CLOSE, 0, 0) ; return 0 ; // 三种排列的情况,直接由client去处理 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: // Attempt to close all children //遍历client窗口的所有子窗口,并对每个子窗口调用CloseEnumProc(若返回值为true就继续遍历否则退出遍历) EnumChildWindows (hwndClient, CloseEnumProc, 0) ; return 0 ; default: // 其他WM_COMMAND消息交给子窗口 hwndChild = (HWND) SendMessage (hwndClient, WM_MDIGETACTIVE, 0, 0) ; if (IsWindow (hwndChild)) SendMessage (hwndChild, WM_COMMAND, wParam, lParam) ; break ; // ...and then to DefFrameProc } break ; case WM_QUERYENDSESSION: case WM_CLOSE: // Attempt to close all children //主框架关闭的时候先关闭所有的子窗口 SendMessage (hwnd, WM_COMMAND, IDM_WINDOW_CLOSEALL, 0) ; //当client还有子窗口的时候不关闭 if (NULL != GetWindow (hwndClient, GW_CHILD)) return 0 ; break ; // i.e., call DefFrameProc case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } // Pass unprocessed messages to DefFrameProc (not DefWindowProc) return DefFrameProc (hwnd, hwndClient, message, wParam, lParam) ;}BOOL CALLBACK CloseEnumProc (HWND hwnd, LPARAM lParam){ if (GetWindow (hwnd, GW_OWNER)) // Check for icon title return TRUE ; //发送WM_MDIRESTORE恢复原状 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 ;}//hello文件窗口回调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 // Allocate memory for window private data 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) ; // Save some window handles hwndClient = GetParent (hwnd) ; hwndFrame = GetParent (hwndClient) ; return 0 ; case WM_COMMAND: //处理frame转发过来的菜单消息 switch (LOWORD (wParam)) { case IDM_COLOR_BLACK: case IDM_COLOR_RED: case IDM_COLOR_GREEN: case IDM_COLOR_BLUE: case IDM_COLOR_WHITE: // Change the text color // 获得各个窗口自己的PHELLODATA数据 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: // Paint the window 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: // Set the Hello menu if gaining focus if (lParam == (LPARAM) hwnd) SendMessage (hwndClient, WM_MDISETMENU, (WPARAM) hMenuHello, (LPARAM) hMenuHelloWindow) ; // Check or uncheck menu item pHelloData = (PHELLODATA) GetWindowLong (hwnd, 0) ; CheckMenuItem (hMenuHello, pHelloData->iColor, (lParam == (LPARAM) hwnd) ? MF_CHECKED : MF_UNCHECKED) ; // Set the Init menu if losing focus 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 ; // i.e., call DefMDIChildProc case WM_DESTROY: pHelloData = (PHELLODATA) GetWindowLong (hwnd, 0) ; HeapFree (GetProcessHeap (), 0, pHelloData) ; return 0 ; } // Pass unprocessed message to DefMDIChildProc 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: // Allocate memory for window private data pRectData = (PRECTDATA) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof (RECTDATA)) ; SetWindowLong (hwnd, 0, (long) pRectData) ; // Start the timer going SetTimer (hwnd, 1, 250, NULL) ; // Save some window handles hwndClient = GetParent (hwnd) ; hwndFrame = GetParent (hwndClient) ; return 0 ; case WM_SIZE: // If not minimized, save the window size if (wParam != SIZE_MINIMIZED) { pRectData = (PRECTDATA) GetWindowLong (hwnd, 0) ; pRectData->cxClient = LOWORD (lParam) ; pRectData->cyClient = HIWORD (lParam) ; } break ; // WM_SIZE must be processed by DefMDIChildProc case WM_TIMER: // Display a random rectangle 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: // Clear the window InvalidateRect (hwnd, NULL, TRUE) ; hdc = BeginPaint (hwnd, &ps) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_MDIACTIVATE: // Set the appropriate menu 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 ; } // Pass unprocessed message to DefMDIChildProc return DefMDIChildProc (hwnd, message, wParam, lParam) ;}
阅读全文
0 0
- windows程序设计——多重文件介面
- Windows程式开发设计指南(十九)多重文件介面
- Windows程序设计:文件操作
- 《windows程序设计》选择文件
- 《Windows程序设计》——字符集
- windows程序设计——CreateProcess()
- Windows程序设计——GetObject
- windows程序设计——键盘
- windows程序设计——鼠标
- windows程序设计——计时器
- 谁偷了我的启动文件?——Windows多重引导故障快速修复(转)
- Windows程序设计:菜单打开文件
- windows程序设计——飞机大战笔记(单文档文件登陆界面)
- linux程序设计—文件操作
- Windows程序设计——终止进程运行
- 《汇编语言程序设计》——仿windows计算器
- 《Windows程序设计》笔记 —— Chapter One
- 《Windows程序设计》笔记 —— Chapter Two
- 转:私有云架构图
- 06_高级painter、保存、打印、预览
- Mina实时框架的使用
- MongoDB基本的操作及C接口使用-MongoDB C Driver
- 树莓派(Raspberry Pi 3)
- windows程序设计——多重文件介面
- (6) JDBC的CallableStatement对象使用
- Spark编程指南
- Unix时间与Excel时间转换
- 决策树转规则
- 牛客网-剑指offer
- Ubuntu64位下搭建javaWeb小型服务器
- vue2.0 axios前后端数据处理
- 大学回忆录