还得请教你。
帖子:http://topic.csdn.net/u/20081021/12/932eb86e-ec10-46f7-9d43-8f37e2aeea1d.html
里面,你教我拦截WM_WINDOWPOSCHANGING消息,然后在窗口子类化里丢弃SWP_SHOWWINDOW,确实能在窗口显示出来之前隐藏窗口。
但有点后续问题。因为我的目标窗口是一个VB程序,上面有个文本框有个.setfocus事件。但由于窗口还没显示出来,那个文本框也还不可见,所以执行.setfocus的时候那个VB程序就出错了(VB里面不允许对不可见的控件执行.setfocus)。无奈之下,我改成拦截WM_WINDOWPOSCHANGED消息,但这样一来,好像出现WM_WINDOWPOSCHANGED消息的时候,窗口就已经显示出来了,所以你教我的那个子类化里面丢弃SWP_SHOWWINDOW消息的办法隐藏不了窗口了。
我改成:
if msg = WM_WINDOWPOSCHANGED then//原来是WM_WINDOWPOSCHANGING
begin
wndPos := PWindowPos(lp);
if (wndPos^.flags and SWP_SHOWWINDOW) <> 0 then
begin
wndPos^.flags := (wndPos^.flags and (not SWP_SHOWWINDOW));
end;
end;
也还是不行,窗口没有隐藏。
我要是直接用showwindow(hwnd,sw_hide);的话,那个窗口总是先显示一下然后才隐藏,效果不好。
能帮我再想想还有什么好办法吗?谢谢了
帖子:http://topic.csdn.net/u/20081021/12/932eb86e-ec10-46f7-9d43-8f37e2aeea1d.html
里面,你教我拦截WM_WINDOWPOSCHANGING消息,然后在窗口子类化里丢弃SWP_SHOWWINDOW,确实能在窗口显示出来之前隐藏窗口。
但有点后续问题。因为我的目标窗口是一个VB程序,上面有个文本框有个.setfocus事件。但由于窗口还没显示出来,那个文本框也还不可见,所以执行.setfocus的时候那个VB程序就出错了(VB里面不允许对不可见的控件执行.setfocus)。无奈之下,我改成拦截WM_WINDOWPOSCHANGED消息,但这样一来,好像出现WM_WINDOWPOSCHANGED消息的时候,窗口就已经显示出来了,所以你教我的那个子类化里面丢弃SWP_SHOWWINDOW消息的办法隐藏不了窗口了。
我改成:
if msg = WM_WINDOWPOSCHANGED then//原来是WM_WINDOWPOSCHANGING
begin
wndPos := PWindowPos(lp);
if (wndPos^.flags and SWP_SHOWWINDOW) <> 0 then
begin
wndPos^.flags := (wndPos^.flags and (not SWP_SHOWWINDOW));
end;
end;
也还是不行,窗口没有隐藏。
我要是直接用showwindow(hwnd,sw_hide);的话,那个窗口总是先显示一下然后才隐藏,效果不好。
能帮我再想想还有什么好办法吗?谢谢了
解决方案 »
- 关掉了{$Q}还有溢出的错误
- 什么是编译指令,有什么作用?
- FastReport中RichText问题,在线等
- infopower 4000 中的wwdbdatetimepicker
- 在线急等,如何让radiogroup中的一个itemindex对应的文字在选中时变色,而不是全变色
- 求助:用TUdateSql控件保存BLOB字段时报错说,LOB定位器无法定位?
- 多线程与数据库问题,在线等候
- 如何在按钮事件中调用另一个非按钮事件?
- 哪里有适合delphi6的控健(包括fastreport)可以下载?
- 见笑啦!!小弟我有一个小问题,想麻烦大家!!!!!(我给40分!!!!!)
- 高分求delphi存取图片例程!我做了3天没做出来 ,谁给我做个
- D7与Excel的交互
我拦截到消息后,为了判断是否是我要的窗口,还要做挺多数据准备操作,甚至还有数据库操作,如果拦截消息重绘消息的话,就太频繁了,因为发出重绘消息太多了,太多操作都会引发重绘消息,这样系统运行很可能受影响其实我开始想过拦截WM_WINDOWPOSCHANGING和WM_WINDOWPOSCHANGED消息,发现目标窗口的话而且是WM_WINDOWPOSCHANGING消息的话,就用原来dandycheung教我方法,先隐藏;发现目标窗口而且还是WM_WINDOWPOSCHANGED消息的话,再执行我填单的操作。
这个想法是基于对于一个窗口显示过程来说,WM_WINDOWPOSCHANGING消息会比WM_WINDOWPOSCHANGED先出现的想法。但这样即使可行,我也有点不甘心,因为判断目标窗口的操作在两次拦截中都要执行一次,效率不高,相当于比原来低了一半。而这样的代价仅仅就是为了实现一个漂亮的显示效果,有点不划算。想知道是不是还有更好的办法。
2、你可以把窗口的大小设置为 0 宽 0 高
3、你还可以用 SetWindowRgn 或者 SetLayeredWindowAttributes 这类的函数把目标窗口弄得即使处于可见状态用户也看不见我能想象的副作用是,由于这些方法都是让用户看不到事实上处于已经显示出来的状态的窗口,所以有可能会对当前的活动窗口的激活状态带来一些闪烁(因为后续你肯定还会隐藏它)。除非特别仔细或者挑剔的用户,这个副作用倒是也影响不大。
其实在禁用窗体的显示事件的时候,你可以判断句柄的父类名,也就是说如果在你的窗体上控件的显示,你放过,如果是窗体本身,就不放过。如果楼主不会写这部分代码,那么只需要你给我提供需要钩的这个VB做的EXE文件,我来帮你续写后面的代码。另外,3楼朋友让次写的那个不让任务管理器出现任意进程的代码没有效果,后来我在QQ上跟你说话你没有反应。
if CompareText(clsName, 'Notepad') = 0 then
关键是这句,使钩住的事件激发成了唯一。如果去掉这句,那么记事本中有多少个控件,就会激发多少次Show事件。而你在激发的每一个事件中只需要判断父类名是不是Notepad即可,如果是,就放掉,如果不是,再判断它是不是Notepad本身,如果是本身,就取消它的Show。
我是在钩子里处理的,子类化过程仅仅做了丢弃消息的事。
我的想法是:
if (winStruct.message = WM_WINDOWPOSCHANGING) or (winStruct.message = WM_WINDOWPOSCHANGED) then
begin
1、判断是否目标窗口
2、如果是目标窗口
2.1 如果是WM_WINDOWPOSCHANGING的话,子类化,实现隐藏效果
2.2 否则,进行我预期的填单操作
end;
按照之前的帖子讨论的办法,我肯定拦截的只是目标窗口的那次show。因为我要拿到窗口的句柄做事情。出现的多次show应该是窗体上每个子窗体(或者称为控件)的show,而不是窗体本身的show
不知道窗口本身的那个WM_WINDOWPOSCHANGING消息相对于4个文本框来说,是最先出现,还是最后出现呢?
你的意思是过滤之前,先判断是不是目标窗口?还是判断有没有SWP_SHOWWINDOW?
如果你的意思是前者,那这个判断不知道要执行多少次
如果是后者,那我总不能所有的show都给去掉SWP_SHOWWINDOW吧。
在这句之前 if CompareText(clsName, 'Notepad') = 0 then
加上GetClassName(GetParent(句柄),cap,99);
if lstrcmpi(cap,'notepad')=0 then
begin
Result := CallNextHookEx(hhook, nCode, wParam, lParam);
exit;
end;
即可。
如果你的文本框不是在窗体上,而是在Panel上,那么还要再取一级父句柄。具体情况具体分析,你不发EXE给我,我就只能回答你这么多了。
你明白了吗?我不想让这个判断频繁发生。
你想象的太简单。
发生了几次,我加上去的代码也发生了几次。总之,你给EXE我马上就可以做出来。如果你想自己搞,那算了。等高人来给你提供更好的算法吧。
这个想法是基于对于一个窗口显示过程来说,WM_WINDOWPOSCHANGING消息会比WM_WINDOWPOSCHANGED先出现的想法。刚才测试了一下这样做,发现不行。好像是我拦截WM_WINDOWPOSCHANGING并在子类化里丢弃SWP_SHOWWINDOW之后,这个窗口就不会再出现WM_WINDOWPOSCHANGED消息了。