Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Handle einer Form aus Taskbareintrag erhalten (https://www.delphipraxis.net/90693-handle-einer-form-aus-taskbareintrag-erhalten.html)

toms 22. Apr 2007 19:11

Re: Handle einer Form aus Taskbareintrag erhalten
 
Habe den Code nochmals ueberarbeitet aber es wird nicht ein korrektes Windowhandle
zurueck gegeben. Irgendwo scheint noch ein Fehler in der Uebersetzung zu sein.

toms 22. Apr 2007 20:29

Re: Handle einer Form aus Taskbareintrag erhalten
 
Vielleicht kann ja mal jemand den C Code ausfueheren und berichten, ob er funktioniert.

Mazel 23. Apr 2007 12:52

Re: Handle einer Form aus Taskbareintrag erhalten
 
Das wär natürlich eine Idee.

Ich habe jetzt mal beide Codes zusammengefügt, da mir aufgefallen ist, dass mehrere Fragmente in beiden wiederholt werden, im Ergebnis hat sich nichts geändert: es wird immernoch ein Wert ausgegeben, kein Wnd-Handle ist.
Delphi-Quellcode:
{--[TaskbarEntry]--------------------------------------------------------------}

procedure TaskbarEntry;
var
 Pos           : TPoint;
 // variables that needed to open taskbar (explorer) process
 TaskbarPID    : DWORD;        // TaskbarProcessID
 TaskbarPHandle : THandle;      // TaskbarProcessHandle
 // variable that helds pointer to a remote buffer in taskbar process
 TaskbarPBuffer : Pointer;      // TaskbarProcessBuffer
 lpPoint       : Pointer;
 NumBytes      : DWORD;
 ButtonIndex   : Integer;
 tbButton      : TTBButton;
 PtbButton     : Pointer;
 dwBytesRead   : DWORD;
 lpRemoteData  : Pointer;
 localBuffer   : array[0..BUFFER_SIZE - 1] of Byte;
 pLocalBuffer  : ^Byte;
 ipLocalBuffer : Pointer;
 Wnd           : HWND;

begin
 GetCursorPos(Pos);
 Windows.ScreenToClient(Main.TBHandle, Pos);
 TaskbarPID := 0;
 ButtonIndex := 0;
 // Main.TBHandle ist Taskbarhandle, welches beim Start der Anwendung ermittelt wird
 GetWindowThreadProcessId(Main.TBHandle, @TaskbarPID);
 TaskbarPHandle := OpenProcess(PROCESS_ALL_ACCESS, False, TaskbarPID);
 If TaskbarPHandle <> 0 then
  try
   lpPoint := VirtualAllocEx(TaskbarPHandle, nil, SizeOf(TPoint), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
   NumBytes := 0;
   WriteProcessMemory(TaskbarPHandle, lpPoint, @Pos, SizeOf(TPoint), NumBytes);
   // Index ermittlen
   ButtonIndex := SendMessage(Main.TBHandle, TB_HITTEST, 0, Integer(lpPoint));
   If Assigned(lpPoint) then VirtualFreeEx(TaskbarPHandle, lpPoint, 0, MEM_RELEASE);
  finally
   CloseHandle(TaskbarPHandle);
  end;
 TaskbarPID := 0;
 GetWindowThreadProcessId(Main.TBHandle, @TaskbarPID);
 TaskbarPHandle := OpenProcess(PROCESS_ALL_ACCESS, False, TaskbarPID);
 If TaskbarPHandle <> 0 then
  try
   // allocate space for remote buffer in taskbar process
   TaskbarPBuffer := VirtualAllocEx(TaskbarPHandle, nil, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
   If Assigned(TaskbarPBuffer) then
    begin
     // declare and prepare variables that will held data
     // about PRESSED button in a taskbar
     PtbButton := @tbButton;
     // Now, retrieve information about the PRESSED button in a taskbar / data is placed in remote buffer
     SendMessage(Main.TBHandle, TB_GETBUTTON, ButtonIndex, Integer(TaskbarPBuffer));
     // And now, the remote data about PRESSED button is transferred to a local variable
     dwBytesRead := 0;
     ReadProcessMemory(TaskbarPHandle, TaskbarPBuffer, PtbButton, SizeOf(TBButton), dwBytesRead);
     // the window handle is in dwData field of TBBUTTON structure (the first 4 bytes)
     pLocalBuffer := @localBuffer[0];
     ipLocalBuffer := pLocalBuffer;
     // initialize remote buffer
     lpRemoteData := @tbButton.dwData;
     // and read the dwData fields of a TBBUTTON from remote process
     dwBytesRead := 0;
     ReadProcessMemory(TaskbarPHandle, lpRemoteData, ipLocalBuffer, SizeOf(Pointer), dwBytesRead);
     // obtain window handle, copy first 4 bytes
     Move(ipLocalBuffer^, Wnd, 4);
     If Assigned(TaskbarPBuffer) then VirtualFreeEx(TaskbarPHandle, TaskbarPBuffer, 0, MEM_RELEASE);
    end;
  finally
   CloseHandle(TaskbarPHandle);
  end;
 Main.Caption := inttostr(Wnd);
end;

DGL-luke 23. Apr 2007 16:48

Re: Handle einer Form aus Taskbareintrag erhalten
 
Hallo,

könnte das sein, dass du mit deine Pointern bisschen mehr aufpassen musst? ;-)

Delphi-Quellcode:
Move(ipLocalBuffer^, Wnd, 4);

Mazel 23. Apr 2007 17:02

Re: Handle einer Form aus Taskbareintrag erhalten
 
Ich habe eben den Code nochmal überarbeitet und deine Änderung mit eingebunden. Nun kommt allerdings 0 als Wnd heraus.

Wo steckt der Fehler?

Gruß
Mazel

toms 23. Apr 2007 19:06

Re: Handle einer Form aus Taskbareintrag erhalten
 
Dieser Code kommt immer noch doppelt vor:

Delphi-Quellcode:
TaskbarPID := 0;
GetWindowThreadProcessId(Main.TBHandle, @TaskbarPID);
TaskbarPHandle := OpenProcess(PROCESS_ALL_ACCESS, False, TaskbarPID);
//...

VirtualAllocEx(TaskbarPHandle, nil,...)

toms 23. Apr 2007 20:23

Re: Handle einer Form aus Taskbareintrag erhalten
 
Habe den Code noch etwas abgeaendert und ueberarbeitet und funktioniert nun bei mir:


Delphi-Quellcode:
//Get the Taskbar handle
function getTaskbarHWND: HWND;
var
  ShellTrayWnd: HWnd;
  ReBarWindow32: HWnd;
  MSTaskSwWClass: HWnd;
begin
  Result := 0;
  ShellTrayWnd := FindWindow('Shell_TrayWnd', nil);
  if ShellTrayWnd <> 0 then
  begin
    ReBarWindow32 := FindWindowEx(ShellTrayWnd, 0, 'ReBarWindow32', nil);
    if ReBarWindow32 <> 0 then
    begin
      MSTaskSwWClass := FindWindowEx(ReBarWindow32, 0, 'MSTaskSwWClass', nil);
      if MSTaskSwWClass <> 0 then
        Result := FindWindowEx(MSTaskSwWClass, 0, 'ToolbarWindow32', nil);
    end;
  end;
end;
Delphi-Quellcode:
type
  TExtraData = packed record
    Wnd: THandle;
    uID: UINT;
  end;

// Retrieve the window handle at the cursor position

function GetWinHandleFromTBButton(hwndTaskbar: HWND; pt: TPoint): HWND;
const
  BUFFER_SIZE = $1000;
var
  taskbarProcessID: DWORD;
  taskbarProcessHandle: THandle;
  pTaskbarProcessBuffer: Pointer;
  dwBytesRead: DWORD;
  Button: TTBButton;
  ExtraData: TExtraData;
  lpPoint: Pointer;
  ButtonIndex: Integer;
begin
  Result := 0;
  if hwndTaskbar <> 0 then
  begin
    // obtain taskbar process id - by window
    GetWindowThreadProcessId(hwndTaskbar, @taskbarProcessID);
    // open taskbar process
    taskbarProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, taskbarProcessID);
    if taskbarProcessHandle <> 0 then
    try
      // allocate space for remote buffer in taskbar process
      lpPoint := VirtualAllocEx(taskbarProcessHandle, nil, SizeOf(TPoint), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
      dwBytesRead := 0;
      WriteProcessMemory(taskbarProcessHandle, lpPoint, @pt, SizeOf(TPOINT), dwBytesRead);
      // Get the Button Index
      ButtonIndex := SendMessage(hwndTaskbar, TB_HITTEST, 0, Integer(lpPoint));
      if Assigned(lpPoint) then
        VirtualFreeEx(taskbarProcessHandle, lpPoint, 0, MEM_RELEASE);
      if ButtonIndex > 0 then
      begin
        // allocate space for remote buffer in taskbar process
        pTaskbarProcessBuffer := VirtualAllocEx(taskbarProcessHandle, nil, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
        if Assigned(pTaskbarProcessBuffer) then
        begin
          // Retrieve information about the button in the taskbar / data is placed in remote buffer
          SendMessage(hwndTaskbar, TB_GETBUTTON, ButtonIndex, Integer(pTaskbarProcessBuffer));
          // Read the data from the Taskbar process into the current process.
          if ReadProcessMemory(taskbarProcessHandle, pTaskbarProcessBuffer, @Button, SizeOf(Button), dwBytesRead)
            and (dwBytesRead = SizeOf(Button)) then
            // Read the extra data, Button.dwData points to its location
            if ReadProcessMemory(taskbarProcessHandle, Pointer(Button.dwData),
              @ExtraData, SizeOf(ExtraData), dwBytesRead) and (dwBytesRead = SizeOf(ExtraData)) then
              Result := ExtraData.Wnd;
          if Assigned(pTaskbarProcessBuffer) then
            VirtualFreeEx(taskbarProcessHandle, pTaskbarProcessBuffer, 0, MEM_RELEASE);
        end;
      end;
    finally
      CloseHandle(taskbarProcessHandle);
    end;
  end;
end;

Testen:

Delphi-Quellcode:
var
  pt: TPOINT;
  TaskbarHWND, windowHandle: HWND;
begin
  TaskbarHWND := getTaskbarHWND;
  GetCursorPos(pt);
  if (WindowFromPoint(pt) <> TaskbarHWND) then Exit;
  Windows.ScreenToClient(TaskbarHWND, pt);
  windowHandle := GetWinHandleFromTBButton(getTaskbarHWND, pt);

Mazel 24. Apr 2007 19:02

Re: Handle einer Form aus Taskbareintrag erhalten
 
Hallo, :)

der Code funktioniert, wirklich super. Ich danke dir, du hast dir echt Mühe gegeben. Ohne dich hätte ich das nicht hinbekommen. :thumb:

Ich habe immer wieder versucht ein paar Änderungen vorzunehmen, aber es kam zu keinem Erfolg. Zudem habe ich versucht den C Code zu verstehen und ihn dann in Delphi umzusetzten, aber die Sache mit den Pointer in C habe ich überhaupt nicht verstanden. Mal wurde es so und mal so grmacht.

Nochmals vielen Danke, auch an DGL-luke.

Nun aber eine Frage:

Wozu ist ExtraData da? In dem einen Thema wurde es verwendet, in diesem hier und in den Code davor nicht.

Gruß
Mazel

toms 25. Apr 2007 06:16

Re: Handle einer Form aus Taskbareintrag erhalten
 
Zitat:

Zitat von Mazel
Hallo, :)

der Code funktioniert, wirklich super. Ich danke dir, du hast dir echt Mühe gegeben. Ohne dich hätte ich das nicht hinbekommen. :thumb:

Was hast du den vor mit dem Code? Erstellst du ein spezielles Programm? *michwundernimmt*

Zitat:

Nun aber eine Frage:

Wozu ist ExtraData da? In dem einen Thema wurde es verwendet, in diesem hier und in den Code davor nicht.

Mazel
ExtraData ist eine "Hilfs-Struktur" zum Auslesen des Handels aus Button.dwData.
Die ersten 4 Bytes enthaelt ja das Handle.
Im obigen Code wird es mit move gemacht "// obtain window handle, copy first 4 bytes",

Da THandle 32 Bit hat (= 4 Byte), wird das Handle dann direkt in das ExtraData.Wnd kopiert.

Mazel 25. Apr 2007 13:32

Re: Handle einer Form aus Taskbareintrag erhalten
 
Zitat:

Was hast du den vor mit dem Code? Erstellst du ein spezielles Programm? *michwundernimmt*
Ich habe ein Programm, welches sich WiVi (Window Visibility) nennt. Dieses macht Fenster durchsichtig zu einem selbstgewählten Grad. Nun wollte der "Idee-Schöpfer" eine Erweiterung: wenn man auf den Button in der Taskleiste klickt soll jenes Fenster geschlossen werden.
Wenn du möchtest, kann ich dir die fertige erweiteret Version senden. :)

Warum hast du das dann mit ExtraData gemacht, wenn es auch mit Move() geht? Oder ging es doch nicht so einfach?

Gruß
Mazel


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:28 Uhr.
Seite 2 von 3     12 3      

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