.if lParam==0 ; 这条消息是由菜单产生的 mov eax,wParam .if ax==IDM_CASCADE ..... .elseif ax==IDM_TILEVERT ..... .else invoke DefFrameProc, hwndFrame, hwndClient, uMsg,wParam, lParam ret .endif 一般来说,你可以忽略未处理的消息. 但是在MDI的情况下,如果你忽略它们, 当用户点击窗口列表中的一个MDI子窗口的名称时,,这个窗口不会被激活. 你需要将这些消息传递给DefFrameProc 这样它们才会得到适当的处理.
idFirstChild 赋值的注意之处: 你不能使用0. 你窗口列表将会表现的不正常. 举个例子, 即使某一个MDI子窗口被激活的话, 窗口列表中的这个MDI子窗口名字前的复选标记也不会显现. 我们可以选择一个安全的值,比如100或是一个比100大的值.
给 CLIENTCREATESTRUCT 结构赋值后,你可以通过调用 CreateWindowEx 用预先注册好的类名"MDICLIENT", 在lParam中传递CLIENTCREATESTRUCT结构的地址来创建客户窗口. 你同样需要在hWndParent参数中指定框架窗口的句柄, 这样Windows才可以知道框架窗口和客户窗口之间的父-子关系. 你可以使用的窗口风格有:WS_CHILD ,WS_VISIBLEHE WS_CLIPCHILDREN . 假如你忘了WS_VISIBLE的话, 即使MDI子窗口成功地创建了,你也看不到它们.
以下是创建客户窗口的步骤:
获取你所希望显示窗口列表的子菜单的句柄. 将这个菜单句柄的值和你希望作为第一个MDI子窗口标识符的值一起传送给CLIENTCREATESTRUCT 结构. 调用 CreateWindowEx 用类名"MDICLIENT" ,lParam参数为CLIENTCREATESTRUCT结构的地址, 创建MDI子窗口 现在我们既有了框架窗口,也有了客户窗口. 下一阶段可以开始创建MDI子窗口了.有两种方法:
你可以发送 WM_MDICREATE消息给客户窗口,在wParam参数中传递类型MDICREATESTRUCT的结构的地址. 这是常用的也是最简单的MDI子窗口的创建方法. .data? mdicreate MDICREATESTRUCT <> .... .code ..... [fill the members of mdicreate] ...... invoke SendMessage, hwndClient, WM_MDICREATE,addr mdicreate,0 假如创建成功的话, SendMessage 将会返回新创建的MDI子窗口的句柄. 你并不需要保存这个句柄. 如果你需要的话, 你可以通过其它的方法来获得它. MDICREATESTRUCT有如下定义.
MDICREATESTRUCT STRUCT szClass DWORD ? szTitle DWORD ? hOwner DWORD ? x DWORD ? y DWORD ? lx DWORD ? ly DWORD ? style DWORD ? lParam DWORD ? MDICREATESTRUCT ENDS
szClass 你作为MDI自窗口模板的窗口类的地址 szTitle 你希望出现在子窗口的标题栏的文本的地址 hOwner 应用程序的例程句柄 x,y,lx,ly 子窗口的左上角的坐标以及宽度和高度 style 子窗口风格. 假若你用MDIS_ALLCHILDSTYLES创建子窗口的话,你可以使用任何窗口风格. lParam 一个应用程序定义的32位值. 这是在MDI窗口中共享值的一种方法. 如果你不需要它, 将它设为NULL.
你可以调用 CreateMDIWindow. 这一个功能具有下列语法: CreateMDIWindow proto lpClassName:DWORD lpWindowName:DWORD dwStyle:DWORD x:DWORD y:DWORD nWidth:DWORD nHeight:DWORD hWndParent:DWORD hInstance:DWORD lParam:DWORD 如果你仔细地看一下这些参数, 你将会发现它们和MDICREATESTRUCT结构的成员是相同的, 除了 hWndParent.以外. 本质上它和你用WM_MDICREATE传送的参数数目是相同的. MDICREATESTRUCT不需要hWndParent 域, 因为你必须用Sendmessage传送整个结构给正确的子窗口. .
在这里,你也许会有一些问题: 我应该使用哪一种方法? 在这两者之间有什么区别? 答案如下:
WM_MDICREATE方法创建的MDI子窗口作为调用代码是同一个线程.这意味这假如这个应用程序只有一个主线程的话, 所有的MDI子窗口都在这个主线程中运行. 这并不是一个大的问题. 但是如果一个或是多个你的MDI子窗口执行一些较长的操作的话, 问题就来了. 想象一下你的整个的应用程序突然之间停止了,对任何事情都没有反应, 一直持续到MDI子窗口的操作结束.
这个问题正是CreateMDIWindow 设计了所要解决的. CreateMDIWindow 为每一个MDI子窗口创建了一个单独的线程. 这样假如一个MDI子窗口忙的话, 它不会拖累整个应用程序..
有关MDI子窗口的窗口过程还有一点需要说明的地方. 对于框架窗口, 你不能调用DefWindowProc来处理未处理的消息. 与之相反你必须在自窗口的窗口过程中使用DefMDIChildProc . 这个函数具有和DefWindowProc相同的参数.
除了WM_MDICREATE以外,还有其它的MDI相关的窗口消息. 列表如下:
WM_MDIACTIVATE 这条消息由应用程序发送给客户窗口,告诉客户窗口激活所选择的MDI子窗口. 当客户窗口受到消息后, 它将激活所选择的MDI子窗口和发送WM_MDIACTIVATE消息给将被激活的子窗口和将变为非活动窗口的子窗口. 这条消息的用途是双方面的:应用程序可以用它来激活所希望的子窗口.同时它又可以被MDI子窗口本身用作活动/非活动窗口的指示器.举个例子,假如每一个MDI子窗口都有不同的菜单, 那么当它变为活动或是非活动窗口的时候,它可以利用这个机会来改变框架窗口的菜单
上一篇:树型视图控件
下一篇:Win32调试API 第一部分
|