Quantcast Delphi Command to Control Another Application? - digitalFAQ.com Forums [Archives]
  #1  
06-16-2003, 11:20 AM
GFR GFR is offline
Free Member
 
Join Date: May 2002
Posts: 438
Thanks: 0
Thanked 0 Times in 0 Posts
Hi,

There's a VB command (I think it's SendKey) that allows you to control another application by sending hotkeys to it (like you open TMPGEnc and your VB program can set the Video Source sending an "ALT-V" to TMPGEnc).

Does anybody knows how to do the same thing with Delphi? I thougth of getting the handler of the application and putting a message in the Windows message queue using the Windows API, but that would be much easier with a single command like in VB

Thanks.
Reply With Quote
Someday, 12:01 PM
admin's Avatar
Site Staff / Ad Manager
 
Join Date: Dec 2002
Posts: 42
Thanks: ∞
Thanked 42 Times in 42 Posts
  #2  
06-16-2003, 09:50 PM
vhelp vhelp is offline
Free Member
 
Join Date: Jan 2003
Posts: 1,009
Thanks: 0
Thanked 0 Times in 0 Posts
hI GFR.. pal..

I broke these out into TWO parts (cause they are)
Also, if some of the CODE start to break-off onto other line, try and
MAXimize your browser. I tried to clean up the code as much as
possible, but my eyes are going cookoo.. you know

Note, I was SURE that Delphi had sendkey support built-in,
but looks like it doesn't, though their is special D/L that does have
a sendkeys unit, but I don't like registering all the time.

I hope this code snipplet helps some in YOUR coding.. Well, have
a look and see if it helps any, else good luck anyways.. hehe..

-vhelp
--- ---- --- ---- --- ---- --- ---- --- ---- --- ----

Part 1 of 2

These functions may be useful. They always send keys to the ACTIVE
window.

Code:
{
 ************************************************************
 * Procedure PostKeyEx32
 *
 * Parameters:
 *  key    : virtual keycode of the key to send. For printable
 *           keys this is simply the ANSI code (Ord(character)).
 *  shift  : state of the modifier keys. This is a set, so you
 *           can set several of these keys (shift, control, alt,
 *           mouse buttons) in tandem. The TShiftState type is 
 *           declared in the Classes Unit.
 *  specialkey: normally this should be False. Set it to True to 
 *           specify a key on the numeric keypad, for example. 
 * Description:
 *  Uses keybd_event to manufacture a series of key events matching 
 *  the passed parameters. The events go to the control with focus.
 *  Note that for characters key is always the upper-case version of
 *  the character. Sending without any modifier keys will result in
 *  a lower-case character, sending it with [ssShift] will result
 *  in an upper-case character!
 * Created: 17.7.98 by P. Below
 ************************************************************
}

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..3] of 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),
                     0, 0);
    End; { For }
    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; { PostKeyEx32 }

Procedure SendText( S: String );

  Procedure SendRawCharacter( ch : Char );
    Var
      i: Integer;
      numStr: String;

    Begin

      numStr := Format('%4.4d',[Ord(ch)]);

      keybd_event( VK_MENU, MapVirtualKey(VK_MENU, 0),
                   0, 0);
      for i:= 1 to Length(numStr) do
        PostKeyEx32( VK_NUMPAD0 + Ord(numstr[i])-Ord('0'), [],
                     false );
        keybd_event( VK_MENU, MapVirtualKey(VK_MENU, 0),
                     KEYEVENTF_KEYUP, 0);
    End;

  Var
    flags: TShiftState;
    vcode: word;
    ret  : word;
    i, n : Integer;
    mask : word;

  Begin { SendText }
    For i := 1  To Length(S) Do Begin
      ret := VkKeyScan( S[i] );
      If ret = $FFFF Then
        SendRawCharacter( S[i] )
      Else Begin
        vcode := Lobyte( ret );
        flags := [];
        mask  := $100;
        For n := 1 To 3 Do Begin
          If (ret and mask) <> 0 Then Begin
            Case mask Of
              $100: Include( flags, ssShift );
              $200: Include( flags, ssCtrl );
              $400: Include( flags, ssAlt );
            End; { Case }
          End; { If }
          mask := mask shl 1;
        End; { For }
        PostKeyEx32( vcode, flags, false );
      End; { Else }
    End; { For }
  End; { SendText }
{
Peter Below (TeamB) 100113.1101@compuserve.com)
No replies in private e-mail, please, unless explicitly
requested!

End of Part 1 of 2
}
Reply With Quote
  #3  
06-16-2003, 10:02 PM
vhelp vhelp is offline
Free Member
 
Join Date: Jan 2003
Posts: 1,009
Thanks: 0
Thanked 0 Times in 0 Posts
.
.
and don't forget Part 2 of 2 here..

Note, I'm gonna include a "definition" file I got on the net on the
different codes for each key and so on and so forth.. I think it's
important to have this close by for your "key" referencing

Remember to MAXimize your browser, in case source CODE gets
snipped to other line.

I know I've done this in Delphi 3. I'm sure that IT had sendkey
support built-in, but my memory is slowly fading away.. Too much
coding i guess..

If this is not what you are looking for (in a project) just keep on
looking. I'll keep my eye out too

-vhelp



PART 2 of 2

{
The following unit is what I use, example:

PostKeyEx (GetWindowsHandle("THE_CAPTION_OF_THE_WINDOW")

for instructions on the rest look later on before the
PostKeyEx32 procedure.

There are other ways to get the window handle, but I
worked this out for what I needed it. One problem
could arise if you have to windows with the same caption
then this will post the key to the first window with
the CAPTION hope this helps
}

Code:
unit MyUtilsUnt;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TMyUtils = class(TForm)
    function GetWindowHandle (WindowName:string):integer;
  Procedure PostKeyEx( hWindow: HWnd; key: Word; Const shift:
                                  TShiftState;specialkey: Boolean );
  Procedure PostKeyEx32( key: Word; Const shift: TShiftState;
                     specialkey: Boolean );
  Procedure SendText( S: String );
  function FileSizeMy (jsFile:string):integer;
  private
    { Private declarations }
  public
    { Public declarations }

  end;

var
  MyUtils: TMyUtils;
  StrListHand,StrListName:TStringList;
implementation

{$R *.DFM}


type
  EnumWindowsProc = function (Hwnd: THandle;
    Param: Pointer): boolean; stdcall;

function GetTitle (Hwnd: THandle; Param: Pointer): Boolean; stdcall;
var
  Text,tmp: string;
begin
   SetLength (Text, 100);
   GetWindowText (Hwnd, PChar (Text), 100);
     StrListHand.Add (IntToStr (HWND));
     tmp := StrListHand.Strings[StrListHand.count-1];
     StrListName.Insert (StrListHand.Count-1,Text);
  file://MyUtils.ListBox1.Items.Add (IntToStr (Hwnd) + ': ' + Text);
  Result := True;
end;

procedure FOrmerBtn;
var
  EWProc: EnumWindowsProc;
begin
 // ListBox1.Items.Clear;
  EWProc := GetTitle;
  EnumWindows (@EWProc, 0);
end;

function TMyUtils.GetWindowHandle (WindowName:string):integer;
var tmpResult:integer;
begin
 result := 0;
 try file://exception
 try file://finally
   StrListHand := TStringList.Create;
   StrListName := TStringList.Create;
 FOrmerBtn;
  tmpResult := StrToInt (StrListHand.Strings[StrListName.IndexOf
                        (WindowName)]);
    if tmpResult > 0 then
     Result := tmpResult;
         finally
     StrListHand.free;
     StrListName.Free;
    end;
 except
   result := 0;
 end;
end;

Procedure TMyUtils.PostKeyEx( hWindow: HWnd; key: Word; Const shift:
                              TShiftState; specialkey: Boolean );
Type
  TBuffers = Array [0..1] of TKeyboardState;
Var
  pKeyBuffers : ^TBuffers;
  lparam: LongInt;

Begin
(* check if the target window exists *)

 If IsWindow(hWindow) Then Begin

(* set local variables to default values *)

 pKeyBuffers := Nil;
 lparam := MakeLong(0, MapVirtualKey(key, 0));

(* modify lparam if special key requested *)

 If specialkey Then
 lparam := lparam or $1000000;

(* allocate space for the key state buffers *)

 New(pKeyBuffers);
 try

(* Fill buffer 1 with current state so we can later restore it.
   Null out buffer 0 to get a "no key pressed" state. *)

 GetKeyboardState( pKeyBuffers^[1] );
 FillChar(pKeyBuffers^[0], Sizeof(TKeyboardState), 0);

(* set the requested modifier keys to "down" state in the buffer *)

 If ssShift In shift Then pKeyBuffers^[0][VK_SHIFT] := $80;

 (* Alt needs special treatment since a bit in lparam needs also be set *)
 If ssAlt In shift Then Begin
   pKeyBuffers^[0][VK_MENU] := $80;
   lparam := lparam or $20000000;
 End;

If ssCtrl In shift Then pKeyBuffers^[0][VK_CONTROL] := $80;
If ssLeft In shift Then pKeyBuffers^[0][VK_LBUTTON] := $80;
If ssRight In shift Then pKeyBuffers^[0][VK_RBUTTON] := $80;
If ssMiddle In shift Then pKeyBuffers^[0][VK_MBUTTON] := $80;

(* make out new key state array the active key state map *)

 SetKeyboardState( pKeyBuffers^[0] );

(* post the key messages *)

If ssAlt In Shift Then Begin
 PostMessage( hWindow, WM_SYSKEYDOWN, key, lparam);
 PostMessage( hWindow, WM_SYSKEYUP, key, lparam or $C0000000);
End
Else Begin
 PostMessage( hWindow, WM_KEYDOWN, key, lparam);
 PostMessage( hWindow, WM_KEYUP, key, lparam or $C0000000);
End;

(* process the messages *)
Application.ProcessMessages;

(* restore the old key state map *)
 SetKeyboardState( pKeyBuffers^[1] );
 finally

(* free the memory for the key state buffers *)
 If pKeyBuffers <> Nil Then
 Dispose( pKeyBuffers );
End; { If }
End;
End; { PostKeyEx }

{************************************************************
 * Procedure PostKeyEx32
 *
 * Parameters:
 *  key    : virtual keycode of the key to send.
 *  shift  : state of the modifier keys. This is a set, so you
 *           can set several of these keys (shift, control, alt,
 *           mouse buttons) in tandem. The TShiftState type is
 *           declared in the Classes Unit.
 *  specialkey: normally this should be False. Set it to True to
 *           specify a key on the numeric keypad, for example.
 * Description:
 *  Uses keybd_event to manufacture a series of key events matching
 *  the passed parameters. The events go to the control with focus.
 *  Note that for characters key is always the upper-case version of
 *  the character. Sending without any modifier keys will result in
 *  a lower-case character, sending it with [ssShift] will result
 *  in an upper-case character!
 * Created: 17.7.98 by P. Below
 ************************************************************}

Procedure TMyutils.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..3] of 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),
                     0, 0);
    End; { For }
    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; { PostKeyEx32 }


Procedure TMyUtils.SendText( S: String );
  Procedure SendRawCharacter( ch : Char );
    Var
      i: Integer;
      numStr: String;
    Begin
      numStr := Format('%4.4d',[Ord(ch)]);
      keybd_event( VK_MENU, MapVirtualKey(VK_MENU, 0),
                   0, 0);
      for i:= 1 to Length(numStr) do
        PostKeyEx32( VK_NUMPAD0 + Ord(numstr[i])-Ord('0'), [], false );
      keybd_event( VK_MENU, MapVirtualKey(VK_MENU, 0),
                   KEYEVENTF_KEYUP, 0);
    End;

  Var
    flags: TShiftState;
    vcode: word;
    ret  : word;
    i, n : Integer;
    mask : word;
  Begin { SendText }
    For i := 1  To Length(S) Do Begin
      ret := VkKeyScan( S[i] );
      If ret = $FFFF Then
        SendRawCharacter( S[i] )
      Else Begin
        vcode := Lobyte( ret );
        flags := [];
        mask  := $100;
        For n := 1 To 3 Do Begin
          If (ret and mask) <> 0 Then Begin
            Case mask Of
              $100: Include( flags, ssShift );
              $200: Include( flags, ssCtrl );
              $400: Include( flags, ssAlt );
            End; { Case }
          End; { If }
          mask := mask shl 1;
        End; { For }
        PostKeyEx32( vcode, flags, false );
      End; { Else }
    End; { For }
  End; { SendText }



function TMyUtils.FileSizeMy (jsFile:string):integer;
 var
 tmpFile :file;
begin
 AssignFile (tmpFile,jsFile);
 Reset (tmpFile);
 Result := FileSize (tmpFile);
 CloseFile (tmpFile);
end;

end.
{
"Chris" <chris@lycos.ltd.uk> wrote in message news:3b2fac1b_1@dnews...
> Can anyone give some code does a SendKey to another application assuming
> you've got the hWnd for that app.
>
> I've tried a few PostMessage / WM_CHAR variants but really sure what all
> those parameters should be.
>
> Thanks
>
> Chris
>

End of Part 2 of 2
}
Reply With Quote
  #4  
06-16-2003, 10:10 PM
vhelp vhelp is offline
Free Member
 
Join Date: Jan 2003
Posts: 1,009
Thanks: 0
Thanked 0 Times in 0 Posts
@ GFR..

Weather or not you can use these key codes in the list provided below,
it may serve to help you w/ keys and things in other projects.

This list is based on the Visual Basic list, which is what you want anyways.

Good luck

-vhelp



Code:
Supports the Visual Basic SendKeys syntax, as documented below.

Supported modifiers:

+ = Shift
^ = Control
% = Alt

Surround sequences of characters or key names with parenthesis in
order to modify them as a group.  For example, '+abc' shifts only 'a',
while '+(abc)' shifts all three characters.

Supported special characters

~ = Enter
( = Begin modifier group (see above)
) = End modifier group (see above)
{ = Begin key name text (see below)
} = End key name text (see below)

Supported characters:

Any character than can be typed is supported.  Surround the modifier keys
listed above with braces in order to send as normal text.

Supported key names (surround these with braces):

BKSP, BS, BACKSPACE
BREAK
CAPSLOCK
CLEAR
DEL
DELETE
DOWN
END
ENTER
ESC
ESCAPE
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
F13
F14
F15
F16
HELP
HOME
INS
LEFT
NUMLOCK
PGDN
PGUP
PRTSC
RIGHT
SCROLLLOCK
TAB
UP

Follow the keyname with a space and a number to send the specified key a
given number of times (e.g., {left 6}).
*)
Reply With Quote
  #5  
06-17-2003, 08:33 AM
GFR GFR is offline
Free Member
 
Join Date: May 2002
Posts: 438
Thanks: 0
Thanked 0 Times in 0 Posts
Thanks, vhelp.

I'm saving this and will try to get it working.
Reply With Quote
  #6  
01-25-2004, 01:16 AM
vhelp vhelp is offline
Free Member
 
Join Date: Jan 2003
Posts: 1,009
Thanks: 0
Thanked 0 Times in 0 Posts
Hay GFR.. :P

It's ben a long time since I last heard from you on this sendkey post.

Have you gotten it working yet. If not, I do have code, ..tested and works
fine, if you need it. Let me know :P

Code works in my Delphi 6 projects.


Other news. . .
At the moment, I'm coding a front-end GUI, and just got over a bug w/ a component
that allows me to drag-n drop files in my apps - fun stuff. Anyways.. I've
fixed THAT bug for sure hehe..
The GUI is something I was working on for over a year now, for vcdhelp
on an MPEG-2 cutter.. and up to now, I've procrastinated (other fun projects
in Delphi and encoding projects) But, I basically stopped because the .exe
apps and shell apps just didn't give me what I was looking for, or I just did
not have the energy to complete them (many versions, sheesh)
Anyways.. thanks to kvcd (strikes again) and the links here, I was able to
give this project yet another go this evening.. thanks to mencoder that has
ben floating around here and other forums, I think I am making some
headway. I don't know.. we'll see :P

-vhelp
Reply With Quote
  #7  
01-26-2004, 07:14 AM
GFR GFR is offline
Free Member
 
Join Date: May 2002
Posts: 438
Thanks: 0
Thanked 0 Times in 0 Posts
Quote:
Originally Posted by vhelp
Hay GFR.. :P

It's ben a long time since I last heard from you on this sendkey post.

Have you gotten it working yet. If not, I do have code, ..tested and works
fine, if you need it. Let me know :P

Code works in my Delphi 6 projects.

-vhelp
Sorry... It worked, many thanks. I just forgot to reply...
Reply With Quote
Reply




Similar Threads
Thread Thread Starter Forum Replies Last Post
Nice Network Radio (music) application kwag Computers 7 07-28-2005 10:05 PM
Intranet & CRM application el_mero_zooter Computers 5 12-02-2004 03:24 PM
TMPGEnc: Background Application Run OK? cheung31 Video Encoding and Conversion 1 11-12-2004 01:13 AM
Making a Delphi GUI need some help Zyphon Avisynth Scripting 8 07-06-2004 02:05 AM
An excellent file sharing application kwag Computers 0 09-04-2002 11:12 PM

Thread Tools



 
All times are GMT -5. The time now is 02:29 AM  —  vBulletin Jelsoft Enterprises Ltd