窗体切换问题,难者不会,会者不难.请高手赐教(50分)

  • 主题发起人 主题发起人 levi
  • 开始时间 开始时间
L

levi

Unregistered / Unconfirmed
GUEST, unregistred user!
为把问题描述清楚,写点有点具体,请高手耐心看完哦 ^_^<br>protected<br> &nbsp;procedure CreateParams(var Params: TCreateParams); override;<br><br>Procedure CreateParams(Var Params: TCreateParams);<br>Begin<br> &nbsp;Inherited CreateParams(Params);<br> &nbsp;With Params Do begin<br> &nbsp; &nbsp;exStyle := exStyle or WS_EX_APPWINDOW;<br> end;<br>end;<br><br>我在一个子窗体中已用以上语句重写了CreateParams,这样在主窗体调用这个窗体后,可以在任务栏中出现子窗体的标题,此步骤无问题。<br><br>为方便描述,我举一个邮件软件的例子:例设软件有三个窗体,分别为收发邮件的主窗体,写邮件的窗体,以及通讯录的窗体。<br> &nbsp; &nbsp;当用户打开主窗体,再在主窗体点击写邮件后,此时在任务栏正常出现了&lt;写邮件&gt;的标题栏,用户继续点击&lt;写邮件&gt;里面的通讯录,显示出了&lt;通讯录&gt;的模式子窗体。<br> &nbsp; &nbsp;此时用户突然需要做其他的事情,打开了桌面上的其他程序,做完后,点任务栏上的&lt;写邮件&gt;标题栏最大化&lt;写邮件&gt;窗体。现在问题就是点击以后这个窗体是显示出来了,但因为原先用户打开了&lt;通讯录&gt;的模式窗体,而这个窗体此时又没有显示出来,所以程序怎么写无法进行,这个问题大家是如何解决的。<br> &nbsp; &nbsp;我看了一下FoxMail的程序,这种情况下,点击&lt;写邮件&gt;窗体后,&lt;通讯录&gt;窗体是会一同被还原在&lt;写邮件&gt;窗体上面的,而我的程序没有。<br><br> &nbsp; &nbsp;请高手赐教如何改可以做到。不能用把通讯录窗体改成AlWaysOnTop方式,会影响其他程序的使用。
 
呜呜,怎么没人回答啊
 
任务栏只显示主窗体的标题,然后写邮件的窗体和通讯录窗体都模式打开,就行了!
 
參考一下我們的吧<br>procedure openform(formclass: Tformclass; var fm; Aowner: Tcomponent);<br>var<br> &nbsp;i: integer;<br> &nbsp;Child: TForm;<br>begin<br> &nbsp;Child := nil;<br> &nbsp;for i := 0 to Screen.FormCount - 1 do<br> &nbsp; &nbsp;if Screen.Forms.Classtype = formclass then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;Child := Screen.Forms;<br> &nbsp; &nbsp; &nbsp;if Child.WindowState = wsMinimized then<br> &nbsp; &nbsp; &nbsp; &nbsp;ShowWindow(Child.handle, SW_SHOWNORMAL)<br> &nbsp; &nbsp; &nbsp;else<br> &nbsp; &nbsp; &nbsp; &nbsp;ShowWindow(Child.handle, SW_SHOWNA);<br> &nbsp; &nbsp; &nbsp;if (not Child.Visible) then Child.Visible := true;<br> &nbsp; &nbsp; &nbsp;Child.BringToFront;<br> &nbsp; &nbsp; &nbsp;Child.SetFocus;<br> &nbsp; &nbsp; &nbsp;TForm(fm) := Child;<br> &nbsp; &nbsp; &nbsp;Child := TForm(formclass.NewInstance);<br> &nbsp; &nbsp; &nbsp;exit;<br> &nbsp; &nbsp;end;<br> &nbsp;if Child = nil then<br> &nbsp;begin<br> &nbsp; &nbsp;TForm(fm) := Child;<br> &nbsp; &nbsp;Child := formclass.Create(Application);<br> &nbsp;end;<br>end;
 
to: royal1442 <br>这样的话,只能一次写一封邮件,如果此时我还要查看主窗体中的已发送或收件箱中的邮件,不是不能操作了<br><br>to: bbscom<br>这个是可以解决全部的被关闭的窗口问题,但是此时我只想在恢复写邮件的窗口中恢复通讯录的窗体,怎办?当然,在这里我们是知道了是通讯录窗体,可以只查找这个基类,但如果打开的窗体类别是不确定的呢? <br>有没有一个属性可以知道他被创建的父窗体或祖父窗体(三级调用时)是谁的,这样就可以解决问题了。就像进程一样,可以知道父进程,类的父类一样。
 
那你把写邮件的程序从主程序中独立出来,成一个独立的程序!
 
谢谢 Roya11442<br>因为程序最终不是邮件软件,考虑到众多的原因,所以不能简单的独立出来。<br><br>我想可否在这方面下功夫呢,即在打开子窗体时,自动向写邮件窗体申报新创建的窗体的句柄,然后在点击写邮件的标题栏时,把这个子窗体激活即可。<br><br>关键是应该在窗体的什么事件,或截获WINDOWS的什么消息才能实现?<br>常规的OnShow,OnActive,OnPaint等事件都不成,Wm_SysComand好像写没截获住.
 
问题解决了,但是是同OUTLOOK的类似,还是没有达到FoxMail显示三个窗体时一样的效果<br>把解决方法公布出来,供大家参考<br>在网上看到了下面的文章,觉得有用,所以贴出来,我也是从这个文章中找到解决方法的。<br>解决思路同我上面的想法,就是在创建前将句柄记录下来,然后在截获消息后激活<br> &nbsp; &nbsp;procedure WMMsg(var Message:TMessage); Message WM_WINDOWPOSCHANGED; <br><br>procedure TfrOriginGather.WMMsg(var Message:TMessage);<br>begin<br> &nbsp;if self.Tag&gt;0 then begin<br> &nbsp; &nbsp;ShowWindow(self.Tag, SW_SHOWNORMAL);<br> &nbsp; &nbsp;BringWindowToTop(self.Tag);<br> &nbsp;end;<br> &nbsp;DefWindowProc(self.Handle,Message.Msg,Message.WParam,Message.LParam);<br>end;<br><br>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>在网上瞎逛,看到这样一道题目“鼠标左键点击在非当前窗口的标题栏上,会产生什么样的win32消息?”。当时感觉有点茫然,不就是WM_LBBUTTONDOWN、WM_ACTIVATE和WM_SETFOCUS吗?后来感觉可能不是这么简单,就用Spy++跟踪了一下,果然多了不少消息。<br><br>在NC点击发出的消息流程如下:<br> &nbsp; WM_NCHITTEST<br> &nbsp; //在鼠标点击非激活窗体的时候发出的,如果是点在子窗体上,还会通过DefWindowProc发给父窗体<br> &nbsp; WM_MOUSEACTIVATE<br> &nbsp; //鼠标左键点在NC发出的消息<br> &nbsp; WM_NCLBUTTONDOWN<br> &nbsp; WM_WINDOWPOSCHANGING<br> &nbsp; WM_WINDOWPOSCHANGED<br> &nbsp; //在应用程序切换的时候,用来Deactivate和Activate应用程序<br> &nbsp; WM_ACTIVATEAPP<br> &nbsp; //改变窗体在Activated和Deactivated状态下的NC<br> &nbsp; WM_NCACTIVATE<br> &nbsp; //Activate和Deactivate窗体,在同一个输入消息队列中Deactivate消息在前,随后才是activate消息;在不同的输入消息队列中,这两个消息被异步处理<br> &nbsp; WM_ACTIVATE<br> &nbsp; WM_NCLBUTTONMOVE<br> &nbsp; WM_NCLBUTTONUP<br> &nbsp; //当窗体获取键盘焦点的时候,才会发出这个消息<br> &nbsp; WM_SETFOCUS<br> &nbsp; <br>在用户区的子窗体上点击的消息流程如下:<br> &nbsp; //一般用来处理create、destroyed和鼠标消息,是子窗体发给所属父窗体的消息<br> &nbsp; WM_PARENTNOTIFY(WM_LBUTTONDOWN)<br> &nbsp; WM_MOUSEACTIVATE<br> &nbsp; WM_WINDOWPOSCHANGING<br> &nbsp; WM_WINDOWPOSCHANGED<br> &nbsp; WM_ACTIVATEAPP<br> &nbsp; WM_NCACTIVATE<br> &nbsp; WM_ACTIVATE<br> &nbsp; <br>通过Alt+Tab让该应用程序Deactivate的消息流程如下:<br> &nbsp; //The WM_CANCELMODE message is sent to cancel certain modes, such as mouse capture. For example, the system sends this message to the active window when a dialog box or message box is displayed. Certain functions also send this message explicitly to the specified window regardless of whether it is the active window. For example, the EnableWindow function sends this message when disabling the specified window.<br> &nbsp; WM_CANCELMODE<br> &nbsp; WM_NCACTIVATE(FALSE)<br> &nbsp; WM_ACTIVATE(FALSE)<br> &nbsp; //An application sends the WM_CHANGEUISTATE message to indicate that the user interface (UI) state should be changed<br> &nbsp; WM_CHANGEUISTATE<br> &nbsp; WM_ACTIVATEAPP(FALSE)
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
I
回复
0
查看
586
import
I
后退
顶部