How do I get the command-line parameters for certain button clicks in a application?
I want to start a program using Delphi code, and "command" it to perform an action, in this case a button click.
I know you can start a program using the com开发者_开发知识库mand line, but I would need the right paramaters for the button click. How or where can I find it?
You could use a program like AutoIt that's designed for automating GUI applications. For example, AutoIt can run a program, wait for that program's window to finish loading, then simulate a button click in that window.
This is far from an ideal situation - command-line parameters or COM Interop are much more reliable - but it works.
AutoIt is also available as a COM or DLL version so that you can use it directly from your Delphi app.
Remote controlling another application is possible, however with the later versions of Windows (Vista/Win7) it will ONLY work if the program you are controlling and your program are running in the same process level. (both apps NOT running as administrator for example). What you will want to do is to find the windows handle of the button using the FindWindow api, then send appropriate mouse messages to the handle you located. Because different applications behave differently this will require some experimentation to get the messaging correct. I believe that WM_MOUSEDOWN and WM_MOUSEUP generally are what your looking to send.
I have written the below unit to parse command line arguments in a more robust way. Feel free to use it. I've included an example usage after the unit (scroll to the bottom).
unit CLArgParser;
//this class makes it easier to parse command line arguments
interface
uses
Classes;
type
strarr = array of string;
type
TCLArgParser = class
private
FPermitTags : array of string;
FTrimAll: boolean;
public
function IsArg(argtag : string) : boolean;
function GetArg(argtag : string) : string;
function GetDelimtedArg(argtag, delimiter : string) : TStringList;
constructor Create(ArgTags : array of string); overload;
constructor Create; overload;
property TrimAll: boolean read FTrimAll write FTrimAll;
end;
implementation
uses
SysUtils;
const
cDefaultTags : array[0..1] of string = ('-','/');
constructor TCLArgParser.Create(ArgTags : array of string);
var i : integer;
begin
try
SetLength(FPermitTags,High(ArgTags)+1);
for i := 0 to High(ArgTags) do begin
FPermitTags[i] := ArgTags[i];
end; //for i
except on e : exception do
raise;
end; //try-except
end;
constructor TCLArgParser.Create;
begin
FTrimAll := False; //default value
inherited Create;
Create(cDefaultTags);
end;
function TCLArgParser.GetArg(argtag: string): string;
var i,j,n : integer;
begin
try
Result := '';
n := High(FPermitTags);
for i := 1 to ParamCount do
for j := 0 to n do
if Uppercase(ParamStr(i)) = (FPermitTags[j] + Uppercase(argtag)) then
Result := ParamStr(i+1);
if FTrimAll then begin
Result := Trim(Result);
end;
except on e : exception do
raise;
end; //try-except
end;
function TCLArgParser.GetDelimtedArg(argtag, delimiter: string): TStringList;
var i : integer;
argval, tmp : string;
begin
try
Result := TStringList.Create;
argval := GetArg(argtag);
for i := 1 to Length(argval) do begin
if ((i = Length(argval)) or ((argval[i] = delimiter) and (tmp <> '')))
then begin
if i = Length(argval) then begin
tmp := tmp + argval[i];
if FTrimAll then begin
tmp := Trim(tmp);
end;
end;
Result.Add(tmp);
tmp := '';
end //if we found a delimted value
else begin
tmp := tmp + argval[i];
end; //else we just keep looking
end; //for ea. character
except on e : exception do
raise;
end; //try-except
end;
function TCLArgParser.IsArg(argtag: string): boolean;
var i,j,n : integer;
begin
try
Result := False;
n := High(FPermitTags);
for i := 1 to ParamCount do begin
for j := 0 to n do begin
if Uppercase(ParamStr(i)) = (FPermitTags[j] + Uppercase(argtag))
then begin
Result := True;
Exit;
end; //if we found it
end; //for j
end; //for i
except on e : exception do
raise;
end; //try-except
end;
end.
Example usage:
procedure DefineParameters;
var
clarg: TCLArgParser;
begin
//assign command line arguments to various global variables
clarg := TCLArgParser.Create;
try
wantshelp := clarg.IsArg('?') or clArg.IsArg('help');
dbuser := clarg.GetArg('u');
dbpwd := clarg.GetArg('p');
dbserver := clarg.GetArg('d');
localfilename := clarg.GetArg('localfile');
ftpuser := clarg.GetArg('ftu');
ftppwd := clarg.GetArg('ftp');
ftpipaddr := clarg.GetArg('fti');
emailfromacct := clarg.GetArg('efrom');
emailtoacct := clarg.GetArg('eto');
archivefolder := clarg.GetArg('archive');
if archivefolder <> '' then begin
if archivefolder[Length(archivefolder)] <> '\' then begin
archivefolder := archivefolder + '\';
end;
end;
//figure out the (optional) verbosity code.
//if they didn't specify, assume the default value
verbosity := c_VerbosityDefault;
if clArg.IsArg('v') then begin
if not(TryStrToInt(clarg.GetArg('v'),verbosity)) then begin
WriteLn('Invalid verbosity code- using default of ' +
IntToStr(c_VerbosityDefault) + '.');
end; //if their specified verbosity was invalid
end; //if they specified the verbosity
if not(TryStrToInt(clarg.GetArg('maxtime'),maxtime)) then begin
maxtime := 9999999;
end;
finally
FreeAndNil(clarg);
end; //try-finally
end;
What you need to find out is how the program gets informed of the button click. For that you can use WinSight that comes with Delphi or (much better) Spy++. You run the program, start listening for messages using one of these tools, click the button and see what happens. Most likely, you'd be interested in the WM_COMMAND message (you can filter out all other messages, to reduce the amount of information in Spy++). Inspect what happens when you click the button, which values are stored in wParam and lParam of the WM_COMMAND message. Read the class and/or title of the program's window from Spy++ and use that in FindWindow in your app. Then, use SendMessage to send the detected message and its params to the obtained window handle and off you go :) Sometimes, the message is not WM_COMMAND, but something else, in which case you need to inspect more to find the right one
Delphi provides 2 global variables for you to pick up parameters: ParamCount and ParamStr.
ParamStr(0) is always the full path and filename of the executable that is running.
From then on it is up to you what the parameters are. So if you want the parameter to be called "clickbutton", then do something like this before Application.Run in the .dpr file:
var
i: Integer;
for i := 0 to ParamCount Do
if (Lowercase(ParamStr(i)) = 'clickbutton') then
Form1.Button1.Click;
So then if your project is called with the command line:
project1.exe clickbutton
then Button1 will be clicked on Form1.
Automise might be right tool for you. It's also possible to code that, but for just one button click it might be too complicated.
Check out AutoHotKey. It allows you to program key clicks. It's free, open source, light-weight and programmable. It enjoys substantial support from its user community and there are several useful utilities made with it. There are some examples of what can be done with it on the Lifehacker web site.
精彩评论