![]() |
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. |
Re: Handle einer Form aus Taskbareintrag erhalten
Vielleicht kann ja mal jemand den C Code ausfueheren und berichten, ob er funktioniert.
|
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; |
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);
|
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 |
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,...) |
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); |
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 |
Re: Handle einer Form aus Taskbareintrag erhalten
Zitat:
Zitat:
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. |
Re: Handle einer Form aus Taskbareintrag erhalten
Zitat:
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. |
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