如何向一个窗体发送组合键CTRL+P,这个窗体有可能不在最前,也有可能最小化了,keybd_event好像不行

解决方案 »

  1.   

    SendMessage(handle, WM_CHAR, aChar, aKeyData)
    其中handle为接受CTRL+A的窗体的句柄,
    aChar = "P"
    aKeyData = 32位
    0-15位:指定当前消息的重复次数。其值就是用户按下该键后自动重复的次数,但是重复次数不累积
    16-23位:指定其扫描码,其值依赖于OEM厂商
    24位:指定该按键是否为扩展按键,所谓扩展按键就是Ctrl,Alt之类的,如果是扩展按键,其值为1,否则为0 
    25-28位:保留字段,暂时不可用 
    29位:指定按键时的上下文,其值为1时表示在按键时Alt键被按下,其值为0表示WM_SYSKEYDOWN消息因没有任何窗口有键盘焦点而被发送到当前活动窗口。 
    30位:指定该按键之前的状态,其值为1时表示该消息发送前,该按键是被按下的,其值为0表示该消息发送前该按键是抬起的。 
    31位:指定其转换状态,对WM_SYSKEYDOWN消息而言,其值总为0。
    0x11  =VK_CONTROL 
    0x0104=WM_SYSKEYDOWN 
    0x0106=WM_SYSCHAR
    0x0105=WM_SYSKEYUPSendMessage(hwnd, 0x0104, 0x11, 0x20380001);//首先 发送了一个Ctrl按下
    SendMessage(hwnd, 0x0104, (int)'P', 0x20210001);//然后发送了一个'P'键 
    SendMessage(hwnd, 0x0106, (int)'p', 0x20210001);// 然后发送了一个字符'p'
    SendMessage(hwnd, 0x0105, 0x11, 0xC0380001);//最后抬起按键CTRL键
      

  2.   

    TO  草原之魂
    SendMessage(edit1.handle, WM_SYSKEYDOWN, VK_CONTROL, $20380001);//首先 发送了一个Ctrl按下
      SendMessage(edit1.handle, WM_SYSKEYDOWN, 80, $20210001);//然后发送了一个'P'键
      SendMessage(edit1.handle, 106, 80, $20210001);// 然后发送了一个字符'p'
      SendMessage(edit1.handle, 105, VK_CONTROL, $C0380001);//最后抬起按键CTRL键
    这个是ALT+P,查了下资料和你说的一样,但是我测试程序这样发送消息,只有ALT响应,CTRL,SHIFT没有反应
      

  3.   

    SendMessage(edit1.handle, WM_SYSKEYDOWN, VK_CONTROL, $20380001);//首先 发送了一个Ctrl按下 
      SendMessage(edit1.handle, WM_SYSKEYDOWN, 80, $20210001);//然后发送了一个'P'键 
      SendMessage(edit1.handle, $106, 80, $20210001);// 然后发送了一个字符'p' 
      SendMessage(edit1.handle, $105, VK_CONTROL, $C0380001);//最后抬起按键CTRL键 显示同时按下的是ALT
      

  4.   


    测试通过~~
    procedure TForm1.Button2Click(Sender: TObject);
      var
          KeyState:   TKeyboardState;
      begin
          GetKeyboardState(KeyState);
          KeyState[VK_CONTROL]:=not KeyState[VK_CONTROL];//ctrl->down
          SetKeyboardState(KeyState);
          SendMessage(edit1.Handle,WM_KEYDOWN,WPARAM('P'),0);
          GetKeyboardState(KeyState);
          KeyState[VK_CONTROL]:=not KeyState[VK_CONTROL];//ctrl->up
          SetKeyboardState(KeyState);
    end;
      

  5.   

    呵呵,你肯定是在同一进程下,我是要操作其他进程的窗体,那个窗体还有可能最小化了,SetKeyboardState只能设置当前进程的按键状态。谢谢,还有别的方法么?
    你开始给的SendMessage参数我怎么调试都只有ALT可行,CTRL和SHIFT都不会出现按下状态
      

  6.   

    SendMessage发送不了组合键,只能使窗体最前,模拟按键。
      

  7.   

    你要的功能不一定好实现,但可以变通实现。如果原程序不处于当前活动状态,那么CTRL+p键并不能被原程序接受。除非CTRL+p是全局的(不过可能性较小)。CTRL+P如果是原程序的一个菜单的快捷键,可以尝试进行模拟菜单输入。无论是最小化还是隐藏了或是被其它窗口挡住,都可以实现。于是你的问题解决了。
      

  8.   

    SendMessage可以发Ctrl+P,
    刚回来看了一下,这贴到现在还没人给答案,于是对自己的代码也没信心了,
    于是又测试了一下,实践证明,WM_KEYDOWN完全可以做到
      

  9.   


    var
      wnd:hwnd;
    procedure TForm1.Button1Click(Sender: TObject);
    var
      ScanCode : Word;
      lParam, Oem: longint;
    begin
    //按CTRL
      ScanCode:= MapVirtualKey($11, 0);
      lParam:= longint(ScanCode) shl 16 or 1;
      SendMessage(wnd, WM_KEYDOWN, $11, lParam);
    //按CTRL+P
      Oem:= OemKeyScan(ord('P'));
      ScanCode:= Oem and $000000FF or $FF00;//从OemKey提取0000XX00做ScanCode,这步估计难倒不少人,国内更没这方面资料,感慨一下
      lParam:= longint(ScanCode) shl 16 or 1;//按MSDN上的说明,把它放到16bit的位置去,然后or 1设置只发送一次
      SendMessage(wnd, WM_KEYDOWN, ord(Key), lParam);
      SendMessage(wnd, WM_CHAR, ord(Key), lParam);
    //松开CTRL+P
      lParam:= lParam or $C0000000;//松开CTRL
      SendMessage(wnd, WM_KEYUP, ord(Key), lParam);
    //松开CTRL
      ScanCode:= MapVirtualKey($11, 0);
      lParam:= longint(ScanCode) shl 16 or 1;
      lParam:= lParam or $C0000000;
      SendMessage(wnd, WM_KEYDOWN, $11, lParam);
    //打完收功!
    end;楼主是不是要考虑加点分 ^_^
      

  10.   

    忘了说明,就是发送带CTRL的键时,如果设置过错误的参数,可能会影响后续测试
    我的机器上就遇到过这样的现象,不知道是不是个别现象
    所以,在测试代码时如果无效,最好是重启后再测试
      

  11.   

    wnd为0没有效果。
    不过还是收藏了。