Einzelnen Beitrag anzeigen

Benutzerbild von toms
toms
(CodeLib-Manager)

Registriert seit: 10. Jun 2002
4.648 Beiträge
 
Delphi XE Professional
 
#2

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 22. Apr 2007, 12:16
Hallo Mazel

Zitat von msdn2.microsoft.com:
TB_HITTEST Message
Determines where a point lies in a toolbar control.
Zudem musst du mit OpenProcess / VirtualAllocEx / WriteProcessMemory arbeiten.

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:
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);
Danach muesste man den Code mit folgendem Kombinieren, um an das Window Handle zu kommen:

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 - &#1101;&#1090;&#1086; &#1080;&#1085;&#1076;&#1077;&#1082;&#1089; &#1082;&#1085;&#1086;&#1087;&#1082;&#1080; &#1085;&#1072; &#1090;&#1072;&#1089;&#1082;&#1073;&#1072;&#1088;&#1077;
// 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);
Thomas
  Mit Zitat antworten Zitat