首页
社区
课程
招聘
如何使用sendmessage方法向notepad窗口发送组合键ctrl-a
发表于: 2007-2-9 14:01 20808

如何使用sendmessage方法向notepad窗口发送组合键ctrl-a

2007-2-9 14:01
20808
收藏
免费 0
支持
分享
最新回复 (19)
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
用Spy++查看Notepad接收到哪些ctrl-a的消息.
2007-2-9 22:58
0
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
3
KEYDOWN就可以吧
2007-2-10 00:06
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
void CCalcsylDlg::OnTestNotepad()
{
        // TODO: Add your control notification handler code here
        HWND w1;
        w1=::FindWindow("Notepad",NULL);
        w1=::FindWindowEx(w1,NULL,"Edit",NULL);
       
        ::SendMessage(w1,WM_CHAR,'A',0);               /* 可以成功的模拟字符A */

        ::SendMessage(w1,WM_KEYDOWN,VK_CONTROL,0);
        ::SendMessage(w1,WM_KEYDOWN,'A',0);
        ::SendMessage(w1,WM_KEYUP,'A',0);
        ::SendMessage(w1,WM_KEYUP,VK_CONTROL,0);
}

使用spy++看了一下,就是两个KEYDOWN,两个KEYUP消息,但上述代码不能模拟按键ctrl-a
2007-2-10 16:08
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
5
/*
* Send CTRL+A Message To Edit Control
* 版权所有 (C) 2007 天津 赵春生
* 2007.02.11 16:22
* http://timw.yeah.net
* http://timw.126.com
* 本程序适用于:WinXP+SP2[Notepad]
* 代码在WinXP+SP2 + VC6+SP6测试通过
*/

#include <windows.h>

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
       
        HWND hwnd=NULL;
        hwnd=FindWindow("Notepad",0);
        hwnd=FindWindowEx(hwnd,0,"Edit",0);
        if (hwnd)
        {
                SendMessage(hwnd,EM_SETSEL,0,-1);//从开始到文本末尾
        }
        else
               
                MessageBox(NULL,"[Notepad] 未发现!","错误!",NULL);
       
        CloseHandle(hwnd);
        return 0;
       
}
2007-2-11 16:29
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
先感谢Vegeta的指导。

上述代码的确可以实现ctrl-a的功能。但是确不是我所需要的。

上述代码是通过发送select all消息过去,而不是发送ctrl-a消息。如果notepad把ctrl-a的功能改成完成其他某特定功能,而这个特定功能不能通过发送 EM_类的消息代替的。我现在想实现的是发送ctrl-a消息过去,让程序自己去处理。

(换个问题:如何发送 ctrl-p或ctrl-f按键?)
2007-2-11 18:14
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
在网上搜了几天,没能搞定。发现网上问这个问题的人还比较多,似乎还没有好的解决方案。最恰当的问法是:
如何用SendMessage向另一程序的非焦点的窗口发送组合键?
2007-2-11 19:15
0
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
我怀疑编辑框控件在接收到"A"键的KEYDOWN消息时判断当前CTRL键的状态,而不是根据是否前面是否有CTRL键的KEYDOWN消息.
2007-2-11 20:13
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
最初由 dwing 发布
我怀疑编辑框控件在接收到"A"键的KEYDOWN消息时判断当前CTRL键的状态,而不是根据是否前面是否有CTRL键的KEYDOWN消息.


不是这样。我把ctrl按住不放,然后发送一个A的WM_KEYDOWN消息过去,没有效果。
2007-2-11 22:16
0
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
最初由 auser 发布
不是这样。我把ctrl按住不放,然后发送一个A的WM_KEYDOWN消息过去,没有效果。


我试过了,是有效果的,只发送'A'的KEYDOWN和KEYUP消息,按住CTRL键就能全选.
但要注意使用PostMessage.
2007-2-12 12:05
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
11
用keybd_event可以,但不符合LZ要求.

SendMessage我没试成功。
2007-2-12 15:48
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
最初由 dwing 发布
我试过了,是有效果的,只发送'A'的KEYDOWN和KEYUP消息,按住CTRL键就能全选.
但要注意使用PostMessage.


看来只能用api hook,把GetKeyStat,GetKeyboardState,GetAsyncKeyState挂住,返回ctrl被按下的假相。
hook api对我来说,难度太大了,看起来是一个不可能完成的任务。

我的本意是操控一个软件在后台完成一系列的功能(全部操作完成可能需数小时)。如果使用keybd_event,的确可以完成模拟组合键,但是这样,操控过程就必须在前台完成,这时候我就不能用计算机搞别的事情了。
2007-2-12 22:50
0
雪    币: 154
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
我做过类似的工作,与LZ的不完全相同,应该也是出现了与LZ相似的情况,我的理解是:

无论用sendmessage还是postmessage,记事本都已经接收到了按键消息,但有一点要注意的是,由于记事本没有处于激活(当前活动窗口)状态,负责接收消息的是记事本的框架(因为记事本是SDI程序),但框架本身并没有处理CTRL+A的消息代码,所以不会出现“全选”的效果。

简单说一句就是,CTRL+A是属于记事本中编辑框的热键,而失去焦点的编辑框是不会响应CTRL+A的。

(个人怀疑也不是由框架实现的,编辑框是WINDOWS的标准控件,标准控件的消息处理似乎由系统的核心DLL实现的,像标准的界面绘制之类的)

要实现非激活状态下的“全选”,估计 Vegeta 的方法最适合了。

如果想测试按键是否真的被框架接收到了,可以试着把“CTRL+A”改成“F5”(插入当前日期和时间)。

dwing在10楼说的情况,我也不清楚,估计是遇到的实际情况不一样吧。

PS:我很菜,了解得不深入,期待高手
2007-2-13 04:56
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
14
LZ不会是穷举注册码吧?

有个变通的方法,可以控制究竟谁能响应CTRL+A,还不是很完美,继续研究中……

#include <windows.h>

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
       
        HWND hwnd=NULL;
        hwnd=FindWindow("Notepad",0);
        hwnd=FindWindowEx(hwnd,0,"Edit",0);
        if (hwnd)
        {
               
                keybd_event(VK_CONTROL,0,0,0);
                PostMessage(hwnd,WM_KEYDOWN,65,0);
                PostMessage(hwnd,WM_KEYUP,65,0);
                keybd_event(VK_CONTROL,0,KEYEVENTF_KEYUP,0);
               
        }
        else
               
                MessageBox(NULL,"[Notepad] 未发现!","错误!",NULL);
       
        CloseHandle(hwnd);
        return 0;
       
}
2007-2-13 11:44
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
dwing说的对,看代码:

CODE:0070936A                 cmp     word ptr [esi], 63h        ; 按下的是'c'键吗?
CODE:0070936E                 jz      short loc_709376
CODE:0070936E
CODE:00709370                 cmp     word ptr [esi], 43h        ; 按下的是'C'键吗?

CODE:00709374                 jnz     short loc_7093A7
CODE:00709374
CODE:00709376
CODE:00709376 loc_709376:                             ; CODE XREF: Ctrl_C_press+16j
CODE:00709376                 test    [esp+8+var_8], 4                ; Ctrl键被按住了吗?
CODE:0070937A                 jz      short loc_7093A7                ; 如果ctrl没有被按住,跳开
CODE:0070937A
CODE:0070937C                 call    sub_433690                ;开始处理  ctrl-c 的
CODE:0070937C
CODE:00709381                 call    sub_432F98
CODE:00709381
CODE:00709386                 mov     eax, [ebp+218h]
CODE:0070938C                 call    sub_404354
CODE:0070938C
CODE:00709391                 push    eax
CODE:00709392                 call    sub_433690
CODE:00709392
CODE:00709397                 pop     edx
CODE:00709398                 call    sub_433184
CODE:00709398
CODE:0070939D                 mov     eax, offset s_NX ;         ;ctrl-c 事件处理完毕
CODE:007093A2                 call    sub_464B9C
CODE:007093A2
CODE:007093A7
2007-2-13 11:45
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
最初由 Vegeta 发布
LZ不会是穷举注册码吧?

有个变通的方法,可以控制究竟谁能响应CTRL+A,还不是很完美,继续研究中……


........


当然不会去穷举注册码了。

使用keybd_event可能会影响前台程序的操作。比如word输入时,突然ctrl键被莫名按下。
2007-2-13 11:52
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
终于弄了个笨办法搞定了:直接修改目标程序,把检测ctrl的地方干掉,把ctrl-c的检测部分改为检测单字符F11,刚好F11这个键目标程序本身没有用到。

这个办法可以达到操控我的这个程序在后台运行了,但是实现方法不佳,通用性不强。个人认为好的办法还是应该inject & hook api。 hookapi的办法通用性比较强,向后台窗口发送组合键应该没有问题,有时间了一定要学一下。
2007-2-14 00:56
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
18
EDIT控件不响应CTRL+A,记事本里的是主窗口响应,然后发消息EM_SETSEL给EDIT控件.

另:你传上来的那段代码不是记事本里的吧.
2007-2-14 16:03
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
最初由 Vegeta 发布
EDIT控件不响应CTRL+A,记事本里的是主窗口响应,然后发消息EM_SETSEL给EDIT控件.

另:你传上来的那段代码不是记事本里的吧.


不是记事本的代码。
我觉得应该是 EDIT控件相应的。 我按照dwing说的,按住ctrl键,然后向notepad的Edit控件发postmessage(key_down ,'A')就能够实现全选。
2007-2-14 18:09
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
20
前天我自己写了个对话框程序,上面放了个EDIT,运行后执行CTRL+A没有全选的效果.看记事本里的一段代码:

/*
01002ECD  |.^\0F85 32FDFFFF JNZ notepad.01002C05
01002ED3  |.  FF35 30980001 PUSH DWORD PTR DS:[1009830]              ; /hWnd = 000F03E2 ('无标题 - 记事本',class='Notepad'); Case 19 of switch 01002BBE
01002ED9  |.  FF15 64120001 CALL DWORD PTR DS:[<&USER32.GetMenu>]    ; \GetMenu
01002EDF  |.  8B3D 40120001 MOV EDI,DWORD PTR DS:[<&USER32.SendMessa>;  USER32.SendMessageW
01002EE5  |.  56            PUSH ESI                                 ; /lParam
01002EE6  |.  56            PUSH ESI                                 ; |wParam
01002EE7  |.  6A 0E         PUSH 0E                                  ; |Message = WM_GETTEXTLENGTH
01002EE9  |.  FF35 38980001 PUSH DWORD PTR DS:[1009838]              ; |hWnd = 1403EA
01002EEF  |.  8BD8          MOV EBX,EAX                              ; |
01002EF1  |.  FFD7          CALL EDI                                 ; \SendMessageW
01002EF3  |.  50            PUSH EAX                                 ; /lParam
01002EF4  |.  56            PUSH ESI                                 ; |wParam
01002EF5  |.  68 B1000000   PUSH 0B1                                 ; |Message = EM_SETSEL
01002EFA  |.  FF35 38980001 PUSH DWORD PTR DS:[1009838]              ; |hWnd = 1403EA
01002F00  |.  FFD7          CALL EDI                                 ; \SendMessageW

*/

当按下CTRL+A的时候:
hWnd = 000F03E2 ('无标题 - 记事本',class='Notepad'); Case 19 of switch 01002BBE

然后向EDIT里发送EM_SETSEL消息.

后悔没系统的学习WIN编程...
2007-2-15 12:28
0
游客
登录 | 注册 方可回帖
返回
//