Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken (https://www.delphipraxis.net/168494-calc-exe-starten-oder-wenn-bereits-aktiv-sw_restore-schicken.html)

erich.wanker 24. Mai 2012 14:10

"Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Hallo Leute,

ich schaff es nicht !! :? :oops: eine ganz einfache Sache zu lösen...

Wenn ich auf einen Button klicke soll "Calc.exe" gestartet werden - und wenn der Taschenrechner bereits gestartet wurde, soll er (falls er minimiert ist..) sw_restore gesendet bekommen und focusiert werden...

schöne Grüße aus dem verregneten Gasteinertal
Erich

Hier mein Versuch:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, LMDCustomComponent, LMDStarter, StdCtrls;

type
  TForm1 = class(TForm)
    LMDStarter1: TLMDStarter;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    BitBtn1: TBitBtn;
    procedure SpeedButton1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  tlhelp32, ShellAPI;


{$R *.dfm}

//********************************************************
//          programm starten oder SW_Restore ausführen  *
//********************************************************
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  hProcess: THandle;
  wf: DWORD;
begin

    hProcess := GetProcessHandleFromID(GetProcessID('calc.exe'));

    if hProcess = 0 then
     begin
        LMDstarter1.StartOperation:=smOpen;     // Programm läuft nicht - also starten
        LMDstarter1.Execute;
     end
     else
     begin
        Hole_Fenster_in_den_Vordergrund('Rechner');
        SwitchToThisWindow(hProcess, True);     // Programm läuft - also anzeigen
        ForceForegroundWindow(hProcess);
        ShowWindow(hProcess,SW_Restore);
        BringWindowToTop(hProcess);

     end;

end;



//********************************************************
//          Versuch 1                                    *
//********************************************************
function GetProcessID(Exename: string): DWORD;
var
  hProcSnap: THandle;
  pe32: TProcessEntry32;
begin
  result := 0;
  hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
  if hProcSnap <> INVALID_HANDLE_VALUE then
  begin
    pe32.dwSize := SizeOf(ProcessEntry32);
    if Process32First(hProcSnap, pe32) = true then
    begin
      while Process32Next(hProcSnap, pe32) = true do
      begin
        if pos(Exename, pe32.szExeFile) <> 0 then
          result := pe32.th32ProcessID;
      end;
    end;
    CloseHandle(hProcSnap);
  end;
end;

function GetProcessHandleFromID(ID: DWORD): THandle;
begin
  result := OpenProcess(SYNCHRONIZE, False, ID);
  CloseHandle(result);
end;



//********************************************************
//          Versuch 2                                    *
//********************************************************
function ForceForegroundWindow(hwnd: THandle): Boolean;
const
  SPI_GETFOREGROUNDLOCKTIMEOUT = $2000;
  SPI_SETFOREGROUNDLOCKTIMEOUT = $2001;
var
  ForegroundThreadID: DWORD;
  ThisThreadID: DWORD;
  timeout: DWORD;
begin
  if IsIconic(hwnd) then ShowWindow(hwnd, SW_RESTORE);

  if GetForegroundWindow = hwnd then Result := True
  else
  begin
    // Windows 98/2000 doesn't want to foreground a window when some other
    // window has keyboard focus

    if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or
      ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and
      ((Win32MajorVersion > 4) or ((Win32MajorVersion = 4) and
      (Win32MinorVersion > 0)))) then
    begin
      // Code from Karl E. Peterson, www.mvps.org/vb/sample.htm
      // Converted to Delphi by Ray Lischner
      // Published in The Delphi Magazine 55, page 16

      Result := False;
      ForegroundThreadID := GetWindowThreadProcessID(GetForegroundWindow, nil);
      ThisThreadID := GetWindowThreadPRocessId(hwnd, nil);
      if AttachThreadInput(ThisThreadID, ForegroundThreadID, True) then
      begin
        BringWindowToTop(hwnd); // IE 5.5 related hack
        SetForegroundWindow(hwnd);
        AttachThreadInput(ThisThreadID, ForegroundThreadID, False);
        Result := (GetForegroundWindow = hwnd);
      end;
      if not Result then
      begin
        // Code by Daniel P. Stasinski
        SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0);
        SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0),
          SPIF_SENDCHANGE);
        BringWindowToTop(hwnd); // IE 5.5 related hack
        SetForegroundWindow(hWnd);
        SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(timeout), SPIF_SENDCHANGE);
      end;
    end
    else
    begin
      BringWindowToTop(hwnd); // IE 5.5 related hack
      SetForegroundWindow(hwnd);
    end;

    Result := (GetForegroundWindow = hwnd);
  end;
end; { ForceForegroundWindow }





//********************************************************
//          Versuch 3                                    *
//********************************************************
procedure SwitchToThisWindow(h1: hWnd; x: bool); stdcall;
  external user32 Name 'SwitchToThisWindow';
         {x = false: Size unchanged, x = true: normal size}






//********************************************************
//          Versuch 4                                    *
//********************************************************
function FindWindowByTitle(WindowTitle: string): Hwnd;
var
  NextHandle: Hwnd;
  NextTitle: array[0..260] of char;
begin
  // Get the first window
  NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);
  while NextHandle > 0 do
  begin
    // retrieve its text
    GetWindowText(NextHandle, NextTitle, 255);
    if Pos(WindowTitle, StrPas(NextTitle)) <> 0 then
    begin
      Result := NextHandle;
      Exit;
    end
    else
      // Get the next window
      NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
  end;
  Result := 0;
end;




//********************************************************
//          Versuch 5                                    *
//********************************************************
procedure Hole_Fenster_in_den_Vordergrund ( Programmname : String);
var h_Prog : hwnd;
begin
  // Funktion holt Fenster in den Vordergrund
   h_Prog := FindWindowByTitle(Programmname);
   if (h_Prog <> 0) then
    begin
     h_Prog := GetWindow(h_Prog, GW_OWNER); // Owner-Handle holen (Handle des TApplication-Fensters)
      if IsIconic(h_Prog) then
       ShowWindow(h_Prog, SW_RESTORE); // restoren wenn minimiert
         ForceForegroundWindow(h_Prog);
         BringWindowToTop(h_Prog);
    end;
end;











// Unit ende!
end.

Bummi 24. Mai 2012 14:21

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Delphi-Quellcode:
var
 h:THandle;
begin
 h := FindWindow(nil,'Rechner');
 if h=0 then Shellexecute(handle,'open','calc.exe','','',sw_Show)
 else
  begin
  SetForegroundWindow(h );
  end;
end;

DeddyH 24. Mai 2012 14:27

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Das ist aber nicht sehr zuverlässig, es kann ja auch noch andere Fenster mit dem Titel "Rechner" geben.

Bummi 24. Mai 2012 14:34

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
schtümpt ...

DeddyH 24. Mai 2012 14:38

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Evtl. hilft dieser Thread schonmal etwas weiter.

teebee 24. Mai 2012 14:48

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Zitat:

Zitat von DeddyH (Beitrag 1167950)
Das ist aber nicht sehr zuverlässig, es kann ja auch noch andere Fenster mit dem Titel "Rechner" geben.

Mit der entsprechenden Fensterklasse wird es schon zuverlässiger:
Delphi-Quellcode:
var
 h:THandle;
begin
 h := FindWindow('SciCalc','Rechner'); // Fensterklasse explizit benannt
 if h=0 then Shellexecute(handle,'open','calc.exe','','',sw_Show)
 else
  begin
  SetForegroundWindow(h );
  end;
end;
Gruß, teebee

DeddyH 24. Mai 2012 14:51

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Auf einem deutschen Windows, ja.

teebee 24. Mai 2012 14:56

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Zitat:

Zitat von DeddyH (Beitrag 1167955)
Auf einem deutschen Windows, ja.

Geht auch nur mit der Klasse ohne Titel.

DeddyH 24. Mai 2012 15:01

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Das weiß ich auch. Nur denke ich mir, dass es zuverlässiger wäre, das Fenster über den Pfad zu ermitteln, es wird ja wohl kaum einer die calc.exe im System32-Ordner überschrieben haben. Problematisch wird das nur, wenn man sie in ein anderes Verzeichnis kopiert und daraus gestartet hat (aber wer macht denn sowas?).

teebee 24. Mai 2012 15:10

AW: "Calc.exe" starten oder wenn bereits aktiv: SW_Restore schicken
 
Zitat:

Zitat von DeddyH (Beitrag 1167957)
Das weiß ich auch.

Hab ich auch nicht angezweifelt:wink:

Letzten Endes wird man immer ein Szenario konstruieren können, und sei es noch so unwahrscheinlich, in dem die aufwändigste Lösung nicht funktioniert.

Gruß, teebee


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:36 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz