Einzelnen Beitrag anzeigen

Benutzerbild von toms
toms
(CodeLib-Manager)

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

Re: Handle einer Form aus Taskbareintrag erhalten

  Alt 23. Apr 2007, 21:23
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);
Thomas
  Mit Zitat antworten Zitat