diff --git a/.gitattributes b/.gitattributes index 747a0cc584..069d66743b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4283,7 +4283,7 @@ lcl/interfaces/win32/win32memostrings.inc svneol=native#text/pascal lcl/interfaces/win32/win32object.inc svneol=native#text/pascal lcl/interfaces/win32/win32proc.pp svneol=native#text/pascal lcl/interfaces/win32/win32themes.pas svneol=native#text/pascal -lcl/interfaces/win32/win32trayicon.inc -text +lcl/interfaces/win32/win32trayicon.inc svneol=native#text/pascal lcl/interfaces/win32/win32uxtheme.pas svneol=native#text/pascal lcl/interfaces/win32/win32winapi.inc svneol=native#text/pascal lcl/interfaces/win32/win32winapih.inc svneol=native#text/pascal diff --git a/lcl/interfaces/win32/win32trayicon.inc b/lcl/interfaces/win32/win32trayicon.inc index c750660688..913f4e71a3 100644 --- a/lcl/interfaces/win32/win32trayicon.inc +++ b/lcl/interfaces/win32/win32trayicon.inc @@ -1,422 +1,422 @@ -{%MainUnit win32wsextctrls.pp} -{ $Id: win32trayicon.inc 11994 2007-09-10 22:30:15Z marc $ } -{****************************************************************************** - Implementation of TWin32WSCustomTrayIcon - - ***************************************************************************** - * * - * This file is part of the Lazarus Component Library (LCL) * - * * - * See the file COPYING.modifiedLGPL.txt, included in this distribution, * - * for details about the copyright. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * - * * - ***************************************************************************** -} - -{ TWin32WSCustomTrayIcon } - -type - // IE 5+ version of TNotifyIconDataW - TNotifyIconDataW2 = record - cbSize: DWORD; - hWnd: HWND; - uID: UINT; - uFlags: UINT; - uCallbackMessage: UINT; - hIcon: HICON; - szTip: array [0..127] of WideChar; - dwState: DWORD; - dwStateMask: DWORD; - szInfo: array [0..255] of WideChar; - u: record - case longint of - 0 : ( uTimeout : UINT ); - 1 : ( uVersion : UINT ); - end; - szInfoTitle: array[0..63] of WideChar; - dwInfoFlags: DWORD; - end; - -const - szClassName = 'TTrayIconClass'; - szAppTitle = 'apptitle'; - uIDTrayIcon = 25; - -var - vwsTrayIcon: TCustomTrayIcon; - -{******************************************************************* -* TrayWndProc () -* -* DESCRIPTION: Window procedure that processes messages for the -* systray icon -* -* PARAMETERS: Standard Mouse Messages have this parameters: -* -* fwKeys = wParam; // key flags -* xPos = LOWORD(lParam); // horizontal position of cursor -* yPos = HIWORD(lParam); // vertical position of cursor -* //* Those positions seam to be wrong -* // Use Mouse.CursorPos instead -* -* RETURNS: A pointer to the newly created object -* -*******************************************************************} -function TrayWndProc(Handle: HWND; iMsg: UINT; WParam_: WPARAM; LParam_:LPARAM):LRESULT; stdcall; -var - pt: TPoint; -begin - if iMsg = WM_USER + uIDTrayIcon then - begin - case LParam_ of - WM_RBUTTONUP: - begin - if Assigned(vwsTrayIcon.OnMouseUp) then vwsTrayIcon.OnMouseUp(Application, - mbRight, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); - if Assigned(vwsTrayIcon.PopUpMenu) then - begin - pt := Mouse.CursorPos;// Gets cursor position in screen coords - - // Apparently SetForegroundWindow and PostMessage are necessary - // because we're invoking the shortcut menu from a notification icon - // This is an attempt to prevent from messing with the Z-order - SetForegroundWindow(Handle); - PostMessage(Handle, WM_NULL, 0, 0); - vwsTrayIcon.PopUpMenu.Popup(pt.x, pt.y); - end; - end; - WM_RBUTTONDOWN: if Assigned(vwsTrayIcon.OnMouseDown) then vwsTrayIcon.OnMouseDown(Application, - mbRight, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); - WM_RBUTTONDBLCLK: if Assigned(vwsTrayIcon.OnDblClick) then vwsTrayIcon.OnDblClick(Application); - - WM_MBUTTONDOWN: if Assigned(vwsTrayIcon.OnMouseDown) then vwsTrayIcon.OnMouseDown(Application, - mbMiddle, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); - WM_MBUTTONUP: if Assigned(vwsTrayIcon.OnMouseUp) then vwsTrayIcon.OnMouseUp(Application, - mbMiddle, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); - - WM_LBUTTONUP: - begin - if Assigned(vwsTrayIcon.OnMouseUp) then vwsTrayIcon.OnMouseUp(Application, - mbLeft, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); - if Assigned(vwsTrayIcon.OnClick) then vwsTrayIcon.OnClick(Application); - end; - WM_LBUTTONDOWN: if Assigned(vwsTrayIcon.OnMouseDown) then vwsTrayIcon.OnMouseDown(Application, - mbLeft, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); - WM_LBUTTONDBLCLK: if Assigned(vwsTrayIcon.OnDblClick) then vwsTrayIcon.OnDblClick(Application); - - WM_MOUSEMOVE: if Assigned(vwsTrayIcon.OnMouseMove) then - vwsTrayIcon.OnMouseMove(Application, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); - end; - - Result := 1; - Exit; - end; - - Result := DefWindowProc(Handle, iMsg, WParam_, LParam_); -end; - -{ TWin32WSCustomTrayIcon } - -{******************************************************************* -* TWin32WSCustomTrayIcon.Hide () -* -* DESCRIPTION: Hides the main tray icon of the program -* -* PARAMETERS: None -* -* RETURNS: True if sucessfull, otherwise False -* -*******************************************************************} -class function TWin32WSCustomTrayIcon.Hide(const ATrayIcon: TCustomTrayIcon): Boolean; -var - tnid: TNotifyIconData; -begin - // Fill TNotifyIconData - FillChar(tnid, SizeOf(tnid), 0); - tnid.cbSize := SizeOf(TNotifyIconData); - tnid.hWnd := ATrayIcon.Handle; - tnid.uID := uIDTrayIcon; - - // Remove the icon - Result := Shell_NotifyIconA(NIM_DELETE, @tnid); - - // Destroys the helper Windows - PostMessage(ATrayIcon.Handle, WM_CLOSE, 0, 0); - PostMessage(ATrayIcon.Handle, WM_DESTROY, 0, 0); -end; - -{******************************************************************* -* TWin32WSCustomTrayIcon.Show () -* -* DESCRIPTION: Shows the main tray icon of the program -* -* PARAMETERS: None -* -* RETURNS: True if sucessfull, otherwise False -* -*******************************************************************} -class function TWin32WSCustomTrayIcon.Show(const ATrayIcon: TCustomTrayIcon): Boolean; -var - tnida: TNotifyIconDataA; - {$ifdef WindowsUnicodeSupport} - tnidw: TNotifyIconDataW2; - AnsiBuffer: ansistring; - WideBuffer: widestring; - {$endif} - Window: Windows.TWndClassEx; -begin - vwsTrayIcon := ATrayIcon; - - ZeroMemory(@Window, SizeOf(TWndClassEx)); - Window.cbSize := SizeOf(TWndClassEx); - Window.style := CS_OWNDC; - Window.lpfnWndProc := @TrayWndProc; - Window.cbClsExtra := 0; - Window.cbWndExtra := 0; - Window.hInstance := hInstance; -// Window.hIcon := Icon.Handle; - Window.hCursor := LoadCursor(0, IDC_ARROW); - Window.hbrBackground := HBRUSH(GetStockObject(NULL_BRUSH)); - Window.lpszMenuName := nil; - Window.lpszClassName := szClassName; -// Window.hIconSm := hSmallIcon; - - Windows.RegisterClassEx(Window); - - ATrayIcon.Handle := CreateWindowEx( - 0, //* Ensure that there will be no button in the bar */ - szClassName, //* Name of the registered class */ - szAppTitle, //* Title of the window */ - 0, //* Style of the window */ - 0, //* x-position (at beginning) */ - 0, //* y-position (at beginning) */ - CW_USEDEFAULT, //* window width */ - CW_USEDEFAULT, //* window height */ - 0, //* handle to parent or owner window */ - 0, //* handle to menu */ - hInstance, //* handle to application instance */ - nil); //* pointer to window-creation data */ - - {$ifdef WindowsUnicodeSupport} - if UnicodeEnabledOS then - begin - // Fill TNotifyIconDataW - FillChar(tnidw, SizeOf(tnidw), 0); - tnidw.cbSize := SizeOf(tnidw); - tnidw.hWnd := ATrayIcon.Handle; - tnidw.uID := uIDTrayIcon; - tnidw.uFlags := NIF_MESSAGE or NIF_ICON; - if (ATrayIcon.Hint <> '') then tnidw.uFlags := tnidw.uFlags or NIF_TIP; - tnidw.uCallbackMessage := WM_USER + uIDTrayIcon; - tnidw.hIcon := ATrayIcon.Icon.Handle; - - WideBuffer := UTF8ToUTF16(ATrayIcon.Hint); - WideStrLCopy(@tnidw.szTip, PWideChar(WideBuffer), 127); - - Result := Shell_NotifyIconW(NIM_ADD, @tnidw); - if not Result then - begin - // Try old version of TNotifyIconDataW - tnidw.cbSize := SizeOf(TNotifyIconDataW); - WideStrLCopy(@tnidw.szTip, PWideChar(WideBuffer), 63); - Result := Shell_NotifyIconW(NIM_MODIFY, @tnidw); - end; - end - else - begin - // Fill TNotifyIconDataA - FillChar(tnida, SizeOf(tnida), 0); - tnida.cbSize := SizeOf(TNotifyIconDataA); - tnida.hWnd := ATrayIcon.Handle; - tnida.uID := uIDTrayIcon; - tnida.uFlags := NIF_MESSAGE or NIF_ICON; - if (ATrayIcon.Hint <> '') then tnida.uFlags := tnida.uFlags or NIF_TIP; - tnida.uCallbackMessage := WM_USER + uIDTrayIcon; - tnida.hIcon := ATrayIcon.Icon.Handle; - - AnsiBuffer := UTF8ToAnsi(ATrayIcon.Hint); - StrLCopy(@tnida.szTip, PChar(AnsiBuffer), 127); - - Result := Shell_NotifyIconA(NIM_ADD, @tnida); - end; - {$else} - // Fill TNotifyIconDataA - FillChar(tnida, SizeOf(tnida), 0); - tnida.cbSize := SizeOf(TNotifyIconDataA); - tnida.hWnd := ATrayIcon.Handle; - tnida.uID := uIDTrayIcon; - tnida.uFlags := NIF_MESSAGE or NIF_ICON; - if (ATrayIcon.Hint <> '') then tnida.uFlags := tnida.uFlags or NIF_TIP; - tnida.uCallbackMessage := WM_USER + uIDTrayIcon; - tnida.hIcon := ATrayIcon.Icon.Handle; - - StrLCopy(@tnida.szTip, PChar(ATrayIcon.Hint), 127); - - // Create Taskbar icon - Result := Shell_NotifyIconA(NIM_ADD, @tnida); - {$endif} -end; - -{******************************************************************* -* TWin32WSCustomTrayIcon.InternalUpdate () -* -* DESCRIPTION: Makes modifications to the Icon while running -* i.e. without hiding it and showing again -* -*******************************************************************} -class procedure TWin32WSCustomTrayIcon.InternalUpdate(const ATrayIcon: TCustomTrayIcon); -var - tnida: TNotifyIconDataA; - {$ifdef WindowsUnicodeSupport} - tnidw: TNotifyIconDataW2; - AnsiBuffer: ansistring; - WideBuffer: widestring; - {$endif} -begin - {$ifdef WindowsUnicodeSupport} - if UnicodeEnabledOS then - begin - // Fill TNotifyIconDataW - FillChar(tnidw, SizeOf(tnidw), 0); - tnidw.cbSize := SizeOf(tnidw); - tnidw.hWnd := ATrayIcon.Handle; - tnidw.uID := uIDTrayIcon; - tnidw.hIcon := ATrayIcon.Icon.Handle; - tnidw.uFlags := NIF_TIP or NIF_ICON; - - WideBuffer := UTF8ToUTF16(ATrayIcon.Hint); - WideStrLCopy(@tnidw.szTip, PWideChar(WideBuffer), 127); - - if not Shell_NotifyIconW(NIM_MODIFY, @tnidw) then - begin - // Try old version of TNotifyIconDataW - tnidw.cbSize := SizeOf(TNotifyIconDataW); - WideStrLCopy(@tnidw.szTip, PWideChar(WideBuffer), 63); - Shell_NotifyIconW(NIM_MODIFY, @tnidw); - end; - end - else - begin - // Fill TNotifyIconDataA - FillChar(tnida, SizeOf(tnida), 0); - tnida.cbSize := SizeOf(TNotifyIconDataA); - tnida.hWnd := ATrayIcon.Handle; - tnida.uID := uIDTrayIcon; - tnida.hIcon := ATrayIcon.Icon.Handle; - tnida.uFlags := NIF_TIP or NIF_ICON; - - AnsiBuffer := UTF8ToAnsi(ATrayIcon.Hint); - StrLCopy(@tnida.szTip, PChar(AnsiBuffer), 127); - - Shell_NotifyIconA(NIM_MODIFY, @tnida); - end; - {$else} - // Fill TNotifyIconDataA - FillChar(tnida, SizeOf(tnida), 0); - tnida.cbSize := SizeOf(TNotifyIconDataA); - tnida.hWnd := ATrayIcon.Handle; - tnida.uID := uIDTrayIcon; - tnida.uFlags := NIF_TIP; - - StrLCopy(@tnida.szTip, PChar(ATrayIcon.Hint), 127); - - // Create Taskbar icon - Shell_NotifyIconA(NIM_MODIFY, @tnida); - {$endif} -end; - -{******************************************************************* -* TWin32WSCustomTrayIcon.ShowBalloonHint () -* -* DESCRIPTION: Shows a small message balloon near the tray icon -* -* RETURNS: False if the default cross-platform hint should be used -* True if a platform-specific hint will be used -* -*******************************************************************} -class function TWin32WSCustomTrayIcon.ShowBalloonHint(const ATrayIcon: TCustomTrayIcon): Boolean; -const - FlagsMap: array[TBalloonFlags] of dword = (NIIF_NONE, NIIF_INFO, NIIF_WARNING, NIIF_ERROR); -var - NotifyData: TNotifyIconDataW2; - w: WideString; -begin - Result := UnicodeEnabledOS; - if not Result then exit; - - NotifyData.cbSize:=SizeOf(NotifyData); - NotifyData.hWnd := ATrayIcon.Handle; - NotifyData.uID := uIDTrayIcon; - NotifyData.uFlags:=NIF_INFO; - NotifyData.u.uTimeout:=ATrayIcon.BalloonTimeout; - w:=UTF8ToUTF16(ATrayIcon.BalloonHint); - WideStrLCopy(@NotifyData.szInfo, PWideChar(w), High(NotifyData.szInfo)); - w:=UTF8ToUTF16(ATrayIcon.BalloonTitle); - WideStrLCopy(@NotifyData.szInfoTitle, PWideChar(w), High(NotifyData.szInfoTitle)); - NotifyData.dwInfoFlags:=FlagsMap[ATrayIcon.BalloonFlags]; - - Result:= Shell_NotifyIconW(NIM_MODIFY, @NotifyData); -end; - -{******************************************************************* -* TWin32WSCustomTrayIcon.GetPosition () -* -* DESCRIPTION: Returns the position of the tray icon on the display. -* This function is utilized to show message boxes near -* the icon -* -*******************************************************************} -function EnumChildProc(handle : HWND; lp : LParam): LongBool; stdcall; -var - s : string; - l : integer; -begin - SetLength(s, 255); - l := GetClassName(handle, PChar(s), Length(s)); - if l = 0 then Exit(False) - else - SetLength(s, l); - if Pos('ToolbarWindow32', s) > 0 then - begin - lp := handle; - result := false; - end - else - result := true; -end; - -class function TWin32WSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint; -var - hWndTaskbar, hWndTray: HWND; - TaskbarRect, TrayRect: TRect; -begin - Result := Point(0, 0); - - { First we get the Taskbar window and it's screen position } - hWndTaskbar := FindWindow('Shell_TrayWnd', nil); - - if hWndTaskbar = 0 then Exit; - - Windows.GetWindowRect(hWndTaskbar, @TaskbarRect); - - hWndTray := ATrayIcon.Handle; - - { Then we locate inside the Tray area, which is just a Toolbar control } - EnumChildWindows(hWndTaskbar, @EnumChildProc,LParam(hWndTray)); - - if hWndTray = 0 then Exit; - - { And we get the size of that control } - Windows.GetWindowRect(hWndTray, @TrayRect); - // OBS: Here TrayRect seams to have a wrong value, so we don't use it - - { Returns an aproximate position of the tray area } - Result.X := TaskbarRect.Right; - Result.Y := TaskbarRect.Top; -end; - - +{%MainUnit win32wsextctrls.pp} +{ $Id: win32trayicon.inc 11994 2007-09-10 22:30:15Z marc $ } +{****************************************************************************** + Implementation of TWin32WSCustomTrayIcon + + ***************************************************************************** + * * + * This file is part of the Lazarus Component Library (LCL) * + * * + * See the file COPYING.modifiedLGPL.txt, included in this distribution, * + * for details about the copyright. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * * + ***************************************************************************** +} + +{ TWin32WSCustomTrayIcon } + +type + // IE 5+ version of TNotifyIconDataW + TNotifyIconDataW2 = record + cbSize: DWORD; + hWnd: HWND; + uID: UINT; + uFlags: UINT; + uCallbackMessage: UINT; + hIcon: HICON; + szTip: array [0..127] of WideChar; + dwState: DWORD; + dwStateMask: DWORD; + szInfo: array [0..255] of WideChar; + u: record + case longint of + 0 : ( uTimeout : UINT ); + 1 : ( uVersion : UINT ); + end; + szInfoTitle: array[0..63] of WideChar; + dwInfoFlags: DWORD; + end; + +const + szClassName = 'TTrayIconClass'; + szAppTitle = 'apptitle'; + uIDTrayIcon = 25; + +var + vwsTrayIcon: TCustomTrayIcon; + +{******************************************************************* +* TrayWndProc () +* +* DESCRIPTION: Window procedure that processes messages for the +* systray icon +* +* PARAMETERS: Standard Mouse Messages have this parameters: +* +* fwKeys = wParam; // key flags +* xPos = LOWORD(lParam); // horizontal position of cursor +* yPos = HIWORD(lParam); // vertical position of cursor +* //* Those positions seam to be wrong +* // Use Mouse.CursorPos instead +* +* RETURNS: A pointer to the newly created object +* +*******************************************************************} +function TrayWndProc(Handle: HWND; iMsg: UINT; WParam_: WPARAM; LParam_:LPARAM):LRESULT; stdcall; +var + pt: TPoint; +begin + if iMsg = WM_USER + uIDTrayIcon then + begin + case LParam_ of + WM_RBUTTONUP: + begin + if Assigned(vwsTrayIcon.OnMouseUp) then vwsTrayIcon.OnMouseUp(Application, + mbRight, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); + if Assigned(vwsTrayIcon.PopUpMenu) then + begin + pt := Mouse.CursorPos;// Gets cursor position in screen coords + + // Apparently SetForegroundWindow and PostMessage are necessary + // because we're invoking the shortcut menu from a notification icon + // This is an attempt to prevent from messing with the Z-order + SetForegroundWindow(Handle); + PostMessage(Handle, WM_NULL, 0, 0); + vwsTrayIcon.PopUpMenu.Popup(pt.x, pt.y); + end; + end; + WM_RBUTTONDOWN: if Assigned(vwsTrayIcon.OnMouseDown) then vwsTrayIcon.OnMouseDown(Application, + mbRight, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); + WM_RBUTTONDBLCLK: if Assigned(vwsTrayIcon.OnDblClick) then vwsTrayIcon.OnDblClick(Application); + + WM_MBUTTONDOWN: if Assigned(vwsTrayIcon.OnMouseDown) then vwsTrayIcon.OnMouseDown(Application, + mbMiddle, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); + WM_MBUTTONUP: if Assigned(vwsTrayIcon.OnMouseUp) then vwsTrayIcon.OnMouseUp(Application, + mbMiddle, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); + + WM_LBUTTONUP: + begin + if Assigned(vwsTrayIcon.OnMouseUp) then vwsTrayIcon.OnMouseUp(Application, + mbLeft, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); + if Assigned(vwsTrayIcon.OnClick) then vwsTrayIcon.OnClick(Application); + end; + WM_LBUTTONDOWN: if Assigned(vwsTrayIcon.OnMouseDown) then vwsTrayIcon.OnMouseDown(Application, + mbLeft, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); + WM_LBUTTONDBLCLK: if Assigned(vwsTrayIcon.OnDblClick) then vwsTrayIcon.OnDblClick(Application); + + WM_MOUSEMOVE: if Assigned(vwsTrayIcon.OnMouseMove) then + vwsTrayIcon.OnMouseMove(Application, KeysToShiftState(WParam_), LOWORD(lParam_), HIWORD(lParam_)); + end; + + Result := 1; + Exit; + end; + + Result := DefWindowProc(Handle, iMsg, WParam_, LParam_); +end; + +{ TWin32WSCustomTrayIcon } + +{******************************************************************* +* TWin32WSCustomTrayIcon.Hide () +* +* DESCRIPTION: Hides the main tray icon of the program +* +* PARAMETERS: None +* +* RETURNS: True if sucessfull, otherwise False +* +*******************************************************************} +class function TWin32WSCustomTrayIcon.Hide(const ATrayIcon: TCustomTrayIcon): Boolean; +var + tnid: TNotifyIconData; +begin + // Fill TNotifyIconData + FillChar(tnid, SizeOf(tnid), 0); + tnid.cbSize := SizeOf(TNotifyIconData); + tnid.hWnd := ATrayIcon.Handle; + tnid.uID := uIDTrayIcon; + + // Remove the icon + Result := Shell_NotifyIconA(NIM_DELETE, @tnid); + + // Destroys the helper Windows + PostMessage(ATrayIcon.Handle, WM_CLOSE, 0, 0); + PostMessage(ATrayIcon.Handle, WM_DESTROY, 0, 0); +end; + +{******************************************************************* +* TWin32WSCustomTrayIcon.Show () +* +* DESCRIPTION: Shows the main tray icon of the program +* +* PARAMETERS: None +* +* RETURNS: True if sucessfull, otherwise False +* +*******************************************************************} +class function TWin32WSCustomTrayIcon.Show(const ATrayIcon: TCustomTrayIcon): Boolean; +var + tnida: TNotifyIconDataA; + {$ifdef WindowsUnicodeSupport} + tnidw: TNotifyIconDataW2; + AnsiBuffer: ansistring; + WideBuffer: widestring; + {$endif} + Window: Windows.TWndClassEx; +begin + vwsTrayIcon := ATrayIcon; + + ZeroMemory(@Window, SizeOf(TWndClassEx)); + Window.cbSize := SizeOf(TWndClassEx); + Window.style := CS_OWNDC; + Window.lpfnWndProc := @TrayWndProc; + Window.cbClsExtra := 0; + Window.cbWndExtra := 0; + Window.hInstance := hInstance; +// Window.hIcon := Icon.Handle; + Window.hCursor := LoadCursor(0, IDC_ARROW); + Window.hbrBackground := HBRUSH(GetStockObject(NULL_BRUSH)); + Window.lpszMenuName := nil; + Window.lpszClassName := szClassName; +// Window.hIconSm := hSmallIcon; + + Windows.RegisterClassEx(Window); + + ATrayIcon.Handle := CreateWindowEx( + 0, //* Ensure that there will be no button in the bar */ + szClassName, //* Name of the registered class */ + szAppTitle, //* Title of the window */ + 0, //* Style of the window */ + 0, //* x-position (at beginning) */ + 0, //* y-position (at beginning) */ + CW_USEDEFAULT, //* window width */ + CW_USEDEFAULT, //* window height */ + 0, //* handle to parent or owner window */ + 0, //* handle to menu */ + hInstance, //* handle to application instance */ + nil); //* pointer to window-creation data */ + + {$ifdef WindowsUnicodeSupport} + if UnicodeEnabledOS then + begin + // Fill TNotifyIconDataW + FillChar(tnidw, SizeOf(tnidw), 0); + tnidw.cbSize := SizeOf(tnidw); + tnidw.hWnd := ATrayIcon.Handle; + tnidw.uID := uIDTrayIcon; + tnidw.uFlags := NIF_MESSAGE or NIF_ICON; + if (ATrayIcon.Hint <> '') then tnidw.uFlags := tnidw.uFlags or NIF_TIP; + tnidw.uCallbackMessage := WM_USER + uIDTrayIcon; + tnidw.hIcon := ATrayIcon.Icon.Handle; + + WideBuffer := UTF8ToUTF16(ATrayIcon.Hint); + WideStrLCopy(@tnidw.szTip, PWideChar(WideBuffer), 127); + + Result := Shell_NotifyIconW(NIM_ADD, @tnidw); + if not Result then + begin + // Try old version of TNotifyIconDataW + tnidw.cbSize := SizeOf(TNotifyIconDataW); + WideStrLCopy(@tnidw.szTip, PWideChar(WideBuffer), 63); + Result := Shell_NotifyIconW(NIM_MODIFY, @tnidw); + end; + end + else + begin + // Fill TNotifyIconDataA + FillChar(tnida, SizeOf(tnida), 0); + tnida.cbSize := SizeOf(TNotifyIconDataA); + tnida.hWnd := ATrayIcon.Handle; + tnida.uID := uIDTrayIcon; + tnida.uFlags := NIF_MESSAGE or NIF_ICON; + if (ATrayIcon.Hint <> '') then tnida.uFlags := tnida.uFlags or NIF_TIP; + tnida.uCallbackMessage := WM_USER + uIDTrayIcon; + tnida.hIcon := ATrayIcon.Icon.Handle; + + AnsiBuffer := UTF8ToAnsi(ATrayIcon.Hint); + StrLCopy(@tnida.szTip, PChar(AnsiBuffer), 127); + + Result := Shell_NotifyIconA(NIM_ADD, @tnida); + end; + {$else} + // Fill TNotifyIconDataA + FillChar(tnida, SizeOf(tnida), 0); + tnida.cbSize := SizeOf(TNotifyIconDataA); + tnida.hWnd := ATrayIcon.Handle; + tnida.uID := uIDTrayIcon; + tnida.uFlags := NIF_MESSAGE or NIF_ICON; + if (ATrayIcon.Hint <> '') then tnida.uFlags := tnida.uFlags or NIF_TIP; + tnida.uCallbackMessage := WM_USER + uIDTrayIcon; + tnida.hIcon := ATrayIcon.Icon.Handle; + + StrLCopy(@tnida.szTip, PChar(ATrayIcon.Hint), 127); + + // Create Taskbar icon + Result := Shell_NotifyIconA(NIM_ADD, @tnida); + {$endif} +end; + +{******************************************************************* +* TWin32WSCustomTrayIcon.InternalUpdate () +* +* DESCRIPTION: Makes modifications to the Icon while running +* i.e. without hiding it and showing again +* +*******************************************************************} +class procedure TWin32WSCustomTrayIcon.InternalUpdate(const ATrayIcon: TCustomTrayIcon); +var + tnida: TNotifyIconDataA; + {$ifdef WindowsUnicodeSupport} + tnidw: TNotifyIconDataW2; + AnsiBuffer: ansistring; + WideBuffer: widestring; + {$endif} +begin + {$ifdef WindowsUnicodeSupport} + if UnicodeEnabledOS then + begin + // Fill TNotifyIconDataW + FillChar(tnidw, SizeOf(tnidw), 0); + tnidw.cbSize := SizeOf(tnidw); + tnidw.hWnd := ATrayIcon.Handle; + tnidw.uID := uIDTrayIcon; + tnidw.hIcon := ATrayIcon.Icon.Handle; + tnidw.uFlags := NIF_TIP or NIF_ICON; + + WideBuffer := UTF8ToUTF16(ATrayIcon.Hint); + WideStrLCopy(@tnidw.szTip, PWideChar(WideBuffer), 127); + + if not Shell_NotifyIconW(NIM_MODIFY, @tnidw) then + begin + // Try old version of TNotifyIconDataW + tnidw.cbSize := SizeOf(TNotifyIconDataW); + WideStrLCopy(@tnidw.szTip, PWideChar(WideBuffer), 63); + Shell_NotifyIconW(NIM_MODIFY, @tnidw); + end; + end + else + begin + // Fill TNotifyIconDataA + FillChar(tnida, SizeOf(tnida), 0); + tnida.cbSize := SizeOf(TNotifyIconDataA); + tnida.hWnd := ATrayIcon.Handle; + tnida.uID := uIDTrayIcon; + tnida.hIcon := ATrayIcon.Icon.Handle; + tnida.uFlags := NIF_TIP or NIF_ICON; + + AnsiBuffer := UTF8ToAnsi(ATrayIcon.Hint); + StrLCopy(@tnida.szTip, PChar(AnsiBuffer), 127); + + Shell_NotifyIconA(NIM_MODIFY, @tnida); + end; + {$else} + // Fill TNotifyIconDataA + FillChar(tnida, SizeOf(tnida), 0); + tnida.cbSize := SizeOf(TNotifyIconDataA); + tnida.hWnd := ATrayIcon.Handle; + tnida.uID := uIDTrayIcon; + tnida.uFlags := NIF_TIP; + + StrLCopy(@tnida.szTip, PChar(ATrayIcon.Hint), 127); + + // Create Taskbar icon + Shell_NotifyIconA(NIM_MODIFY, @tnida); + {$endif} +end; + +{******************************************************************* +* TWin32WSCustomTrayIcon.ShowBalloonHint () +* +* DESCRIPTION: Shows a small message balloon near the tray icon +* +* RETURNS: False if the default cross-platform hint should be used +* True if a platform-specific hint will be used +* +*******************************************************************} +class function TWin32WSCustomTrayIcon.ShowBalloonHint(const ATrayIcon: TCustomTrayIcon): Boolean; +const + FlagsMap: array[TBalloonFlags] of dword = (NIIF_NONE, NIIF_INFO, NIIF_WARNING, NIIF_ERROR); +var + NotifyData: TNotifyIconDataW2; + w: WideString; +begin + Result := UnicodeEnabledOS; + if not Result then exit; + + NotifyData.cbSize:=SizeOf(NotifyData); + NotifyData.hWnd := ATrayIcon.Handle; + NotifyData.uID := uIDTrayIcon; + NotifyData.uFlags:=NIF_INFO; + NotifyData.u.uTimeout:=ATrayIcon.BalloonTimeout; + w:=UTF8ToUTF16(ATrayIcon.BalloonHint); + WideStrLCopy(@NotifyData.szInfo, PWideChar(w), High(NotifyData.szInfo)); + w:=UTF8ToUTF16(ATrayIcon.BalloonTitle); + WideStrLCopy(@NotifyData.szInfoTitle, PWideChar(w), High(NotifyData.szInfoTitle)); + NotifyData.dwInfoFlags:=FlagsMap[ATrayIcon.BalloonFlags]; + + Result:= Shell_NotifyIconW(NIM_MODIFY, @NotifyData); +end; + +{******************************************************************* +* TWin32WSCustomTrayIcon.GetPosition () +* +* DESCRIPTION: Returns the position of the tray icon on the display. +* This function is utilized to show message boxes near +* the icon +* +*******************************************************************} +function EnumChildProc(handle : HWND; lp : LParam): LongBool; stdcall; +var + s : string; + l : integer; +begin + SetLength(s, 255); + l := GetClassName(handle, PChar(s), Length(s)); + if l = 0 then Exit(False) + else + SetLength(s, l); + if Pos('ToolbarWindow32', s) > 0 then + begin + lp := handle; + result := false; + end + else + result := true; +end; + +class function TWin32WSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint; +var + hWndTaskbar, hWndTray: HWND; + TaskbarRect, TrayRect: TRect; +begin + Result := Point(0, 0); + + { First we get the Taskbar window and it's screen position } + hWndTaskbar := FindWindow('Shell_TrayWnd', nil); + + if hWndTaskbar = 0 then Exit; + + Windows.GetWindowRect(hWndTaskbar, @TaskbarRect); + + hWndTray := ATrayIcon.Handle; + + { Then we locate inside the Tray area, which is just a Toolbar control } + EnumChildWindows(hWndTaskbar, @EnumChildProc,LParam(hWndTray)); + + if hWndTray = 0 then Exit; + + { And we get the size of that control } + Windows.GetWindowRect(hWndTray, @TrayRect); + // OBS: Here TrayRect seams to have a wrong value, so we don't use it + + { Returns an aproximate position of the tray area } + Result.X := TaskbarRect.Right; + Result.Y := TaskbarRect.Top; +end; + +