![]() |
Handle einer Form aus Taskbareintrag erhalten
Hallo,
ich suche nach einer Möglichkeit, über ein Klick mit der mittleren Maustaste auf ein Taskbareintrag einer Form, das Handle der jeweiligen Form zu ermitteln. Ich habe folgendes ausprobiert, jedoch bekomme ich da selber nur das Handle der Taskbar und nicht der einzelnen Einträge:
Delphi-Quellcode:
Ein Klick mit der Mausstaste fange ich folgendermaßen ab:
GetCursorPos(Pos);
Wnd := WindowFromPoint(Pos);
Delphi-Quellcode:
Hat jemand einen Rat für mich?
{--[MouseHookProc]-------------------------------------------------------------}
function MouseHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin If nCode = HC_ACTION then begin If lParam <> 0 then with PEventMsg(lParam)^ do begin If Message = WM_MBUTTONDOWN then begin GetCursorPos(Pos); Wnd := WindowFromPoint(Pos); end; end; end; Result := CallNextHookEx(Main.MouseHook, nCode, wParam, lParam); end; Gruß Mazel |
Re: Handle einer Form aus Taskbareintrag erhalten
Hallo Mazel
Zitat:
Habe ein Beispiel in C gefunden.
Code:
POINT pt;
GetCursorPos(&pt); if (WindowFromPoint(pt)!=hwndTW) return 0; ScreenToClient(hwndTW,&pt); HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pidTB);// pidTB is the process ID of the taskbar LPVOID lpPoint=VirtualAllocEx(hProc,NULL,sizeof(POINT),MEM_COMMIT,PAGE_READWRITE); WriteProcessMemory(hProc,lpPoint,&pt,sizeof(POINT),NULL); int i=(int)SendMessage(hwndTW,TB_HITTEST,0,(LPARAM)(LPPOINT)lpPoint); VirtualFreeEx(hProc,lpPoint,NULL,MEM_RELEASE); CloseHandle(hProc); Meine Delphi Umsetzung ist wahrscheinlich noch nicht ganz richtig. Konnte sie auch nicht testen.
Delphi-Quellcode:
function getTaskbarHWND: HWND;
var ShellTrayWnd: HWnd; ReBarWindow32: HWnd; MSTaskSwWClass: HWnd; begin Result := 0; ShellTrayWnd := FindWindow('Shell_TrayWnd', nil); if ShellTrayWnd = 0 then begin ShowMessage('No taskbar found'); Exit; end; ReBarWindow32 := FindWindowEx(ShellTrayWnd, 0, 'ReBarWindow32', nil); if ReBarWindow32 = 0 then begin ShowMessage('Error with taskbar'); Exit; end; MSTaskSwWClass := FindWindowEx(ReBarWindow32, 0, 'MSTaskSwWClass', nil); if MSTaskSwWClass = 0 then begin ShowMessage('Error inside taskbar'); Exit; end; Result := FindWindowEx(MSTaskSwWClass, 0, 'ToolbarWindow32', nil); // not for Win95 * end; end;
Delphi-Quellcode:
Danach muesste man den Code mit folgendem Kombinieren, um an das Window Handle zu kommen:
var
pt: TPOINT; TaskbarHWND: HWND; hProc: THandle; PID: THandle; lpNumberOfBytesWritten: DWORD; i: Integer; lpPoint: Pointer; begin Sleep(2000); TaskbarHWND := getTaskbarHWND; GetCursorPos(pt); if (WindowFromPoint(pt) <> TaskbarHWND) then Exit; Windows.ScreenToClient(TaskbarHWND, pt); GetWindowThreadProcessId(TaskbarHWND, @PID); hProc := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False, PID); lpPoint := VirtualAllocEx(hProc, nil, SizeOf(TPoint), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE); FillChar(pt, SizeOf(TPOINT), 0); lpNumberOfBytesWritten := 0; WriteProcessMemory(hProc, lpPoint, @pt, SizeOf(TPOINT), lpNumberOfBytesWritten); i := SendMessage(TaskbarHWND, TB_HITTEST, 0, lParam(lpPoint)); //???? Caption := IntToStr(i); VirtualFreeEx(hProc, lpPoint, NULL, MEM_RELEASE); CloseHandle(hProc);
Code:
// find Windows Taskbar (Note: works under XP and 2k3)
HWND hwndTaskbar = FindWindow("Shell_TrayWnd", NULL); hwndTaskbar = FindWindowEx(hwndTaskbar, NULL, "ReBarWindow32", NULL); hwndTaskbar = FindWindowEx(hwndTaskbar, NULL, "MSTaskSwWClass", NULL); hwndTaskbar = FindWindowEx(hwndTaskbar, NULL, "ToolbarWindow32", NULL);i - это индекс кнопки на таскбаре // variables that needed to open taskbar (explorer) process DWORD taskbarProcessID; const int BUFFER_SIZE = 0x1000; // obtain taskbar process id - by window GetWindowThreadProcessId(hwndTaskbar, &taskbarProcessID); // open taskbar process HANDLE taskbarProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, taskbarProcessID); // variable that helds pointer to a remote buffer in taskbar process DWORD_PTR taskbarProcessBuffer; // allocate space for remote buffer in taskbar process taskbarProcessBuffer = (DWORD_PTR)VirtualAllocEx(taskbarProcessHandle, NULL, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE); // declare and prepare variables that will held data // about PRESSED button in a taskbar TBBUTTON tbButton; TBBUTTON* pTBButton = &tbButton; DWORD_PTR lpTBButton = (DWORD_PTR)pTBButton; // Now, retrieve information about the PRESSED button in a taskbar // Note: data is placed in remote buffer SendMessage(hwndTaskbar, TB_GETBUTTON, i, taskbarProcessBuffer); // And now, the remote data about PRESSED button is transferred to a local variable DWORD dwBytesRead = 0; ReadProcessMemory(taskbarProcessHandle, (LPVOID)taskbarProcessBuffer, (LPVOID)lpTBButton, sizeof(TBBUTTON), &dwBytesRead); // ------------------------------------------------------------------ // Where is keeped the window handle? // It is in dwData field of TBBUTTON structure (the first 4 bytes) :)) // MSDN doesn't specify anything about this! // ------------------------------------------------------------------ // Retrieve window handle of pressed btn BYTE localBuffer[BUFFER_SIZE]; BYTE* pLocalBuffer = localBuffer; DWORD_PTR ipLocalBuffer = (DWORD_PTR)pLocalBuffer; // window handle pLocalBuffer = localBuffer; ipLocalBuffer = (DWORD_PTR)pLocalBuffer; // initialize remote buffer DWORD_PTR lpRemoteData = (DWORD_PTR)tbButton.dwData; // and read the dwData fields of a TBBUTTON from remote process ReadProcessMemory(taskbarProcessHandle, (LPVOID)lpRemoteData, (LPVOID)ipLocalBuffer, sizeof(DWORD_PTR), &dwBytesRead); // obtain window handle // copy first 4 bytes HWND windowHandle; memcpy(&windowHandle, (void *)ipLocalBuffer, 4); |
Re: Handle einer Form aus Taskbareintrag erhalten
Hallo,
danke für die schnelle Antwort. :thumb: Zunächst werde ich versuchen müssen, den C Code in Delphi zu übersetzten. Da ich keinerlei Kentnisse in C habe, wird das sicher lange dauern, aber ich versuche es, denn ein paar kleine Dinge sind in Dephi nicht viel anders, dennoch werde ich da Hilfe brauchen. Was ich gleich nicht verstanden habe ist: DWORD_PTR taskbarProcessBuffer; Was beudetet PTR? Das selbe finde sich auch in der TBBUTTON Struktur. Gruß Mazel |
Re: Handle einer Form aus Taskbareintrag erhalten
Das ist ein Pointer auf ein DWORD, also sowas wie "CardinalPtr", glaub ich. Die ganze Zeile ist eine Variablendeklaration.
EDIT: Wenn Delphi keine passenden Typ dafür hat, kannst du es auch als Pointer oder gleich als Cardinal deklarieren. Jenachdem, was in C alles damit gemacht wird, ist das eien oder das andere besser. |
Re: Handle einer Form aus Taskbareintrag erhalten
Danke DGL-luke, diese Bezeichnung war mir nicht bekannt.
Ich habe mal in der Suche etwas herumgesucht und dabei folgendes Thema gefunden: ![]() Nun kann man sicher den Code so umstellen, dass zumdindest ein paar Teile genutzt werden können. Ich habe das eben probiert, aber mir ist mein Rechner abgestürzt. Daher ist auch der von mir schon teilweise angepasste Code aus dem übernommen Code weg. Jetzt brauch ich erstmal Abstand um später einen neuen Versuch zu starten. Eventuell weis jemand von euch, wie ich den Code am besten zusammensetze. Gruß Mazel |
Re: Handle einer Form aus Taskbareintrag erhalten
Vielleicht koennte jemand noch helfen, diese 3 Codefragemente nach Delphi zu uebersetzen :?:
1.
Code:
2.
SendMessage(hwndTW,TB_HITTEST,0,(LPARAM)(LPPOINT)lpPoint);
Code:
3.
TBBUTTON tbButton;
TBBUTTON* pTBButton = &tbButton; DWORD_PTR lpTBButton = (DWORD_PTR)pTBButton;
Code:
// Retrieve window handle of pressed btn
BYTE localBuffer[BUFFER_SIZE]; BYTE* pLocalBuffer = localBuffer; DWORD_PTR ipLocalBuffer = (DWORD_PTR)pLocalBuffer; pLocalBuffer = localBuffer; ipLocalBuffer = (DWORD_PTR)pLocalBuffer |
Re: Handle einer Form aus Taskbareintrag erhalten
1.
Delphi-Quellcode:
2.
SendMessage(hwndTW,TB_HITTEST,0,Integer(lpPoint));
Delphi-Quellcode:
3.
var
tbButton: TBButton; PtbButton: Pointer; PtbButton := @TBButton;
Delphi-Quellcode:
WObei mir die etwas sinnlos erscheinen, die Codestückchen, insbesondere wenn man was erst initialisiert und ihm dann den sleben wert nochmal zuweist.
// Retrieve window handle of pressed btn
var localBuffer: array[0..BUFFER_SIZE-1] of Byte; pLocalBuffer: ^Byte; //"BytePointer", könnte sein dass Delphi schon "PByte" definiert hat, das ist dann schöner ipLocalBuffer: Pointer; pLocalBuffer := @localBuffer[0]; ipLocalBuffer := pLocalBuffer; |
Re: Handle einer Form aus Taskbareintrag erhalten
Danke erstmal. Habe das 1. Codestueck ueberarbeitet und es liefert schonmal erfolgreich den Index des Buttons unter der Maus.
Delphi-Quellcode:
var
pt: TPOINT; TaskbarHWND: HWND; hProc: THandle; PID: THandle; NumBytes: DWORD; iButtonIndex : Integer; lpPoint: Pointer; begin TaskbarHWND := getTaskbarHWND; GetCursorPos(pt); if (WindowFromPoint(pt) <> TaskbarHWND) then Exit; Windows.ScreenToClient(TaskbarHWND, pt); PID := 0; GetWindowThreadProcessId(TaskbarHWND, @PID); hProc := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False, PID); if hProc <> 0 then try lpPoint := VirtualAllocEx(hProc, nil, SizeOf(TPoint), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE); NumBytes := 0; WriteProcessMemory(hProc, lpPoint, @pt, SizeOf(TPOINT), NumBytes); // Index ermittlen iButtonIndex := SendMessage(TaskbarHWND,TB_HITTEST,0,Integer(lpPoint)); Caption := IntToStr(iButtonIndex ); if Assigned(lpPoint) then VirtualFreeEx(hProc, lpPoint, 0, MEM_RELEASE); finally CloseHandle(hProc); end; |
Re: Handle einer Form aus Taskbareintrag erhalten
Anbei schonmal ein Entwurf meiner Delphi Uebersetzung des 2. Codefragmentes.
Es liefert von einem gegebenem Buttonindex das Handle des zugehoerigen Fensters.
Delphi-Quellcode:
function GetHandleFromButtonIndex(ButtonIndex: Word): HWND;
const BUFFER_SIZE = $1000; var hwndTaskbar: HWND; // variables that needed to open taskbar (explorer) process taskbarProcessID: DWORD; taskbarProcessHandle: THandle; // variable that helds pointer to a remote buffer in taskbar process taskbarProcessBuffer: Pointer; i: Integer; dwBytesRead: DWORD; lpRemoteData: Pointer; tbButton: TTBBUTTON; PtbButton: Pointer; localBuffer: array[0..BUFFER_SIZE - 1] of Byte; pLocalBuffer: ^Byte; ipLocalBuffer: Pointer; btnWindowHandle: HWND; begin Result := 0; // find Windows Taskbar hwndTaskbar := getTaskbarHWND; 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 taskbarProcessBuffer := VirtualAllocEx(taskbarProcessHandle, nil, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE); if Assigned(taskbarProcessBuffer) 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(hwndTaskbar, TB_GETBUTTON, ButtonIndex, Integer(taskbarProcessBuffer)); // And now, the remote data about PRESSED button is transferred to a local variable dwBytesRead := 0; ReadProcessMemory(taskbarProcessHandle, taskbarProcessBuffer, 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(taskbarProcessHandle, lpRemoteData, ipLocalBuffer, SizeOf(Pointer), dwBytesRead); // obtain window handle, copy first 4 bytes Move(ipLocalBuffer, btnWindowHandle, 4); Result := btnWindowHandle; if Assigned(taskbarProcessBuffer) then VirtualFreeEx(taskbarProcessHandle, taskbarProcessBuffer, 0, MEM_RELEASE); end; finally CloseHandle(taskbarProcessHandle); end; end; end; |
Re: Handle einer Form aus Taskbareintrag erhalten
Das ist ja wirklich super :thumb:
Ich habe eben den ersten Codeabschnitt kopiert und eingefügt und das funktioniert auch ohne Probleme. Der 2. Abschnitt geht aber noch nicht ganz. Egal welchen Button ich betätige, es wird immer der selbe Wert zurückgegeben. Ich bin sicher, das Problem wird auch noch gelöst. Jetzt werde ich aber nichts mehr machen, morgen steht Geschichte Abi-Prüfung an. Gruß Mazel |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:32 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