06-16-2003, 11:20 AM
|
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.
|
Someday, 12:01 PM
|
|
Site Staff / Ad Manager
|
|
Join Date: Dec 2002
Posts: 42
Thanks: ∞
Thanked 42 Times in 42 Posts
|
|
|
06-16-2003, 09:50 PM
|
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
}
|
06-16-2003, 10:02 PM
|
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
}
|
06-16-2003, 10:10 PM
|
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}).
*)
|
06-17-2003, 08:33 AM
|
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.
|
01-25-2004, 01:16 AM
|
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
|
01-26-2004, 07:14 AM
|
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...
|
All times are GMT -5. The time now is 04:28 AM — vBulletin © Jelsoft Enterprises Ltd
|