Einzelnen Beitrag anzeigen

taaktaak

Registriert seit: 25. Okt 2007
Ort: Radbruch
1.993 Beiträge
 
Delphi 7 Professional
 
#8

Re: ShellExecute() >> WindowHandle

  Alt 29. Jun 2009, 22:35
So, ich denke, ich habe es jetzt hinbekommen - die ersten Tests funktionieren zufriedenstellend. Zum besseren Verständnis zunächst die Aufgabenstellung etwas konkreter als bisher beschrieben:

In einem RichEdit sind Links auf beliebige Dateien placiert (Bilder, Texte o.ä.). Ein Klick auf die Links soll die Dateien mit dem verknüpften Programm anzeigen lassen. Damit kann man sich natürlich, ausreichend oft geklickt, auch große Bildschirme schnell "zumüllen" - aus diesem Grund soll optional der mehrfache Aufruf verhindert werden und stattdessen das bereits gestartete Programmfenster wieder in den Vordergrund geholt werden.

Beispielhaft habe ich das jetzt so gelöst:

Delphi-Quellcode:
uses ShellAPI;

type PEnumInfo = ^TEnumInfo;
     TEnumInfo = record
                      ProcessID : DWORD;
                      HWND : THandle;
                      end;

     tCalledLinks = record
                      LinkText : String;
                      WinHandle : DWord;
                      end;

var CalledLinks : tCalledLinks; // use array later on

procedure AddProcess(LnkText:String;WinHandle:HWnd);
begin
  CalledLinks.LinkText :=LnkText;
  CalledLinks.WinHandle:=WinHandle;
  (*
  add record to array
  *)

end;

function CanSetToForeGround(LnkText:String):Boolean;
begin
  Result:=SetForeGroundWindow(CalledLinks.WinHandle);
  (*
  if not(Result) then begin
  // remove record from array
  end
  *)

end;

function GetAssociatedApp(FName:String):String;
begin
  SetLength(Result,MAX_PATH);
  if FindExecutable(PChar(FName),
                    nil,
                    PChar(Result))>32 then SetLength(Result,StrLen(PChar(Result)))
                                      else Result:=''
end;

function RunProcess(FName:String;ShowCmd:DWORD;Wait:Boolean;var ProcID:DWord):LongWord;
var StartupInfo : TStartupInfo;
    ProcessInfo : TProcessInformation;
begin
  FillChar(StartupInfo,SizeOf(StartupInfo),#0);
  StartupInfo.cb :=SizeOf(StartupInfo);
  StartupInfo.dwFlags :=STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
  StartupInfo.wShowWindow:=ShowCmd;
  if not(CreateProcess(nil,
                       @FName[1],
                       nil,
                       nil,
                       False,
                       CREATE_NEW_CONSOLE or
                       NORMAL_PRIORITY_CLASS,
                       nil,
                       nil,
                       StartupInfo,
                       ProcessInfo)) then Result:=WAIT_FAILED
                                     else begin
    if not(Wait) then begin
      WaitForInputIdle(ProcessInfo.hProcess,INFINITE);
      ProcID:=ProcessInfo.dwProcessId;
      exit
      end;
 
    WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
    GetExitCodeProcess (ProcessInfo.hProcess,Result)
    end;

  if ProcessInfo.hProcess<>0 then CloseHandle(ProcessInfo.hProcess);
  if ProcessInfo.hThread <>0 then CloseHandle(ProcessInfo.hThread)
end;

function EnumWindowsProc(Wnd:DWORD;var EI:TEnumInfo):Boolean; stdcall;
var PID : DWORD;
begin
  GetWindowThreadProcessID(Wnd,@PID);
  Result:=(PID<>EI.ProcessID) or (not IsWindowVisible(WND)) or (not IsWindowEnabled(WND));
  if not(Result) then EI.HWND:=WND
end;

function FindAppWindow(PID:DWORD):DWORD;
var EI : TEnumInfo;
begin
  EI.ProcessID:=PID;
  EI.HWND :=0;
  EnumWindows(@EnumWindowsProc,Integer(@EI));
  Result:=EI.HWND
end;

procedure CallLink(DataFile:String;AdmitMultipleCalls:Boolean);
var AppName,
    ProcessPara : String;
    ProcID : Cardinal;
begin
  AppName :=GetAssociatedApp(DataFile);
  ProcessPara:=AppName+' '+DataFile;

  if AdmitMultipleCalls or
     not(CanSetToForeGround(DataFile)) then
 
  if RunProcess(ProcessPara,
                SW_SHOWNORMAL,
                false,
                ProcID)=WAIT_FAILED then ShowMessage('Create process error')
                                    else

    if not(AdmitMultipleCalls) then AddProcess(DataFile,FindAppWindow(ProcID))

end;

procedure TfoTest15.buShowLinkClick(Sender:TObject);
begin
  CallLink('d:\data_p\delphi\delphiguide\bitmaps\Edit_0000_Save.bmp',
           cbAdmitMultipleCalls.Checked)
end;
Ralph
  Mit Zitat antworten Zitat