标题:请教可以检测到Messagebox()在运行吗?
只看楼主
csyx
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:29
帖 子:484
专家分:1827
注 册:2018-3-13
得分:0 
以下是引用foxfans在2023-5-15 17:05:56的发言:
其实并不存在bug,Vfp的MessageBox实际是对二个API函数的封装MessageBoxA和MessageBoxTimeoutA,
置顶状态时,MessageBoxA时抢占获得焦点只要不被其他置顶窗口激活Messagebox窗口就默认置顶在上面.
而当MessageBoxTimeoutA时,Vfp主窗口本身重绘又置顶就会把messageboxtimeout(本身不置顶)窗口置后,这时候你再弄个置顶窗口放在你主程序上面一样把Vfp主程序统统覆盖,除非你这时候Hook掉这个Messaageboxtimeout窗口,把这个窗口也设置成置顶状态,就会在你的主窗口上面,换句话说,即使你的messagebox置顶别人的也是置顶属性的窗口后激活在你messagebox窗口位置时,一样会在你messagebox窗口之上.

好吧,请您解释下为何直接调用这个 api 不会发生楼主的情况,原因是什么?

*!*    Messagebox("在这里呀!",1,"信息提示")
Declare Long MessageBoxTimeout in win32api ;
    Long hWnd, String lpText, String lpCaption, Long uType, Long wLanguageId, Long dwMilliseconds
MessageBoxTimeout(Thisform.HWnd, '在这里呀!', '信息提示', 0, 0, 5000)
2023-05-15 17:44
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
个人理解,这样试试:
Messagebox("猫猫躲我",1,"信息提示") 时,表单是不活动的,不响应消息,AlwaysOnTop失效。
Messagebox("我躲猫猫",1,"信息提示",50000) 时,表单是活动的,AlwaysOnTop有效,会响应消息,只是先放在消息队列,等Messagebox返回断续执行。
可以试试继续点击“我躲猫猫”或点击关闭表单看看


[此贴子已经被作者于2023-5-15 19:31编辑过]

2023-05-15 17:52
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
以下是引用csyx在2023-5-15 17:44:51的发言:


好吧,请您解释下为何直接调用这个 api 不会发生楼主的情况,原因是什么?

*!*    Messagebox("在这里呀!",1,"信息提示")
Declare Long MessageBoxTimeout in win32api ;
    Long hWnd, String lpText, String lpCaption, Long uType, Long wLanguageId, Long dwMilliseconds
MessageBoxTimeout(Thisform.HWnd, '在这里呀!', '信息提示', 0, 0, 5000)

可能与Thisform.HWnd(MessageBox的所有者)有关
VFP的MessageBox所有者是不是NULL?还是 _vfp或_screen
2023-05-15 17:55
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
MessageBoxTimeout 虽然在 user32.dll 里,好像是未公开的API,使用时是否会带有不确定性的问题?

2023-05-15 17:58
foxfans
Rank: 4
等 级:贵宾
威 望:11
帖 子:90
专家分:278
注 册:2021-10-23
得分:0 
刚才看了messagebox和timeout出来的时候还是置顶状态
但传的hwnd不是thisform.hwnd,如果是_screen.hwnd 或_vfp.whnd按上面的例子也不像,会卡在那里和自带的messagebox状态不一样.应该是别的窗口句柄.谁有空可以去enum窗口出来,再一个个比对一下,或直接勾子OD跟看一下是哪个hwnd和enum的对比一下,确认是哪个

[此贴子已经被作者于2023-5-15 18:13编辑过]

2023-05-15 18:10
csyx
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:29
帖 子:484
专家分:1827
注 册:2018-3-13
得分:0 
28楼的时候我说了,怀疑是vfp传递的第一个参数错误,所以我说这是bug
传入的是什么不知道,既不是 Null,也不是 _Screen.hWnd,这俩的光标都是忙状态,与带 timeout 参数时表象不同
2023-05-15 18:20
csyx
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:29
帖 子:484
专家分:1827
注 册:2018-3-13
得分:0 
其实这都不重要,知道 vfp 的 MessageBox 有这毛病就行

我的代码多年前就不直接用这个函数了,全改用自己的 MsgBox,都是直接调用 api
如果指定了超时参数,咱就用 MessageBoxTimeoutW,没有就调 MessageBoxW - 文字或标题是 N' 开头(源于 SQL Server 的 unicode 表示法),就直接传递,不是就先转 unicode
2023-05-15 18:41
foxfans
Rank: 4
等 级:贵宾
威 望:11
帖 子:90
专家分:278
注 册:2021-10-23
得分:0 
通过勾子可以确定,上面的例子vfp在调用messagebox带时间参数时, Vfp调用 MessageBoxTimeoutA 时里面传的Hwnd 100%是0

上面的例子给messageboxtimeoutA发送的参数如上图
,进一步研究发现,MessageboxA MessageBoxTimeoutA最终都会调用到MessageBoxTimeoutW  ->>    MessageBoxWorker 所以在这下面勾也一样.

[此贴子已经被作者于2023-5-15 20:15编辑过]

2023-05-15 19:26
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
继续试试:
Messagebox("猫猫躲我",1,"信息提示") 时,窗口样式:
  标准样式:0x94C801C5
  扩展样式:0x00010109

Messagebox("我躲猫猫",1,"信息提示",50000) 时,窗口样式:
  标准样式:0x94C801C5
  扩展样式:0x00010101
  
差别在扩展样式,没有Timeout的多了个:
  WS_EX_TOPMOST equ 8h

这正符合有Timeout时 +4096 的做法:MB_SYSTEMMODAL 0x1000(4096)消息对话框具有WS_EX_TOPMOST样式。
2023-05-15 20:14
foxfans
Rank: 4
等 级:贵宾
威 望:11
帖 子:90
专家分:278
注 册:2021-10-23
得分:0 
对还是按文档,规范参数timeout文档配用参数也是4096,肯定有他的道理.

MessageBox消息经过的函数很多,非常复杂,实在不行就换api不用自带的好控制,4096去alwaysontop也是可以不知道为什么非要ontop


[此贴子已经被作者于2023-5-15 20:40编辑过]

2023-05-15 20:36



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-512194-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.048640 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved