介绍如何通过代码实现模拟按键的函数

作者: 陆岛工作室

Windows API 的 keybd_event 函数,它可以产生键盘消息。实现向其他窗口模拟真实的按键动作。
例如:
  {按下A键} 
  Edit1.SetFocus; 
  keybd_event(VK_SHIFT, 
000); 
  keybd_event(ord(
'A'), 000); 
  keybd_event(VK_SHIFT, 
0, KEYEVENTF_KEYUP, 0); 
  
  
{按下左Window键然后选择“运行”} 
  keybd_event(VK_LWIN, 
000); 
  keybd_event(ord(
'R'), 000); 
  keybd_event(VK_LWIN, 
0, KEYEVENTF_KEYUP, 0); 

KEYBD_EVENT 的函数说明:
函数功能:该函数合成一次击键事件。系统可使用这种合成的击键事件来产生WM_KEYUP或WM_KEYDOWN消息,键盘驱动程序的中断处理程序调用keybd_event函数。在Windows NT中该函数己被使用Sendlhput来替代它。

函数原型;VOID keybd_event(BYTE bVk,BYTE bScan,DWORD dwFlags,DWORD dwExtralnfo);

参数:

    bVk:定义一个虚据拟键码。键码值必须在1~254之间。

    bScan:定义该键的硬件扫描码。

    dwFlags:定义函数操作的名个方面的一个标志位集。应用程序可使用如下一些预定义常数的组合设置标志位。

    KEYEVENTF_EXETENDEDKEY:若指定该值,则扫描码前一个值为OXEO(224)的前缀字节。DEYEVENTF_KEYUP:若指定该值,该键将被释放;若未指定该值,该键交被接下。dwExtralnfo:定义与击键相关的附加的32位值。


根据这个API函数,整理一个完整的函数,方便操作:

procedure PostKey(const mKey: Word; mShiftState: TShiftState; mCount: Integer = 1);  
const   
  cExtended: 
set of Byte = [VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_HOME, VK_END, VK_PRIOR, VK_NEXT, VK_INSERT, VK_DELETE];   
    
  
procedure pKeyboardEvent(mKey,   mScanCode:   Byte;   mFlags:   Longint);   
  
var   
    vKeyboardMsg: TMsg;   
  
begin   
    keybd_event(mKey, mScanCode, mFlags, 
0);   
    
while PeekMessage(vKeyboardMsg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) do 
    
begin   
      TranslateMessage(vKeyboardMsg);   
      DispatchMessage(vKeyboardMsg);   
    
end;   
  
end;
    
  
procedure pSendKeyDown(mKey: Word; mGenUpMsg: Boolean);   
  
var   
    vScanCode: Byte;   
    vNumState: Boolean;   
    vKeyBoardState: TKeyboardState;   
  
begin   
    
if (mKey = VK_NUMLOCK) then
    
begin   
      vNumState :
= ByteBool(GetKeyState(VK_NUMLOCK) and 1);   
      GetKeyBoardState(vKeyBoardState);   
      
if vNumState then   
        vKeyBoardState[VK_NUMLOCK] :
= (vKeyBoardState[VK_NUMLOCK] and not 1)   
      
else 
        vKeyBoardState[VK_NUMLOCK] :
= (vKeyBoardState[VK_NUMLOCK] or 1);   
        
      SetKeyBoardState(vKeyBoardState);   
      Exit;   
    
end;   
  
    vScanCode :
= Lo(MapVirtualKey(mKey, 0));   
    
if (mKey in cExtended) then 
    
begin   
      pKeyboardEvent(mKey, vScanCode, KEYEVENTF_EXTENDEDKEY);   
      
if mGenUpMsg then   
        pKeyboardEvent(mKey, vScanCode, KEYEVENTF_EXTENDEDKEY 
or KEYEVENTF_KEYUP)   
    
end else
    
begin   
      pKeyboardEvent(mKey, vScanCode, 
0);   
      
if mGenUpMsg then pKeyboardEvent(mKey, vScanCode, KEYEVENTF_KEYUP);   
    
end;   
  
end;   {   pSendKeyDown   }   
    
   
procedure pSendKeyUp(mKey: Word);   
   
var   
     vScanCode: Byte;   
   
begin   
     vScanCode :
= Lo(MapVirtualKey(mKey, 0));   
     
if mKey in cExtended then   
       pKeyboardEvent(mKey, vScanCode, KEYEVENTF_EXTENDEDKEY 
and KEYEVENTF_KEYUP)   
     
else 
       pKeyboardEvent(mKey, vScanCode, KEYEVENTF_KEYUP);   
   
end
    
var   
  I: Integer;   
begin   
  
for I := 1 to mCount do
  
begin   
    
if ssShift in mShiftState then pSendKeyDown(VK_SHIFT, False);   
    
if ssCtrl in mShiftState then pSendKeyDown(VK_CONTROL, False);   
    
if ssAlt in mShiftState then pSendKeyDown(VK_MENU, False);   
    pSendKeyDown(mKey,   True);   
    
if ssShift in mShiftState then pSendKeyUp(VK_SHIFT);   
    
if ssCtrl in mShiftState then pSendKeyUp(VK_CONTROL);   
    
if ssAlt in mShiftState then pSendKeyUp(VK_MENU);   
  
end;   
end

另外一处函数也可以实现类似功能。

Procedure PostKeyEx32( key: Word; Const shift: TShiftState; specialkey: Boolean ); 
Type 
  TShiftKeyInfo 
= Record 
    shift: Byte; 
    vkey : Byte; 
  End; 
  
  byteset 
= Set of 0..7
Const 
  shiftkeys: Array [
1..3of TShiftKeyInfo = 
    ((shift: Ord(ssCtrl); vkey: VK_CONTROL ), 
     (shift: Ord(ssShift); vkey: VK_SHIFT ), 
     (shift: Ord(ssAlt); vkey: VK_MENU )); 
Var 
  flag: DWORD; 
  bShift: ByteSet absolute shift; 
  i: Integer; 
Begin 
  
for i := 1 to 3 Do 
  
begin 
   
if shiftkeys[i].shift in bShift Then 
     keybd_event( shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 
0), 00); 
  
end;  
  
  
if specialkey then 
    flag :
= KEYEVENTF_EXTENDEDKEY 
  
else 
    flag :
= 0
 
  keybd_event( key, MapvirtualKey( key, 
0 ), flag, 0 ); 
  flag :
= flag or KEYEVENTF_KEYUP; 
  keybd_event( key, MapvirtualKey( key, 
0 ), flag, 0 ); 
 
  
for i := 3 downto 1 do 
  
begin 
   If shiftkeys[i].shift In bShift Then 
   keybd_event( shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 
0), KEYEVENTF_KEYUP, 0); 
  
end{ For } 
End; 

posted @ 2008-06-09 13:08  陆岛工作室  阅读(...)  评论(...编辑  收藏