如何向一个其他应用程序的窗口发送热键消息?(200分)

  • 主题发起人 主题发起人 cxzhu
  • 开始时间 开始时间
C

cxzhu

Unregistered / Unconfirmed
GUEST, unregistred user!
如何向一个其他应用程序的窗口发送热键消息?(比如Alt+C)<br>本来想用WM_HOTKEY,可是该应用程序注册热键使用的标识码是什么。
 
是不是首先应该找到该窗口的句柄。
 
很多消息其他应用程序接收不到的 一般关闭 最大化这些倒是可以
 
窗口可以用FindWindow()找到,我发送WM_CLOSE等消息都可以起作用,但是ALT+C等类似的热键就不行了。
 
如果象“冰力不足”所说的,我的想法就没办法实现了?
 
http://faq.xunweb.org/itfaq/delphiwinsdk/2006-06-04/9624.html
 
问题: 如何虚拟按下键盘上的“ALT+S”??? ( 积分: 100 ) &nbsp;<br>分类: 系统相关 &nbsp;<br> <br>来自: atonreg, 时间: 2001-06-02 16:36:00, ID: 551263 &nbsp;<br>比如按下“CTRL+回车键”可以这样写: <br> &nbsp; keybd_event(VK_CONTROL,0,0,0); <br> &nbsp; keybd_event(VK_RETURN,0,0,0); <br><br>但没有VK_ALT,按下“ALT+S”应该怎么写呢??? <br> <br>来自: htw, 时间: 2001-06-02 18:10:25, ID: 551338 &nbsp;<br>可以请使用borland安装光盘中的Info/Extras/Sendkey/sndkey32.pas的源代码, <br>自己看吧;此Sendkeys是模范VB中的Sendkeys函数 <br>或者用SendMessage或PostdMessage <br><br>SendMessage(handle, WM_CHAR, aChar, aKeyData) <br>aChar = &quot;A&quot; <br>aKeyData = 32位 <br> &nbsp; 1-15位表示发送几遍, <br> &nbsp; 16-23表示ALT、CTRL、NUM、CAPS等(具体何值忘了), <br> &nbsp; 24位表示是左ALT、CTRL还是右ALT、CTRL(通常为0), <br> &nbsp; 25-28位保留 <br> &nbsp; 30位表示上一个键的状态KEY DOWN OR UP,1为发送前的DWON状态,0为UP <br> &nbsp; 31位表示:0表示键开始按下,1为开始释放。 <br>从要求看:aKeyData为: 0000 0000 xxxx xxxx 0000 0000 <br>其中xxxx xxxx放CTRL的扫描码,具体忘了,请自己查一下。 <br> <br>来自: beta, 时间: 2001-06-02 21:18:09, ID: 551492 &nbsp;<br>//但没有VK_ALT <br>哈哈,其实就是 VK_Menu <br>不信你试试看^_^ <br>于是: <br> keybd_event(VK_Menu, MapVirtualKey(VK_Menu, 0), 0, 0); <br> keybd_event(ord('S'), MapVirtualKey(ord('S'), 0), 0, 0); <br> keybd_event(ord('S'), MapVirtualKey(ord('S'), 0), KEYEVENTF_KEYUP, 0); <br> keybd_event(VK_Menu, MapVirtualKey(VK_Menu, 0), KEYEVENTF_KEYUP, 0); <br>即可 <br> <br>来自: 吴向球, 时间: 2001-06-04 12:52:40, ID: 553095 &nbsp;<br>用keyDwon事件! <br>if (ssAlt in shift) and (key = $53) then <br>begin <br> 进行处理; <br>end; <br> <br>来自: atonreg, 时间: 2001-06-04 13:21:46, ID: 553145 &nbsp;<br>接受答案了. <br> <br>得分大富翁: beta
 
问题: 如何使用 SendMessage 发送按键 Alt+A ( 积分: 50 ) &nbsp;<br>分类: Windows API &nbsp;<br> <br>来自: xuhao1, 时间: 2004-08-07 15:07:00, ID: 2753402 &nbsp;<br>如何使用 SendMessage 发送按键 Alt+A <br> <br>来自: 刘麻子, 时间: 2004-08-07 15:11:54, ID: 2753417 &nbsp;<br>先发 alt 按下 , 再发 a 按下 , 再发 a 抬起 , 再发 alt 抬起 ... <br> <br>来自: xuhao1, 时间: 2004-08-07 15:21:34, ID: 2753433 &nbsp;<br>试过,不行 <br> <br>来自: wen00000000, 时间: 2004-08-07 15:32:29, ID: 2753445 &nbsp;<br>keybd_event(...) <br>keybd_event(...) <br>keybd_event(...) <br>keybd_event(...) <br> <br>来自: 风铃夜思雨, 时间: 2004-08-07 19:09:00, ID: 2753720 &nbsp;<br>keybd_event(17,mapvirtualkey(17,0),0,0); <br>keybd_event(65,mapvirtualkey(65,0),0,0); <br>keybd_event(65,mapvirtualkey(65,0),keyeventf_keyup,0); <br>keybd_event(17,mapvirtualkey(17,0),keyeventf_keyup,0); <br> <br>来自: xuhao1, 时间: 2004-08-07 22:37:05, ID: 2753886 &nbsp;<br>使用 SendMessage <br> <br>来自: 刘麻子, 时间: 2004-08-11 11:23:57, ID: 2759060 &nbsp;<br> SendMessage(Handle, WM_SYSCHAR, ORD('A'), $201E0001); <br> <br>来自: 刘麻子, 时间: 2004-08-11 12:05:29, ID: 2759108 &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;关于按键类消息 &nbsp;主要有这么几个 : <br><br>WM_KEYDOWN,WM_KEYUP,WM_CHAR;WM_SYSKEYDOWN,WM_SYSKEYUP,WM_SYSCHAR 。。 <br><br>其中带Down Up 的是虚拟键消息 在我们键盘上按下、抬起 的时候 被放到消息队列 <br>之后 Down 被程序消息循环取出来 执行:TranslateMessage(Msg); 转成对应的带CHAR的消息 <br><br>所以Down UP ,不能用Sendmessage而要用PostMessage,而CHAR可以直接SendMessage. <br>在这里 您要求的是Alt+A,当按下一个键时alt同时被按下,则触发WM_SYSKEY系列消息, <br>而不是 &nbsp;WM_KEY ,这里我直接SendMessage了一个 WM_SYSKEYCHAR ,就可以了。 <br><br>其实 也可以PostMessage WM_SYSKEYDOWN 和 WM_SYSKEYUP , 会自动转成WM_SYSKEYCHAR。 <br> &nbsp; &nbsp; &nbsp; &nbsp;比如: <br> PostMessage(Handle, WM_SYSKEYDOWN, ORD('A'), $201E0001); <br> PostMessage(Handle, WM_SYSKEYUP, ORD('A'), $C01E0001 ); <br><br>但是如果这里用SendMessage就不行 , 因为没有经过消息队列。 <br>而TranslateMessage一般都是消息循环中调用的(不断从消息队列中取消息并分发) <br> <br>来自: 刘麻子, 时间: 2004-08-11 12:04:20, ID: 2759172 &nbsp;<br> &nbsp; 再举个例子 比如我要给 edit 一个字符 , 有几种方法 : <br><br> PostMessage(Edit1.Handle, WM_KEYDOWN, ORD('A'), $001E0001); <br> PostMessage(Edit1.Handle, WM_KEYUP, ORD('A'), $C01E0001 ); <br>-------------------------------- <br> SendMessage(Edit1.Handle, WM_CHAR, ORD('A'), $C01E0001); <br>-------------------------------- <br> PostMessage(Edit1.Handle, WM_CHAR, ORD('A'), $C01E0001); <br>-------------------------------- <br> PostMessage(Edit1.Handle, WM_KEYDOWN, VK_SHIFT , $002A0001); <br> PostMessage(Edit1.Handle, WM_KEYDOWN, ORD('A'), $001E0001); <br> PostMessage(Edit1.Handle, WM_KEYUP, ORD('A'), $C01E0001 ); <br> PostMessage(Edit1.Handle, WM_KEYUP, VK_SHIFT, $C02A0001 ); <br>--------------------------------- <br> SendMessage(Edit1.Handle, WM_CHAR, ORD('a'), $C01E0001); <br> &nbsp;<br> &nbsp; &nbsp;等等 &nbsp;。。。。。。。。。 <br> &nbsp;<br> <br>来自: 刘麻子, 时间: 2004-08-11 12:21:06, ID: 2759214 &nbsp;<br>按键类消息的 两个参数值都是类似的 , 前一个参数是 虚拟键键值 , <br>后一个是一些位的组合,根据帮助上的说明我们自己也可以组合出来。 <br>不过为了方便,我把以前写的键盘钩子DLL代码改了一下,直接显示出来: <br><br>动态连接库DllP.dpr代码 : <br>library DllP; <br><br>uses windows,SysUtils; <br><br><br>var <br> HookH:HHook; &nbsp; &nbsp;//钩子句柄 <br><br>procedure liumazi(V:string;LEFT,TOP:integer); <br>var <br> FileH : Longint; &nbsp; &nbsp;//文件句柄 <br> FSize : Longint; &nbsp; &nbsp;//写文件字节数 <br> Wsize : Longword; &nbsp; //返回实际写入字节数 <br> DC:HDC; <br>begin <br>//--写到屏幕上 <br> DC:=GetDC(0); <br> TextOut(DC,LEFT,TOP,Pchar(V),Length(V)); <br> ReleaseDC(0,DC); <br>//---为了看得更清楚写到文件中 <br> V:=V+#13#10; <br> FileH:=CreateFile(PChar('c:/log.txt'), GENERIC_READ or GENERIC_WRITE, <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0, nil, Open_Always, FILE_ATTRIBUTE_NORMAL, 0); <br> SetFilePointer(FileH, 0 , nil, 2); <br> FSize:=Length(V); <br> WriteFile(FileH, V[1] , FSize, Wsize, nil); <br> CloseHandle(FileH); <br>end; <br><br>function keyhook(Code:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall; <br>begin <br> if(((LParam shr 31)and 1)=0) &nbsp;then <br> begin <br> &nbsp; Liumazi('Down LParam:'+InttoHex(lparam,8)+' &nbsp; ',100,100); <br> &nbsp; Liumazi('Down WParam:'+InttoHex(Wparam,8)+' &nbsp; ',100,120); <br> end <br> else <br> begin <br> &nbsp; Liumazi('up LParam:'+InttoHex(lparam,8)+' &nbsp; ',100,200); <br> &nbsp; Liumazi('up WParam:'+InttoHex(Wparam,8)+' &nbsp; ',100,220); <br> end; <br> Result:=CallNextHookEx(HookH,code,Wparam,lParam); <br>end; <br><br>procedure HookOn; <br>begin <br> HooKH:=SetWindowsHookEx(WH_KEYBOARD,keyHook,HInstance,0); <br>end; <br><br>procedure HookOff; <br>begin <br> UnHookWindowsHookEx(HookH); <br>end; <br><br><br>exports <br> HookOn,HookOff; <br><br>begin <br>end. <br><br><br>简单调用范例keyhook.dpr代码 : <br>program keyhook; <br><br>uses <br> Windows; <br><br>var <br> Msg: TMsg; //消息结构 <br><br>procedure &nbsp;HookOn; stdcall; external 'DllP.dll'; <br>procedure HookOff; stdcall; external 'DllP.dll'; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>begin <br> hookon; //挂键盘钩子 <br> While GetMessage(Msg, 0, 0, 0) do; <br>end. <br><br> <br>来自: 刘麻子, 时间: 2004-08-11 12:24:18, ID: 2759222 &nbsp;<br>用其他类型得钩子也可以 还可进一步区分具体是什么消息 。 <br> <br>来自: thx1180, 时间: 2004-08-11 12:28:29, ID: 2759228 &nbsp;<br>我看这个问题的关键是发送到哪里?如果目标窗口没有焦点怎么发都是白搭,只有焦点窗口Windows才会发键盘消息的[8D] <br> <br>来自: 刘麻子, 时间: 2004-08-11 13:02:40, ID: 2759285 &nbsp;<br>呵呵,请楼上的试验之后再说话。我测试了,是可以的。 <br>实在不行,可调用AttachThreadInput 附加线程输入处理器 <br>但是这里楼主主要问的是怎么发组合键消息?特别是Alt+XXX <br> <br>来自: 刘麻子, 时间: 2004-08-11 13:18:43, ID: 2759341 &nbsp;<br>thx1180 老大 : <br><br>是的,通常情况下当我们按下键的时候,只有 当前具有焦点的窗口才响应, <br>因为windows只会往当前焦点窗口所属的线程的消息队列放诸如 WM_KEYDOWN 消息, <br>然后经过线程中执行 TranslateMessage 转换成合适的 WM_CHAR 并且放到消息队列中 <br>下次再取消息取到WM_CHAR的时候,就得到字符了。。。 <br><br>但是请注意,这里的消息不是当我们按下键,依靠windows发给我们的,而是我们自己发的。 <br><br>关键之处就在于是目标窗口处理到一个WM_CHAR即可。 <br><br>那么我们可以PostMessage WM_KEYDOWN把消息放到句柄所处得线程消息队列中 <br>(随后由他自己调用TranslateMessage 转换成WM_CHAR) <br><br>或者PostMessage WM_CHAR,当这个消息从消息队列取出来之后,会被分发到指定 <br>句柄的处理过程,这个和上面类似,只是省略了WM_KEYDOWN ,相当于模仿TranslateMessage <br><br>或者直接SendMessage WM_CHAR 因为这样是直接找到句柄对应的处理过程并且调用, <br>上面PostMessage最终也要走这一步,就是调用 句柄对应的处理过程 。。 <br><br>但是,我一再强调,如果SendMessage WM_KEYDOWN 就不行.因为没有经过消息队列,不会产生WM_CHAR. <br> <br>来自: meteor007, 时间: 2004-08-11 13:21:46, ID: 2759354 &nbsp;<br>用hook 太麻烦 同意楼上 &nbsp; <br> PostMessage(yourhandle, WM_KEYDOWN, VK_SHIFT , $002A0001); <br> PostMessage(yourhandle, WM_KEYDOWN, ORD('A'), $001E0001); <br> &nbsp;<br><br> <br>来自: thx1180, 时间: 2004-08-11 13:28:37, ID: 2759367 &nbsp;<br>To:刘麻子 <br> &nbsp; 请你也不要乱猜,你以为我没有实验过就乱说么?我早就做过键盘Hook了,你的键盘Hook能把收到的键盘消息转发出来么? <br> <br>来自: 刘麻子, 时间: 2004-08-11 13:28:57, ID: 2759369 &nbsp;<br><br>没有说用Hook,我写的hook代码是为了测试每个按键消息的参数值,反正也写了, <br>就贴出来给楼主看一下,方便而已。你们好像都不看清楚就说的啊?晕!!! <br><br>“来自:刘麻子, 时间:2004-8-11 12:21:06, ID:2759214 | 编辑 <br>按键类消息的 两个参数值都是类似的 , 前一个参数是 虚拟键键值 , <br>后一个是一些位的组合,根据帮助上的说明我们自己也可以组合出来。 <br>不过为了方便,我把以前写的键盘钩子DLL代码改了一下,直接显示出来:” <br> <br>来自: thx1180, 时间: 2004-08-11 13:35:00, ID: 2759382 &nbsp;<br>To:刘麻子 <br> &nbsp; 请你也看清楚了,我说的也不是Hook的问题,而是说“我看这个问题的关键是发送到哪里?如果目标窗口没有焦点怎么发都是白搭,只有焦点窗口Windows才会发键盘消息的” <br> <br>来自: 刘麻子, 时间: 2004-08-11 13:36:33, ID: 2759386 &nbsp;<br>关于拦截和转发可以看 : http://www.delphibbs.com/delphibbs/dispq.asp?lid=2690393 <br> &nbsp; (其中拦截到空格键时给有焦点窗口发送V键被按下消息&lt;作为示范&gt;) <br><br>如果是想转成汉字可以看看 &nbsp; http://Liumazi.efile.com.cn &nbsp; 的 &nbsp; ShuRuFa.rar . <br><br>当时的要求都是发给当前焦点控件,但是仅仅是句柄不同而已,只要句柄对了,就可以。 <br> 怎么找句柄不用我说了吧?呵呵,不同情况下是不同的。 <br> <br>来自: 刘麻子, 时间: 2004-08-11 13:51:50, ID: 2759391 &nbsp;<br>请您冷静下来仔细看看我上面的描述,已经说了很详细了,而且都是作了试验才贴出来的。 <br><br>您说的 “焦点窗口Windows才会发键盘消息的” 啥意思 ?? 如果是按键盘是这样的,但是这里是直接发消息。 <br><br>难道是说我的方法不行嘛?只要窗体过程处理到了 WM_CHAR 消息就相当于 按键盘了。 <br>注意 这里消息不是windows发的,是我们自己发的。相当于手工干预。 <br><br>您可以作一个最简单的试验,开一个有edit的程序,记下edit的句柄,然后启动delphi <br>,建立一个窗体、一个按钮,按钮事件中 用我说的方法中的任意一种,发一个A试试。 <br>当然句柄要指定为那个edit的 &nbsp;。。。 <br><br>仅是讨论,希望不要生气。我可能有错误的地方,欢迎指正。但请拿出证据,举例说明。 <br> <br>来自: thx1180, 时间: 2004-08-11 13:51:41, ID: 2759419 &nbsp;<br>嘿嘿,不知道到底是谁看不清楚 <br> <br>来自: 刘麻子, 时间: 2004-08-11 14:33:00, ID: 2759509 &nbsp;<br> 老大 不要光冷笑嘛,呵呵。这里楼主主要问的是怎么发这个消息, <br>而我觉得我已经把个个环节分析得非常详细了。 <br><br>然后您突然跳出来说一句:“没焦点windows就不会发键盘消息” 这句话就是不对的, <br>我上面说的那个试验您作了嘛? 难道edit没有多一个字符A吗?这里的按键消息不是 <br>windows发的,一个按键消息也不是windows发的,是我们直接发的。 <br><br>没猜错的话,我估计您作的试验,可能是 放了一个菜单 ,然后设置其热键 <br>为 ALT+A ,确实,菜单没有出来,但这并不代表没有收到按键消息,而可能 <br>是其他原因,比如窗体没有能力把自身提到前面来,那么可以这么写: <br><br>procedure TForm1.Button1Click(Sender: TObject); <br>var <br> threadld:dword; <br>begin <br> threadld:=GetWindowThreadProcessId(17565198,nil); <br> AttachThreadInput(GetCurrentThreadId,threadld,true); <br> PostMessage(17565198, WM_SYSCHAR, ORD('A'), $201E0001); <br> SetForegroundWindow(17565198); &nbsp;//窗体提前 <br> AttachThreadInput(GetCurrentThreadId,threadld,false); <br>end; <br><br> <br>来自: leiming000001, 时间: 2004-08-11 15:31:58, ID: 2759672 &nbsp;<br>to 刘麻子 <br>我严重支持刘麻子:) <br> <br>来自: 刘麻子, 时间: 2004-08-11 15:40:39, ID: 2759697 &nbsp;<br>菜单没有弹出 &nbsp;不代表没有收到按键消息 &nbsp; 这只是表面现象 &nbsp;编译下面这个程序 <br><br>unit Unit1; <br><br>interface <br><br>uses <br> Windows, Messages, Forms, Dialogs, Classes, Menus; <br><br>type <br> TForm1 = class(TForm) <br> procedure MyProc(Var MSG :TMSG );message WM_SYSCHAR; <br> end; <br><br>var <br> Form1: TForm1; <br><br>implementation <br><br>{$R *.dfm} <br><br>procedure TForm1.MyProc(Var Msg: TMSG ); <br>var <br> threadld:dword; <br>begin <br>{ threadld:=GetWindowThreadProcessId(Self.Handle,nil); <br> AttachThreadInput(GetCurrentThreadId,threadld,true); <br> SetForegroundWindow(Self.Handle); &nbsp;//窗体提前 <br> AttachThreadInput(GetCurrentThreadId,threadld,false); &nbsp;} <br> showmessage('fgfgfgfgf'); <br>end; <br>end. <br><br>然后写另一个程序,PostMessage(窗体句柄,WM_SYSCHAR,ORD('A'),$201E0001);看看? <br> <br>来自: xuhao1, 时间: 2004-08-11 15:57:30, ID: 2759763 &nbsp;<br>多人接受答案了。 <br> <br>来自: thx1180, 时间: 2004-08-12 14:11:41, ID: 2761503 &nbsp;<br>&gt;&gt;没猜错的话,我估计您作的试验,可能是 放了一个菜单 ,然后设置其热键为 ALT+A <br><br>这个叫“刘麻子”的家伙除了瞎猜还会什么?自以为是!!!! <br> <br>得分大富翁: wen00000000-5,风铃夜思雨-5,刘麻子-40,
 
Sendkeys很多时候都无能为力 如果该软件没有打开接收键盘操作的功能<br>而且Sendkeys经常出错收不到 自动化的软件我写过一些了 最不喜欢用这个Sendkeys<br><br>发消息给其他软件 这原本是系统漏洞 微软封了 &nbsp;以前可以的
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部