我编写的模拟键盘程序,无法在浏览器的地址栏里面连续输入字符,只能输入一个字符?
而且不知有什么办法取得浏览器里面网页含有的输入窗口的焦点!,那位做过模拟键盘的高人,指点一下!.

解决方案 »

  1.   

    IE 浏览器本身是一个COM服务程序
    其实要在它的地址栏里面输入地址,用下面的方法来实现var
      ShellWindow: IShellWindows;
      vi: OleVariant;
      spDisp: IDispatch;
      IDoc1: IHTMLDocument2;
      i: integer;
      nCount: integer;
      IE1: IWebBrowser2;
      Address, p1, p2, p3, p4: OleVariant;
    begin
      ShellWindow := CoShellWindows.Create;
      nCount := ShellWindow.Count;
      for i := 0 to nCount-1 do
      begin
        vi := i;
        spDisp := ShellWindow.Item(vi);
        spDisp.QueryInterface( iWebBrowser2, IE1);
        if IE1 <> nil then
        begin
          IE1.Document.QueryInterface(IHTMLDocument2,iDoc1);
          if iDoc1 <> nil then
          begin
            if IDoc1.title = '网易' then
            begin
              address := 'www.csdn.net';
              IE1.Navigate(address,p1,p2,p3,p4);
            end;
          end;
        end;
      end;
    end;
    上面的程序是让当前title为'网易'的页面去浏览'www.csdn.net'
    IHTMLDocument可以完全的控制IE,包括里面的表单
      

  2.   

    我这有个函数得到当前正在输入控件的Handle 
    function TForm1.GetSysFocus: Integer;
    var
      hOtherWin,OtherThreadID,hFocusWin:integer;
    begin
      hOtherWin:=GetForegroundWindow;
      OtherThreadID:=GetWindowThreadProcessID(hOtherWin,nil);
      if AttachThreadInput(GetcurrentThreadID,OtherThreadID,True) then
      begin
        hFocusWin:=GetFocus;
        result:=GetFocus;
      if HFocusWin<>0 then
      try
      //SendMessage(GetFocus,WM_COPY,0,0);//书上是这么写的
      finally
        AttachThreadInput(GetcurrentThreadID,OtherThreadID,False);
      end;
      end
      else result:=GetFocus;
    end;
      

  3.   

    看看下面代码:模拟键盘'a'输入keybd_event(65,0,KEYEVENTF_EXTENDEDKEY,0); //KEYDOWN,keybd_event(65,0,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0); //KEYUP以上可成功实现,但我想按模拟Ctrl+Shift切换输入法keybd_event(VK_MODECHANGE,0,KEYEVENTF_EXTENDEDKEY,0); //KEYDOWN,keybd_event(VK_MODECHANGE,0,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0); //KEYUP却不能实现,谁能帮忙。为什么????
      

  4.   

    可以用JournalPlayback Windows Hook实现 
    DDG5第13章有个Demo, 你可以去看看。SendKey.pas内容如下:unit SendKey;interfaceusesSysUtils, Windows, Messages, Classes, KeyDefs;type{ Error codes }TSendKeyError = (sk_None, sk_FailSetHook, sk_InvalidToken,sk_UnknownError, sk_AlreadyPlaying);{ first vk code to last vk code }TvkKeySet = set of vk_LButton..vk_Scroll;{ exceptions }ESendKeyError = class(Exception);ESKSetHookError = class(ESendKeyError);ESKInvalidToken = class(ESendKeyError);ESKAlreadyPlaying = class(ESendKeyError);function SendKeys(S: String): TSendKeyError;procedure WaitForHook;procedure StopPlayback;varPlaying: Boolean;implementationuses Forms;type{ a TList descendant that know how to dispose of its contents }TMessageList = class(TList)publicdestructor Destroy; override;end;const{ valid "sys" keys }vkKeySet: TvkKeySet = [Ord('A')..Ord('Z'), vk_Menu, vk_F1..vk_F12]; destructor TMessageList.Destroy;vari: longint;begin{ deallocate all the message records before discarding the list }for i := 0 to Count - 1 doDispose(PEventMsg(Items[i]));inherited Destroy;end;var{ variables global to the DLL }MsgCount: word = 0;MessageBuffer: TEventMsg;HookHandle: hHook = 0;MessageList: TMessageList = Nil;AltPressed, ControlPressed, ShiftPressed: Boolean;procedure StopPlayback;{ Unhook the hook, and clean up }begin{ if Hook is currently active, then unplug it }if Playing thenUnhookWindowsHookEx(HookHandle);MessageList.Free;Playing := False;end;function Play(Code: integer; wParam, lParam: Longint): Longint; stdcall;{ This is the JournalPlayback callback function. It is called by }{ Windows when Windows polls for hardware events. The code parameter}{ indicates what to do. }begincase Code ofHC_SKIP:{ HC_SKIP means to pull the next message out of our list. If we}{ are at the end of the list, it's okay to unhook the }{ JournalPlayback hook from here. }begin{ increment message counter }inc(MsgCount);{ check to see if all messages have been played }if MsgCount >= MessageList.Count then StopPlayback{ otherwise copy next message from list into buffer }else MessageBuffer := TEventMsg(MessageList.Items[MsgCount]^);Result := 0;end;HC_GETNEXT:{ HC_GETNEXT means to fill the wParam and lParam with the proper}{ values so that the message can be played back. DO NOT unhook}{ hook from within here. Return value indicates how much time }{ until Windows should playback message. We'll return 0 so that}{ it is processed right away. }begin{ move message in buffer to message queue }PEventMsg(lParam)^ := MessageBuffer;Result := 0 { process immediately }endelse{ if Code isn't HC_SKIP or HC_GETNEXT, call next hook in chain }Result := CallNextHookEx(HookHandle, Code, wParam, lParam);end;end;procedure StartPlayback;{ Initializes globals and sets the hook }begin{ grab first message from list and place in buffer in case we }{ get a hc_GetNext before and hc_Skip }MessageBuffer := TEventMsg(MessageList.Items[0]^);{ initialize message count and play indicator }MsgCount := 0;{ initialize Alt, Control, and Shift key flags }AltPressed := False;ControlPressed := False;ShiftPressed := False;{ set the hook! }HookHandle := SetWindowsHookEx(wh_JournalPlayback, Play, hInstance,0);if HookHandle = 0 thenraise ESKSetHookError.Create('Failed to set hook');Playing := True;end;procedure MakeMessage(vKey: byte; M: Cardinal);{ procedure builds a TEventMsg record that emulates a keystroke and }{ adds it to message list }varE: PEventMsg;beginNew(E); // allocate a message recordwith E^ dobeginmessage := M; // set message fieldparamL := vKey; // vk code in ParamLparamH := MapVirtualKey(vKey, 0); // scan code in ParamHtime := GetTickCount; // set timehwnd := 0; // ignoredend;MessageList.Add(E);end;procedure KeyDown(vKey: byte);{ Generates KeyDownMessage }begin{ don't generate a "sys" key if the control key is pressed }{ (This is a Windows quirk) }if AltPressed and (not ControlPressed) and (vKey in vkKeySet) thenMakeMessage(vKey, wm_SysKeyDown)elseMakeMessage(vKey, wm_KeyDown);end;procedure KeyUp(vKey: byte);{ Generates KeyUp message }begin{ don't generate a "sys" key if the control key is pressed }{ (This is a Windows quirk) }if AltPressed and (not ControlPressed) and (vKey in vkKeySet) then
      

  5.   

    接上文MakeMessage(vKey, wm_SysKeyUp)elseMakeMessage(vKey, wm_KeyUp);end;procedure SimKeyPresses(VKeyCode: Word);{ This function simulates keypresses for the given key, taking into }{ account the current state of Alt, Control, and Shift keys }begin{ press Alt key if flag has been set }if AltPressed thenKeyDown(vk_Menu);{ press Control key if flag has been set }if ControlPressed thenKeyDown(vk_Control);{ if shift is pressed, or shifted key and control is not pressed...}if (((Hi(VKeyCode) and 1) <> 0) and (not ControlPressed)) orShiftPressed thenKeyDown(vk_Shift); { ...press shift }KeyDown(Lo(VKeyCode)); { press key down }KeyUp(Lo(VKeyCode)); { release key }{ if shift is pressed, or shifted key and control is not pressed...}if (((Hi(VKeyCode) and 1) <> 0) and (not ControlPressed)) orShiftPressed thenKeyUp(vk_Shift); { ...release shift }{ if shift flag is set, reset flag }if ShiftPressed then beginShiftPressed := False;end;{ Release Control key if flag has been set, reset flag }if ControlPressed then beginKeyUp(vk_Control);ControlPressed := False;end;{ Release Alt key if flag has been set, reset flag }if AltPressed then beginKeyUp(vk_Menu);AltPressed := False;end;end;procedure ProcessKey(S: String);{ This function parses each character in the string to create the }{ message list }varKeyCode: word;Key: byte;index: integer;Token: TKeyString;beginindex := 1;repeatcase S[index] ofKeyGroupOpen:{ It's the beginning of a special token! }beginToken := '';inc(index);while S[index] <> KeyGroupClose do begin{ add to Token until the end token symbol is encountered }Token := Token + S[index];inc(index);{ check to make sure the token's not too long }if (Length(Token) = 7) and (S[index] <> KeyGroupClose) thenraise ESKInvalidToken.Create('No closing brace');end;{ look for token in array, Key parameter will }{ contain vk code if successful }if not FindKeyInArray(Token, Key) thenraise ESKInvalidToken.Create('Invalid token');{ simulate keypress sequence }SimKeyPresses(MakeWord(Key, 0));end;AltKey: AltPressed := True; // set Alt flagControlKey: ControlPressed := True; // set Control flagShiftKey: ShiftPressed := True; // set Shift flagelse begin{ A normal character was pressed }{ convert character into a word where the high byte contains }{ the shift state and the low byte contains the vk code }KeyCode := vkKeyScan(S[index]);{ simulate keypress sequence }SimKeyPresses(KeyCode);end;end;Inc(index);until index > Length(S);end;procedure WaitForHook;beginrepeat Application.ProcessMessages until not Playing;end;function SendKeys(S: String): TSendKeyError;{ This is the one entry point. Based on the string passed in the S }{ parameter, this function creates a list of keyup/keydown messages, }{ sets a JournalPlayback hook, and replays the keystroke messages. }beginResult := sk_None; // assume successtryif Playing then raise ESKAlreadyPlaying.Create('');MessageList := TMessageList.Create; // create list of messagesProcessKey(S); // create messages from stringStartPlayback; // set hook and play back messagesexcept{ if an exception occurs, return an error code, and clean up }on E:ESendKeyError dobeginMessageList.Free;if E is ESKSetHookError thenResult := sk_FailSetHookelse if E is ESKInvalidToken thenResult := sk_InvalidTokenelse if E is ESKAlreadyPlaying thenResult := sk_AlreadyPlaying;endelseResult := sk_UnknownError; // Catch-all exception handlerend;end;end. 
      

  6.   

    用GetFocus获得,在某些操作系统下你可能还需要用AttachThreadInput:function TSysFocus.GetSysFocus : integer;//取当前活动窗口 
    var 
    hOtherWin,OtherThreadID,hFocusWin:integer; 
    begin 
    hOtherWin:=GetForegroundWindow; 
    OtherThreadID:=GetWindowThreadProcessID(hOtherWin,nil); 
    if AttachThreadInput(GetcurrentThreadID,OtherThreadID,True) then 
    begin 
    hFocusWin:=GetFocus; 
    result:=GetFocus; 
    if HFocusWin<>0 then 
    AttachThreadInput(GetcurrentThreadID,OtherThreadID,False) 
    else result:=GetFocus; 
    end; 
      

  7.   

    参考:
    http://www.pconline.com.cn/pcedu/empolder/gj/cb/10206/65594_1.htmlBCB代码,看看原理
      

  8.   

    我做过不论是APP还是OCX,最主要是要让你点击时你的东西不能有焦点