function FileDroppedAtIcon(
const a_hWndOwner: HWND;
const a_iButtonID: integer;
const PPoint: TPoint): boolean;
var
hWndTray, hWndOfIconOwner: HWND;
dwTrayProcessID, dwBytesRead: DWORD;
hTrayProc: THandle;
iButtonsCount, iButton, iIconId: integer;
lpData: Pointer;
buttonData: TTBBUTTON;
bIconFound: BOOL;
dwExtraData:
array[0..1]
of DWORD;
rcPosition: TRect;
begin
hWndTray:=FindTrayHWND;
{FindTrayHWND s.o.}
//now we have to get an ID of the parent process for system tray
dwTrayProcessID:=DWORD(-1);
GetWindowThreadProcessId(hWndTray, dwTrayProcessID);
//here we get a handle to tray application process
hTrayProc:=OpenProcess(PROCESS_ALL_ACCESS, false, dwTrayProcessID);
//now we check how many buttons is there - should be more than 0
iButtonsCount:=SendMessage(hWndTray, TB_BUTTONCOUNT, 0, 0);
//We want to get data from another process - it's not possible
//to just send messages like TB_GETBUTTON with a locally
//allocated buffer for return data. Pointer to locally allocated
//data has no usefull meaning in a context of another
//process (since Win95) - so we need
//to allocate some memory inside Tray process.
//We allocate sizeof(TBBUTTON) bytes of memory -
//because TBBUTTON is the biggest structure we will fetch.
//But this buffer will be also used to get smaller
//pieces of data like RECT structures.
lpData:=VirtualAllocEx(hTrayProc,
nil, SizeOf(TTBBUTTON), MEM_COMMIT, PAGE_READWRITE);
bIconFound:=false;
for iButton := 0
to iButtonsCount - 1
do
begin
//first let's read TBUTTON information
//about each button in a task bar of tray
dwBytesRead:=DWORD(-1);
SendMessage(hWndTray, TB_GETBUTTON, iButton, LPARAM(lpData));
//we filled lpData with details of iButton icon of toolbar
//- now let's copy this data from tray application
//back to our process
ReadProcessMemory(hTrayProc, lpData, @buttonData, SizeOf(TTBBUTTON), dwBytesRead);
//let's read extra data of each button:
//there will be a HWND of the window that
//created an icon and icon ID
dwExtraData[0] := 0;
dwExtraData[1] := 0;
ReadProcessMemory(hTrayProc, Pointer(buttonData.dwData), @dwExtraData, SizeOf(dwExtraData), dwBytesRead);
hWndOfIconOwner:=HWND(dwExtraData[0]);
iIconId:=Integer(dwExtraData[1]);
if (hWndOfIconOwner <> a_hWndOwner)
or (iIconId <> a_iButtonID)
then
begin
Continue;
{sollte man hier nicht lieber den nachfolgenden Code
reinschreiben, anstatt eine if Abfrage später auf
Break zu prüfen?}
end;
//we found our icon - in WinXP it could be hidden - let's check it:
if (buttonData.fsState
and TBSTATE_HIDDEN) > 0
then
begin
Break;
end;
//now just ask a tool bar of rectangle of our icon
SendMessage(hWndTray, TB_GETITEMRECT, iButton, LPARAM(lpData));
ReadProcessMemory(hTrayProc, lpData, @rcPosition, SizeOf(TRECT), dwBytesRead);
MapWindowPoints(hWndTray, 0, rcPosition, 2);
if (PPoint.X > rcPosition.Left)
and (PPoint.X < rcPosition.Right)
and
(PPoint.Y > rcPosition.Top)
and (PPoint.Y < rcPosition.Bottom)
then
begin
//stuff dropped at our icon
bIconFound:=true;
Break;
end;
end;
VirtualFreeEx(hTrayProc, lpData, 0, MEM_RELEASE);
CloseHandle(hTrayProc);
result:=bIconFound;
end;