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;