分享
 
 
 

Delphi 消息机制引入的一个副作用

王朝delphi·作者佚名  2007-02-07
窄屏简体版  字體: |||超大  

Delphi 在处理进程的消息时引入了一个隐藏的窗体Application ,借此进行消息的分发。这样的机制优美的处理了消息的分发和处置的问题。但是最近我发现这个机制也引入了一个副作用,会在某些情况下影响程序的界面交互行为。

我遇到的需求是需要在程序中实现单个实例,并且在第二个实例被启动的时候,首先将前一个实例置到最前,然后退出。按说这样的问题应该是比较典型的例子,但是这样的一个简单需求就受到了这个副作用的影响。

我的实现方式是这样的:第二个实例启动的时候,对前一实例发一个消息,要求它将自己置前,然后退出。至于前一个实例的句柄怎么取得,可以用FindWindows ,也可以用命名的FileMapping ,总之,第一个窗体就这样接到了将自己置前的命令。

怎么将这个窗体置到最前呢?众所周知,SetForegroundWindow 并不能真正将一个窗体置到最前,相反的,为了礼貌起见,它会让这个指定的窗体在任务栏里面闪动,吸引用户注意,但是它不会把这个窗体盖在Z-Order 的顶端。很有教养,但是我不喜欢,因为这不是我想要的。

于是我使用了这样一个方法将我要的窗体直接置到最前面:

SetWindowPos(hForm, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);

SetWindowPos(hForm, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);

强行把窗体拖到Z-Order 的顶端,然后去掉它的TOPMOST 属性,这样就可以了。有点不够礼貌,不过要是礼貌有用的话,要警察做什么?

好了,前面说的内容似乎和我们的标题没太多关系,可是后面的麻烦都根源在这里。

我发现,当第一个实例被最小化时,第二个实例将它唤醒,将它的主窗体置到最前,然后窗体的“最小化”按钮失效了!这时窗体可以操作、可以最大化、可以关闭,却再也不能最小化了!

这是一个很郁闷的问题,一个不能最小化的窗体实在是很不友好的,我可以接受一个不礼貌的窗体,却不愿意接受一个这样不友好的家伙。

我发现问题原因的过程是这样的:

在进程中,主窗体的WM_SYSCOMMAND 消息是被传递给Application 类处理的,当CmdType 为SC_MINIMIZE的时候,Application 会调用Minimize 方法:

procedure TApplication.Minimize;

begin

if not IsIconic(FHandle) then

begin

NormalizeTopMosts;

SetActiveWindow(FHandle);

if (MainForm <> nil) and (ShowMainForm or MainForm.Visible)

and IsWindowEnabled(MainForm.Handle) then

begin

SetWindowPos(FHandle, MainForm.Handle, MainForm.Left, MainForm.Top,

MainForm.Width, 0, SWP_SHOWWINDOW);

DefWindowProc(FHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0);

end else

ShowWinNoAnimate(FHandle, SW_MINIMIZE);

if Assigned(FOnMinimize) then FOnMinimize(Self);

end;

end;

注意这个IsIconic(FHandle),它就是问题原因的冰山一角。IsIconic 是用来检测窗体是否处于最小化状态的API。我发现,第二实例将前一实例的主窗体置前之后,这个窗体最小化调用这个方法时,每次IsIconic(FHandle) 都是True。也就是说,Application 一直认为自己是最小化的。

于是问题就比较清楚了:我们在将主窗体强行置到最前的时候,Application 并没有恢复原状态。于是在Minimize 方法中主窗体就得不到最小化的命令了。

难怪在VC 开发的程序中不会有这样的问题!因为不存在Application 的这个因素。

于是我们只要将主窗体强行置前之前,首先将Application 恢复:

if IsIconic(Application.Handle) then

begin

DefWindowProc(Application.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);

end;

这样就好了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有