program startat; { Author : Stefan M. Huber Created: 2006-08-07 Update : 2007-03-05 Version: 0.2 Purpose: Launch programmes at a given screen position. CHANGELOG [ 2007-03-05 ] * Try to launch programmes in a maximized or normal state. * Introduce an artificial lag to enable waiting for applications to launch. * Error message (GetLastError) } {$APPTYPE CONSOLE} uses SysUtils, windows, uGetopt; var hnd : DWORD; i, x, y : integer; waitTimeout : integer; max : boolean; prg, args : string; errStr : string; function EnumWindowCallback(AHandle: HWND; ALParam: PInteger): bool; stdcall; var R : TRect; begin Result := false; if GetWindowRect(AHandle, R) then Result := MoveWindow(AHandle, x, y, R.Right - R.Left, R.Bottom-R.Top, true) end; function WinExec(AFileName, AParams: String): DWORD; // collected from various sources on the net var SI : TStartupInfo; PI : TProcessInformation; begin FillChar(SI,Sizeof(SI),#0); SI.cb := Sizeof(SI); SI.dwFlags := STARTF_USESHOWWINDOW; if max then SI.wShowWindow := SW_SHOWMAXIMIZED else SI.wShowWindow := SW_SHOW; if CreateProcess(nil, PChar(AFilename + ' ' + AParams),{ pointer to command line string } nil, { pointer to process security attributes} nil, { pointer to thread security attributes } false, { handle inheritance flag } CREATE_NEW_CONSOLE or { creation flags } NORMAL_PRIORITY_CLASS or CREATE_DEFAULT_ERROR_MODE, nil, { pointer to new environment block } nil, { pointer to current directory name } SI, { pointer to STARTUPINFO } PI) { pointer to PROCESS_INF } then begin WaitForInputIdle(PI.hProcess, 5000); Result := PI.dwThreadId; CloseHandle( PI.hProcess ); CloseHandle( PI.hThread ); end else begin errStr := SysErrorMessage(GetLastError); Result := DWORD(-1); end; end; begin x := -1; y := -1; waitTimeout := 0; try with TGetopt.Create('x:y:mnw:') do try while getopt do case Option of 'x' : try x := StrToInt(Argument); except x := -1; end; 'y' : try y := StrToInt(Argument); except y := -1; end; 'm' : max := true; 'n' : max := false; 'w' : try waitTimeout := StrToInt(Argument) except waitTimeout := 0; end; end; if RemainingArguments.Count = 0 then raise Exception.Create('Missing programme!'); { REMOVED: When screens have a vertical offset to each other, negative numbers may be useful if x < 0 then raise Exception.Create('-x must be specified and a nonnegative number.'); if y < 0 then raise Exception.Create('-y must be specified and a nonnegative number.');} prg := RemainingArguments.Strings[0]; args := ''; for i := 1 to RemainingArguments.Count - 1 do args := args + ' ' + RemainingArguments.Strings[i]; finally Free; end; hnd := WinExec(prg, args); if hnd <> DWORD(-1) then begin if waitTimeout > 0 then sleep(waitTimeout*1000); EnumThreadWindows(hnd, @EnumWindowCallback, 42); end else begin WriteLn(errStr); end; except on E: Exception do begin writeln('startat: ' + E.Message); writeln; WriteLn(' Usage: startat -x LEFT -y TOP [-w SECONDS] [-n] [-m] programme [arguments]'); Writeln; writeln(' -x LEFT specifies the horizontal position of the programme window'); writeln(' -y TOP specifies the vertical position of the programme window'); writeln(' -m tries to launch the programme in a maximized state'); writeln(' -n tries to launch the programme in normal state'); writeln(' -w SECONDS waits SECONDS seconds, before trying to move the window'); writeln; writeln(' startat attempts to launch ''programme'' at a given screen position.'); writeln(' depending on the programme and its behaviour this might fail, though.'); writeln; writeln(' StartAt 0.2 was written by Stefan M. Huber, 2007.'); writeln(' http://stefan.huberdoc.at/'); end; end end.