能力值:
( LV4,RANK:50 )
|
-
-
2 楼
用Spy++查看Notepad接收到哪些ctrl-a的消息.
|
能力值:
( LV12,RANK:290 )
|
-
-
3 楼
KEYDOWN就可以吧
|
能力值:
( 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
|
能力值:
( 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;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
先感谢Vegeta的指导。
上述代码的确可以实现ctrl-a的功能。但是确不是我所需要的。
上述代码是通过发送select all消息过去,而不是发送ctrl-a消息。如果notepad把ctrl-a的功能改成完成其他某特定功能,而这个特定功能不能通过发送 EM_类的消息代替的。我现在想实现的是发送ctrl-a消息过去,让程序自己去处理。
(换个问题:如何发送 ctrl-p或ctrl-f按键?)
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
在网上搜了几天,没能搞定。发现网上问这个问题的人还比较多,似乎还没有好的解决方案。最恰当的问法是:
如何用SendMessage向另一程序的非焦点的窗口发送组合键?
|
能力值:
( LV4,RANK:50 )
|
-
-
8 楼
我怀疑编辑框控件在接收到"A"键的KEYDOWN消息时判断当前CTRL键的状态,而不是根据是否前面是否有CTRL键的KEYDOWN消息.
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
最初由 dwing 发布 我怀疑编辑框控件在接收到"A"键的KEYDOWN消息时判断当前CTRL键的状态,而不是根据是否前面是否有CTRL键的KEYDOWN消息.
不是这样。我把ctrl按住不放,然后发送一个A的WM_KEYDOWN消息过去,没有效果。
|
能力值:
( LV4,RANK:50 )
|
-
-
10 楼
最初由 auser 发布 不是这样。我把ctrl按住不放,然后发送一个A的WM_KEYDOWN消息过去,没有效果。
我试过了,是有效果的,只发送'A'的KEYDOWN和KEYUP消息,按住CTRL键就能全选.
但要注意使用PostMessage.
|
能力值:
( LV12,RANK:530 )
|
-
-
11 楼
用keybd_event可以,但不符合LZ要求.
SendMessage我没试成功。
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
最初由 dwing 发布 我试过了,是有效果的,只发送'A'的KEYDOWN和KEYUP消息,按住CTRL键就能全选. 但要注意使用PostMessage.
看来只能用api hook,把GetKeyStat,GetKeyboardState,GetAsyncKeyState挂住,返回ctrl被按下的假相。
hook api对我来说,难度太大了,看起来是一个不可能完成的任务。
我的本意是操控一个软件在后台完成一系列的功能(全部操作完成可能需数小时)。如果使用keybd_event,的确可以完成模拟组合键,但是这样,操控过程就必须在前台完成,这时候我就不能用计算机搞别的事情了。
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
我做过类似的工作,与LZ的不完全相同,应该也是出现了与LZ相似的情况,我的理解是:
无论用sendmessage还是postmessage,记事本都已经接收到了按键消息,但有一点要注意的是,由于记事本没有处于激活(当前活动窗口)状态,负责接收消息的是记事本的框架(因为记事本是SDI程序),但框架本身并没有处理CTRL+A的消息代码,所以不会出现“全选”的效果。
简单说一句就是,CTRL+A是属于记事本中编辑框的热键,而失去焦点的编辑框是不会响应CTRL+A的。
(个人怀疑也不是由框架实现的,编辑框是WINDOWS的标准控件,标准控件的消息处理似乎由系统的核心DLL实现的,像标准的界面绘制之类的)
要实现非激活状态下的“全选”,估计 Vegeta 的方法最适合了。
如果想测试按键是否真的被框架接收到了,可以试着把“CTRL+A”改成“F5”(插入当前日期和时间)。
dwing在10楼说的情况,我也不清楚,估计是遇到的实际情况不一样吧。
PS:我很菜,了解得不深入,期待高手
|
能力值:
( 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;
}
|
能力值:
( 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
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
最初由 Vegeta 发布 LZ不会是穷举注册码吧?
有个变通的方法,可以控制究竟谁能响应CTRL+A,还不是很完美,继续研究中……
........
当然不会去穷举注册码了。
使用keybd_event可能会影响前台程序的操作。比如word输入时,突然ctrl键被莫名按下。
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
终于弄了个笨办法搞定了:直接修改目标程序,把检测ctrl的地方干掉,把ctrl-c的检测部分改为检测单字符F11,刚好F11这个键目标程序本身没有用到。
这个办法可以达到操控我的这个程序在后台运行了,但是实现方法不佳,通用性不强。个人认为好的办法还是应该inject & hook api。 hookapi的办法通用性比较强,向后台窗口发送组合键应该没有问题,有时间了一定要学一下。
|
能力值:
( LV12,RANK:530 )
|
-
-
18 楼
EDIT控件不响应CTRL+A,记事本里的是主窗口响应,然后发消息EM_SETSEL给EDIT控件.
另:你传上来的那段代码不是记事本里的吧.
|
能力值:
( LV2,RANK:10 )
|
-
-
19 楼
最初由 Vegeta 发布 EDIT控件不响应CTRL+A,记事本里的是主窗口响应,然后发消息EM_SETSEL给EDIT控件.
另:你传上来的那段代码不是记事本里的吧.
不是记事本的代码。
我觉得应该是 EDIT控件相应的。 我按照dwing说的,按住ctrl键,然后向notepad的Edit控件发postmessage(key_down ,'A')就能够实现全选。
|
能力值:
( 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编程...
|
|
|