30#include <sfx2/strings.hrc>
33#include <osl/diagnose.h>
34#include <osl/thread.h>
35#include <systools/win32/qswin32.h>
43#define EXECUTER_WINDOWCLASS L"SO Executer Class"
44#define EXECUTER_WINDOWNAME L"SO Executer Window"
47#define ID_QUICKSTART 1
58#define IDM_STARTCENTER 14
61#define ICON_LO_DEFAULT 1
62#define ICON_TEXT_DOCUMENT 2
63#define ICON_SPREADSHEET_DOCUMENT 4
64#define ICON_DRAWING_DOCUMENT 6
65#define ICON_PRESENTATION_DOCUMENT 8
66#define ICON_TEMPLATE 11
67#define ICON_DATABASE_DOCUMENT 12
68#define ICON_MATH_DOCUMENT 13
71#define SFX_TASKBAR_NOTIFICATION WM_USER+1
77static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis);
78static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis);
91static void addMenuItem( HMENU hMenu, UINT
id, UINT iconId,
const OUString& text,
int& pos,
bool bOwnerdraw,
const OUString& module )
93 MENUITEMINFOW
mi = {};
95 mi.cbSize =
sizeof(
mi );
96 if(
id ==
static_cast<UINT
>( -1 ) )
99 mi.fType=MFT_SEPARATOR;
105 mi.fMask=MIIM_FTYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
106 mi.fType=MFT_OWNERDRAW;
108 MYITEM *pMyItem =
new MYITEM;
109 pMyItem->text =
text;
110 pMyItem->iconId = iconId;
112 mi.dwItemData =
reinterpret_cast<ULONG_PTR
>(pMyItem);
116 mi.fMask=MIIM_STRING | MIIM_STATE | MIIM_ID;
117 mi.dwTypeData = o3tl::toW(
119 mi.cch =
text.getLength();
122 mi.fState = MFS_ENABLED;
125 mi.fState |= MFS_DEFAULT;
128 InsertMenuItemW( hMenu,
pos++,
TRUE, &
mi );
136 HMENU hMenu = CreatePopupMenu();
140 OSL_ENSURE( pShutdownIcon,
"ShutdownIcon instance empty!");
146 ::std::set< OUString > aFileNewAppsAvailable;
150 if ( !newMenuProp.sURL.isEmpty() )
151 aFileNewAppsAvailable.insert( newMenuProp.sURL );
155 struct MenuEntryDescriptor
160 rtl::OUStringConstExpr sURLDescription;
161 }
static const aMenuItems[] =
172 for (
const auto& [eModuleIdentifier, nMenuItemID, nMenuIconID, sURL] : aMenuItems)
178 if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() )
190 SfxResId( STR_QUICKSTART_FROMTEMPLATE ),
pos,
true,
"");
191 addMenuItem( hMenu,
static_cast< UINT
>( -1 ), 0, OUString(),
pos,
false,
"" );
193 addMenuItem( hMenu,
static_cast< UINT
>( -1 ), 0, OUString(),
pos,
false,
"" );
195 addMenuItem( hMenu,
static_cast< UINT
>( -1 ), 0, OUString(),
pos,
false,
"" );
207 if( !hMenu || !IsMenu( hMenu ))
210 MENUITEMINFOW
mi = {};
211 mi.cbSize =
sizeof(
mi );
212 mi.fMask = MIIM_DATA;
214 for (UINT
pos = 0; GetMenuItemInfoW(hMenu,
pos,
true, &
mi); ++
pos)
216 if (MYITEM* pMyItem =
reinterpret_cast<MYITEM*
>(
mi.dwItemData))
218 mi.fMask = MIIM_DATA;
225 OUString strTip =
SfxResId(STR_QUICKSTART_TIP);
229 nid.hIcon =
static_cast<HICON
>(LoadImageW( GetModuleHandleW(
nullptr ), MAKEINTRESOURCEW(
ICON_LO_DEFAULT ),
230 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ),
231 LR_DEFAULTCOLOR | LR_SHARED ));
233 wcsncpy( nid.szTip, o3tl::toW(strTip.getStr()), 64 );
235 nid.cbSize =
sizeof(nid);
239 nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON;
241 Shell_NotifyIconW(NIM_ADD, &nid);
247 static UINT s_uTaskbarRestart = 0;
248 static UINT s_uMsgKillTray = 0;
258 s_uTaskbarRestart = RegisterWindowMessageW(L
"TaskbarCreated");
259 s_uMsgKillTray = RegisterWindowMessageW( SHUTDOWN_QUICKSTART_MESSAGE );
276 OnMeasureItem(hWnd,
reinterpret_cast<LPMEASUREITEMSTRUCT
>(lParam));
280 OnDrawItem(hWnd,
reinterpret_cast<LPDRAWITEMSTRUCT
>(lParam));
289 SAL_WARN_IF(!ret,
"sfx.appl",
"ERROR: PostMessage() failed!");
297 SetForegroundWindow( hWnd );
305 int m = TrackPopupMenuEx(
popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON,
306 pt.x,
pt.y, hWnd,
nullptr );
307 bool const ret = PostMessageW( hWnd, 0, 0, 0 );
308 SAL_WARN_IF(!ret,
"sfx.appl",
"ERROR: PostMessage() failed!");
326 nid.cbSize=
sizeof(nid);
329 Shell_NotifyIconW(NIM_DELETE, &nid);
333 bool const ret2 = PostMessageW(
aExecuterWindow, WM_COMMAND,
m,
reinterpret_cast<LPARAM
>(hWnd));
334 SAL_WARN_IF(!ret2,
"sfx.appl",
"ERROR: PostMessage() failed!");
342 PostQuitMessage( 0 );
343 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
345 if( uMsg == s_uTaskbarRestart )
350 else if ( uMsg == s_uMsgKillTray )
354 nid.cbSize=
sizeof(nid);
357 Shell_NotifyIconW(NIM_DELETE, &nid);
360 SAL_WARN_IF(!ret,
"sfx.appl",
"ERROR: PostMessage() failed!");
363 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
379 switch( LOWORD(wParam) )
423 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
431 osl_setThreadName(
"SystrayThread");
434 QUICKSTART_CLASSNAME,
435 QUICKSTART_WINDOWNAME,
443 GetModuleHandleW(
nullptr ),
451 int const bRet = GetMessageW(&msg,
nullptr, 0, 0);
458 SAL_WARN(
"sfx.appl",
"GetMessageW failed: " << WindowsErrorString(GetLastError()));
461 TranslateMessage( &msg );
462 DispatchMessageW( &msg );
473 WNDCLASSEXW listenerClass;
474 listenerClass.cbSize =
sizeof(listenerClass);
475 listenerClass.style = 0;
477 listenerClass.cbClsExtra = 0;
478 listenerClass.cbWndExtra = 0;
479 listenerClass.hInstance = GetModuleHandleW(
nullptr );
480 listenerClass.hIcon =
nullptr;
481 listenerClass.hCursor =
nullptr;
482 listenerClass.hbrBackground =
nullptr;
483 listenerClass.lpszMenuName =
nullptr;
484 listenerClass.lpszClassName = QUICKSTART_CLASSNAME;
485 listenerClass.hIconSm =
nullptr;
487 RegisterClassExW(&listenerClass);
489 WNDCLASSEXW executerClass;
490 executerClass.cbSize =
sizeof(executerClass);
491 executerClass.style = 0;
493 executerClass.cbClsExtra = 0;
494 executerClass.cbWndExtra = 0;
495 executerClass.hInstance = GetModuleHandleW(
nullptr );
496 executerClass.hIcon =
nullptr;
497 executerClass.hCursor =
nullptr;
498 executerClass.hbrBackground =
nullptr;
499 executerClass.lpszMenuName =
nullptr;
501 executerClass.hIconSm =
nullptr;
503 RegisterClassExW( &executerClass );
515 GetModuleHandleW(
nullptr ),
520 CloseHandle(CreateThread(
nullptr, 0,
SystrayThread,
nullptr, 0, &dwThreadId));
536 UnregisterClassW( QUICKSTART_CLASSNAME, GetModuleHandleW(
nullptr ) );
544 MYITEM *pMyItem =
reinterpret_cast<MYITEM *
>(lpmis->itemData);
545 HDC hdc =
GetDC(hwnd);
548 NONCLIENTMETRICSW ncm = {};
549 ncm.cbSize =
sizeof(ncm);
551 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
554 ncm.lfMenuFont.lfWeight =
FW_BOLD;
556 HFONT hfntOld =
static_cast<HFONT
>(SelectObject(hdc, CreateFontIndirectW( &ncm.lfMenuFont )));
558 GetTextExtentPoint32W(hdc, o3tl::toW(pMyItem->text.getStr()),
559 pMyItem->text.getLength(), &
size);
561 lpmis->itemWidth =
size.cx + 4 + GetSystemMetrics( SM_CXSMICON );
562 lpmis->itemHeight = std::max<int>(
size.cy, GetSystemMetrics( SM_CYSMICON ));
563 lpmis->itemHeight += 4;
565 DeleteObject( SelectObject(hdc, hfntOld) );
566 ReleaseDC(hwnd, hdc);
571 MYITEM *pMyItem =
reinterpret_cast<MYITEM *
>(lpdis->itemData);
572 COLORREF clrPrevText, clrPrevBkgnd;
576 bool fSelected = lpdis->itemState & ODS_SELECTED;
577 bool fDisabled = lpdis->itemState & (ODS_DISABLED | ODS_GRAYED);
581 RECT aRect = lpdis->rcItem;
583 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
586 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) );
588 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
591 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) );
593 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
595 hbrOld =
static_cast<HBRUSH
>(SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) ));
598 PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top,
PATCOPY);
600 int height = aRect.bottom-aRect.top;
605 int cx = GetSystemMetrics( SM_CXSMICON );
606 int cy = GetSystemMetrics( SM_CYSMICON );
607 HICON hIcon(
nullptr );
608 HMODULE hModule( GetModuleHandleW(
nullptr ) );
610 if ( pMyItem->module.getLength() > 0 )
612 LPCWSTR pModuleName = o3tl::toW( pMyItem->module.getStr() );
613 hModule = GetModuleHandleW( pModuleName );
614 if ( hModule ==
nullptr )
616 hModule = LoadLibraryW(pModuleName);
620 hIcon =
static_cast<HICON
>(LoadImageW( hModule, MAKEINTRESOURCEW( pMyItem->iconId ),
622 LR_DEFAULTCOLOR | LR_SHARED ));
625 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
627 DrawStateW( lpdis->hDC, hbrIcon,
nullptr,
reinterpret_cast<LPARAM
>(hIcon), WPARAM(0),
x,
y+(height-cy)/2, 0, 0, DST_ICON | (fDisabled ? (fSelected ? DSS_MONO : DSS_DISABLED) : DSS_NORMAL) );
629 DeleteObject( hbrIcon );
634 NONCLIENTMETRICSW ncm = {};
635 ncm.cbSize =
sizeof(ncm);
637 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
640 if ( lpdis->itemState & ODS_DEFAULT )
641 ncm.lfMenuFont.lfWeight =
FW_BOLD;
643 hfntOld =
static_cast<HFONT
>(SelectObject(lpdis->hDC, CreateFontIndirectW( &ncm.lfMenuFont )));
647 GetTextExtentPointW( lpdis->hDC, o3tl::toW(pMyItem->text.getStr()), pMyItem->text.getLength(), &
size );
649 DrawStateW( lpdis->hDC,
nullptr,
nullptr,
reinterpret_cast<LPARAM
>(pMyItem->text.getStr()), WPARAM(0), aRect.left, aRect.top + (height -
size.cy)/2, 0, 0, DST_TEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) );
652 DeleteObject( SelectObject( lpdis->hDC, hbrOld ) );
653 DeleteObject( SelectObject( lpdis->hDC, hfntOld) );
654 SetTextColor(lpdis->hDC, clrPrevText);
655 SetBkColor(lpdis->hDC, clrPrevBkgnd);
665 if( NOERROR == SHGetMalloc(&pMalloc) )
672#define ALLOC(type, n) static_cast<type *>(HeapAlloc(GetProcessHeap(), 0, sizeof(type) * n ))
673#define FREE(p) HeapFree(GetProcessHeap(), 0, p)
679 HRESULT hHdl = SHGetSpecialFolderLocation(
nullptr, nFolderID, &pidl );
682 if( hHdl == NOERROR )
685 lpFolderA =
ALLOC( WCHAR, 16000 );
687 SHGetPathFromIDListW( pidl, lpFolderA );
688 aFolder = o3tl::toU( lpFolderA );
696OUString ShutdownIcon::GetAutostartFolderNameW32()
701static HRESULT WINAPI
SHCoCreateInstance( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv )
703 HRESULT hResult = E_NOTIMPL;
704 HMODULE hModShell = GetModuleHandleW( L
"SHELL32" );
706 if ( hModShell !=
nullptr )
708 typedef HRESULT (WINAPI *SHCoCreateInstance_PROC)( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv );
710 SHCoCreateInstance_PROC lpfnSHCoCreateInstance =
reinterpret_cast<SHCoCreateInstance_PROC
>(GetProcAddress( hModShell, MAKEINTRESOURCEA(102) ));
712 if ( lpfnSHCoCreateInstance )
713 hResult = lpfnSHCoCreateInstance( lpszReserved, clsid, pUnkUnknown, iid, ppv );
718static bool CreateShortcut(
const OUString& rAbsObject,
const OUString& rAbsObjectPath,
719 const OUString& rAbsShortcut,
const OUString& rDescription,
const OUString& rParameter )
723 CLSID clsid_ShellLink = CLSID_ShellLink;
724 CLSID clsid_IShellLink = IID_IShellLinkW;
726 hres = CoCreateInstance( clsid_ShellLink,
nullptr, CLSCTX_INPROC_SERVER,
727 clsid_IShellLink,
reinterpret_cast<void**
>(&psl) );
729 hres =
SHCoCreateInstance(
nullptr, clsid_ShellLink,
nullptr, clsid_IShellLink,
reinterpret_cast<void**
>(&psl) );
731 if( SUCCEEDED(hres) )
734 psl->SetPath( o3tl::toW(rAbsObject.getStr()) );
735 psl->SetWorkingDirectory( o3tl::toW(rAbsObjectPath.getStr()) );
736 psl->SetDescription( o3tl::toW(rDescription.getStr()) );
737 if( rParameter.getLength() )
738 psl->SetArguments( o3tl::toW(rParameter.getStr()) );
740 CLSID clsid_IPersistFile = IID_IPersistFile;
741 hres = psl->QueryInterface( clsid_IPersistFile,
reinterpret_cast<void**
>(&ppf) );
743 if( SUCCEEDED(hres) )
745 hres = ppf->Save( o3tl::toW(rAbsShortcut.getStr()),
TRUE );
758 bool bExists =
false;
759 WIN32_FIND_DATAW aFindData;
761 HANDLE hFind = FindFirstFileW( lpPath, &aFindData );
763 if ( INVALID_HANDLE_VALUE != hFind )
775 GetModuleFileNameW(
nullptr, aPath, _MAX_PATH-1);
777 OUString aOfficepath( o3tl::toU(aPath) );
778 int i = aOfficepath.lastIndexOf(
'\\');
780 aOfficepath = aOfficepath.copy(0, i);
782 OUString quickstartExe(aOfficepath +
"\\quickstart.exe");
784 return FileExistsW( o3tl::toW(quickstartExe.getStr()) );
787void ShutdownIcon::EnableAutostartW32(
const OUString &aShortcut )
790 GetModuleFileNameW(
nullptr, aPath, _MAX_PATH-1);
792 OUString aOfficepath( o3tl::toU(aPath) );
793 int i = aOfficepath.lastIndexOf(
'\\');
795 aOfficepath = aOfficepath.copy(0, i);
797 OUString quickstartExe(aOfficepath +
"\\quickstart.exe");
799 CreateShortcut( quickstartExe, aOfficepath, aShortcut, OUString(), OUString() );
static bool IsQuickstarterInstalled()
static ShutdownIcon * getInstance()
static void terminateDesktop()
static void FromTemplate()
static void addTerminateListener()
static OUString GetUrlDescription(std::u16string_view aUrl)
static bool GetAutostart()
static void SetAutostart(bool bActivate)
static void OpenURL(const OUString &aURL, const OUString &rTarget, const css::uno::Sequence< css::beans::PropertyValue > &=css::uno::Sequence< css::beans::PropertyValue >(0))
bool IsModuleInstalled(EModule eModule) const
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
constexpr tools::Long SIZE
OUString SfxResId(TranslateId aId)
constexpr OUStringLiteral DRAW_URL
constexpr OUStringLiteral MATH_URL
constexpr OUStringLiteral STARTMODULE_URL
constexpr OUStringLiteral CALC_URL
constexpr OUStringLiteral BASE_URL
constexpr OUStringLiteral WRITER_URL
constexpr OUStringLiteral IMPRESS_WIZARD_URL
#define ICON_DRAWING_DOCUMENT
static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
static void SHFree_(void *pv)
static DWORD WINAPI SystrayThread(LPVOID)
static LRESULT CALLBACK listenerWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
static OUString SHGetSpecialFolder(int nFolderID)
static HRESULT WINAPI SHCoCreateInstance(LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv)
void win32_init_sys_tray()
static bool CreateShortcut(const OUString &rAbsObject, const OUString &rAbsObjectPath, const OUString &rAbsShortcut, const OUString &rDescription, const OUString &rParameter)
#define EXECUTER_WINDOWNAME
static LRESULT CALLBACK executerWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis)
static void addTaskbarIcon(HWND hWnd)
#define ICON_MATH_DOCUMENT
static void addMenuItem(HMENU hMenu, UINT id, UINT iconId, const OUString &text, int &pos, bool bOwnerdraw, const OUString &module)
static HMENU createSystrayMenu()
#define SFX_TASKBAR_NOTIFICATION
#define ICON_TEXT_DOCUMENT
static void deleteSystrayMenu(HMENU hMenu)
#define EXECUTER_WINDOWCLASS
static HWND aExecuterWindow
static bool FileExistsW(LPCWSTR lpPath)
#define ICON_SPREADSHEET_DOCUMENT
static HWND aListenerWindow
#define ICON_PRESENTATION_DOCUMENT
void win32_shutdown_sys_tray()
#define ICON_DATABASE_DOCUMENT