Windows MDI编程
来源:互联网 发布:origin无法连接网络 编辑:程序博客网 时间:2024/05/18 01:57
一.windows MDI程序基本框架
一个多文档程序由一个框架窗口作为顶层父窗口,一个客户区窗口作为子窗口的容器,以及若干个子窗口也称文档窗口组成,其组织框架如上图所示。
二 . MDI核心API
一个窗口类:
MDICLIENT
二个数据结构:
CLIENTCREATESTRUCT
定义如下
typedef struct tagCLIENTCREATESTRUCT { // ccs HANDLE hWindowMenu; //与MDI子窗口关联的菜单 UINT idFirstChild; //第一个子窗口关联菜单的ID,以后每增加一个子窗口,在此值上+1} CLIENTCREATESTRUCT
MDICREATESTRUCT
定义如下,与CreateWindow窗口参数相对性
typedef struct tagMDICREATESTRUCT { // mdic LPCTSTR szClass; LPCTSTR szTitle; HANDLE hOwner; int x; int y; int cx; int cy; DWORD style; LPARAM lParam; } MDICREATESTRUCT;
五个函数
- DefFrameProc(框架窗口缺省返回)
- DefMDIChildProc(子窗口过程函数,缺省返回)
- TranslateMDISysAccel(快捷键处理)
- ArrangeIconicWindows(图标处理)
- CreateMDIWindows(一般用于多线程)
十二条消息
除了WM_MDICREATE以外,还有其它的MDI相关的窗口消息. 列表如下:
WM_MDIACTIVATE 这条消息由应用程序发送给客户窗口,告诉客户窗口激活所选择的MDI子窗口. 当客户窗口受到消息后,
它将激活所选择的MDI子窗口和发送WM_MDIACTIVATE消息给将被激活的子窗口和将变为非活动窗口的子窗口.
这条消息的用途是双方面的:应用程序可以用它来激活所希望的子窗口.同时它又可以被MDI子窗口本身用作活动/非活动窗口的指示器.举个例子,假如每一个MDI子窗口都有不同的菜单,
那么当它变为活动或是非活动窗口的时候,它可以利用这个机会来改变框架窗口的菜单 WM_MDICASCADE WM_MDITILE
WM_MDIICONARRANGE 这些消息处理如何排列MDI子窗口. 举个例子,
假如你希望MDI子窗口排列成层叠的样式,发送WM_MDICASCADE消息给客户窗口.
WM_MDIDESTROY 发送这条消息给客户窗口来关闭一个MDI子窗口. 你应该使用这条消息而不是调用DestroyWindow
因为假如这个MDI子窗口最大化的话, th这条消息将会恢复框架窗口的标题. 假如你使用DestroyWindow,
框架窗口的标题将不会被恢复. WM_MDIGETACTIVE 发送这条消息检索当前活动MDI子窗口的句柄. WM_MDIMAXIMIZE
WM_MDIRESTORE 发送 WM_MDIMAXIMIZE来最大化MDI子窗口和WM_MDIRESTORE来将它恢复成以前的状态.
对于这些操作总是使用这些消息. 假如你使用参数为SW_MAXIMIZE来调用ShowWindow时,MDI子窗口最大化并没有问题,
但是当你试图将它恢复成以前的状态时,问题就来了. 但是你可以用调用ShowWindow来最小化MDI子窗口.
WM_MDINEXT 发送这条消息给客户窗口,根据wParam和lParam里相应的值来激活下一个或是前一个MDI子窗口.
WM_MDIREFRESHMENU 发送这条消息给客户窗口来刷新框架窗口的菜单. 注意在发送了这条消息之后,
你必须调用DrawMenuBar 来更新菜单条.
WM_MDISETMENU 发送这条消息给客户窗口来取代框架窗口的整个菜单或是窗口子菜单. 你必须使用这条消息而不是用SetMenu.
在发送了这条消息之后, 你必须调用DrawMenuBar来更新菜单条.
正常情况下当活动的MDI子窗口有它自己的菜单而且你希望用这个活动的子窗口自身的菜单来取代框架窗口的菜单时,你将使用这条消息.一个简单的MDI例子,仅仅创建一个MDI窗口,不做任何处理,如果需要处理,请在处理子窗口对象的消息:
#include <windows.h>#include <tchar.h>#include "resource.h"LRESULT WINAPI FrameProc(HWND hFrame, UINT uMsg, WPARAM wParam, LPARAM lParam);LRESULT WINAPI ChildProc(HWND hFrame, UINT uMsg, WPARAM wParam, LPARAM lParam);void ShowError(TCHAR *pszErrorPos);//框架窗口类名TCHAR g_szFrameClsname[] = _T("FrameWnd");//应用程序名称TCHAR g_szAppName[] = _T("MDIDemo");//子窗口类名TCHAR g_szChildName[] = _T("Child");int WINAPI WinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPSTR lpCmdLine,_In_ int nShowCmd){MSG msg = { 0 };WNDCLASS wdFrame = { 0 };HWND hFrame = NULL;wdFrame.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);wdFrame.hCursor = ::LoadCursor(NULL, IDC_ARROW);wdFrame.hInstance = hInstance;wdFrame.lpfnWndProc = FrameProc;wdFrame.lpszClassName = g_szFrameClsname;wdFrame.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_FRAME);wdFrame.style = CS_VREDRAW | CS_HREDRAW;if (!RegisterClass(&wdFrame)){ShowError(_T("Registe FramClass"));return -1;}wdFrame.lpfnWndProc = ChildProc;wdFrame.lpszClassName = g_szChildName;wdFrame.lpszMenuName = NULL;if (!RegisterClass(&wdFrame)){ShowError(_T("Create Child"));return -1;}hFrame = CreateWindow(g_szFrameClsname, g_szAppName, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL);if (!hFrame){ShowError(_T("Create FrameWnd"));return - 1;}ShowWindow(hFrame, nShowCmd);UpdateWindow(hFrame);while (::GetMessage(&msg, NULL, 0, 0)){::TranslateMessage(&msg);::DispatchMessage(&msg);}return msg.wParam;}LRESULT WINAPI FrameProc(HWND hFrame, UINT uMsg, WPARAM wParam, LPARAM lParam){static HWND hClient, hChild;static HINSTANCE hInstance;switch (uMsg){case WM_CREATE:{//创建客户窗口CLIENTCREATESTRUCT ccs = { 0 };ccs.hWindowMenu = GetSubMenu(GetMenu(hFrame), 0);ccs.idFirstChild = 500;//第一个子窗口与之关联的菜单项IDhInstance = GetModuleHandle(NULL);hClient = CreateWindow(_T("MDICLIENT"), NULL, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,0, 0, 0, 0,hFrame, NULL, hInstance, &ccs);if (!hClient){ShowError(_T("Create Client"));return -1;}}return 0;case WM_SIZE:{MoveWindow(hClient, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);}return 0;case WM_COMMAND:{switch (LOWORD(wParam)){case ID_FILE_OPEN:{//创建子窗口MDICREATESTRUCT mcs = { 0 };mcs.x = CW_USEDEFAULT;mcs.y = CW_USEDEFAULT;mcs.cx = CW_USEDEFAULT;mcs.cy = CW_USEDEFAULT;mcs.hOwner = hInstance;mcs.style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN;mcs.szClass = g_szChildName;hChild = (HWND)::SendMessage(hClient, WM_MDICREATE,0, (LPARAM)(LPMDICREATESTRUCT)&mcs);if (!hChild){ShowError(_T("Create Child"));return -1;}}return 0;case ID_FILE_CLOSE:{}return 0;default:break;}}break;case WM_DESTROY:PostQuitMessage(0);return 0;default:break;}return DefFrameProc(hFrame, hClient, uMsg, wParam, lParam);}LRESULT WINAPI ChildProc(HWND hChild, UINT uMsg, WPARAM wParam, LPARAM lParam){static HINSTANCE hInstance;static HWND hClent;HMENU hMenu, hSubMenu;switch (uMsg){case WM_CREATE:{//关联对应的菜单,本程序只拥有一个菜单,如果想每个子文档关联不同的菜单也是可以的,最后需要重绘菜单 DrawMenuhInstance = ::GetModuleHandle(NULL);hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU_FRAME));hSubMenu = ::GetSubMenu(hMenu, 0);SendMessage(GetParent(hChild), WM_MDISETMENU, (WPARAM)hMenu, (LPARAM)hSubMenu);}return 0;case WM_QUERYENDSESSION:case WM_CLOSE:{if (IDOK == MessageBox(hChild, _T("OK to Close Windows?"), _T("CLose Windows"), MB_ICONQUESTION | MB_OK)){break;}}return 0;default:break;}return DefMDIChildProc(hChild, uMsg, wParam, lParam);}void ShowError(TCHAR *pszErrorPos){DWORD dwError = GetLastError();HLOCAL hLocal = NULL;TCHAR szError[255] = _T("");if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL, dwError, MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED),(LPWSTR)&hLocal, 0, NULL)){if (NULL != hLocal){wsprintf(szError, _T("%s Error is : %s"), pszErrorPos, LocalLock(hLocal));MessageBox(NULL, szError, _T("Error"), MB_OK | MB_ICONERROR);LocalFree(hLocal);return;}}}
- Windows编程之MDI
- Windows MDI编程
- Windows SDK编程--创建MDI窗口
- C#中的MDI编程
- Windows编程基础 第三章 基本窗口创建过程 MDI窗口创建
- Visual C#中的MDI编程
- MDI
- MDI
- Winform MDI编程-获得MDI窗体中的MDI控件的方法
- Windows SDK笔记(七):创建MDI窗口
- Windows SDK笔记(七):创建MDI窗口
- MDI编程常用窗体控制语句
- 深入MDI客户窗口编程及改进
- 浅谈MDI窗体的多窗体编程
- C#中的MDI编程实例讲解
- Windows应用程序C#创建MDI父窗体和子窗体
- [Windows应用程序]怎样建立winForm多文档窗口MDI
- 第九章. Windows窗体设计(MDI窗体,继承窗体)
- 决策树 学习
- leetcode 107. Binary Tree Level Order Traversal II BFS广度优先遍历
- 上下左右原地动画
- 《数字图像处理》MATLAB版笔记二
- 工业镜头的分类
- Windows MDI编程
- HDU 2363 Cycling 二分+ 限制最短路
- eclipse导出runnable jar包及资源读取
- ext6如何解决因由于面板里组件ID重复导致的报错
- 【源码】Enum
- java项目开发
- 计算机-第一作业-自我介绍
- 二叉查找树、平衡二叉树、红黑树、B-/B+树性能对比
- eclipse如何导出apk文件