tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / sfx2 / source / appl / shutdowniconw32.cxx
blob5d4c89307baf7a9d6a30f9c52a464a0555eacbdc
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include <sal/macros.h>
20 #include <sal/log.hxx>
22 #include <unotools/moduleoptions.hxx>
23 #include <unotools/dynamicmenuoptions.hxx>
25 #undef WB_LEFT
26 #undef WB_RIGHT
28 #include "shutdownicon.hxx"
29 #include <sfx2/sfxresid.hxx>
30 #include <sfx2/strings.hrc>
31 #include <shlobj.h>
32 #include <objidl.h>
33 #include <osl/diagnose.h>
34 #include <osl/thread.h>
35 #include <systools/win32/qswin32.h>
36 #include <comphelper/sequenceashashmap.hxx>
37 #include <comphelper/windowserrorstring.hxx>
38 #include <o3tl/char16_t2wchar_t.hxx>
40 #include <set>
43 #define EXECUTER_WINDOWCLASS L"SO Executer Class"
44 #define EXECUTER_WINDOWNAME L"SO Executer Window"
47 #define ID_QUICKSTART 1
48 #define IDM_EXIT 2
49 #define IDM_OPEN 3
50 #define IDM_WRITER 4
51 #define IDM_CALC 5
52 #define IDM_IMPRESS 6
53 #define IDM_DRAW 7
54 #define IDM_BASE 8
55 #define IDM_TEMPLATE 9
56 #define IDM_MATH 12
57 #define IDM_INSTALL 10
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
69 #define ICON_OPEN 5 // See index of open folder icon in shell32.dll
71 #define SFX_TASKBAR_NOTIFICATION WM_USER+1
73 static HWND aListenerWindow = nullptr;
74 static HWND aExecuterWindow = nullptr;
75 static HMENU popupMenu = nullptr;
77 static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis);
78 static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis);
80 namespace {
82 struct MYITEM
84 OUString text;
85 OUString module;
86 UINT iconId;
91 static 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 ) )
98 mi.fMask=MIIM_FTYPE;
99 mi.fType=MFT_SEPARATOR;
101 else
103 if( bOwnerdraw )
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;
111 pMyItem->module = module;
112 mi.dwItemData = reinterpret_cast<ULONG_PTR>(pMyItem);
114 else
116 mi.fMask=MIIM_STRING | MIIM_STATE | MIIM_ID;
117 mi.dwTypeData = o3tl::toW(
118 const_cast<sal_Unicode *>(text.getStr()));
119 mi.cch = text.getLength();
122 mi.fState = MFS_ENABLED;
123 mi.wID = id;
124 if ( IDM_TEMPLATE == id )
125 mi.fState |= MFS_DEFAULT;
128 InsertMenuItemW( hMenu, pos++, TRUE, &mi );
132 static HMENU createSystrayMenu( )
134 SvtModuleOptions aModuleOptions;
136 HMENU hMenu = CreatePopupMenu();
137 int pos=0;
139 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
140 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!");
142 if( !pShutdownIcon )
143 return nullptr;
145 // collect the URLs of the entries in the File/New menu
146 ::std::set< OUString > aFileNewAppsAvailable;
147 std::vector< SvtDynMenuEntry > const aNewMenu = SvtDynamicMenuOptions::GetMenu( EDynamicMenuType::NewMenu );
148 for ( SvtDynMenuEntry const & newMenuProp : aNewMenu )
150 if ( !newMenuProp.sURL.isEmpty() )
151 aFileNewAppsAvailable.insert( newMenuProp.sURL );
154 // describe the menu entries for launching the applications
155 struct MenuEntryDescriptor
157 SvtModuleOptions::EModule eModuleIdentifier;
158 UINT nMenuItemID;
159 UINT nMenuIconID;
160 OUString sURLDescription;
161 } static constexpr aMenuItems[] =
163 { SvtModuleOptions::EModule::WRITER, IDM_WRITER, ICON_TEXT_DOCUMENT, WRITER_URL },
164 { SvtModuleOptions::EModule::CALC, IDM_CALC, ICON_SPREADSHEET_DOCUMENT, CALC_URL },
165 { SvtModuleOptions::EModule::IMPRESS, IDM_IMPRESS,ICON_PRESENTATION_DOCUMENT, IMPRESS_WIZARD_URL },
166 { SvtModuleOptions::EModule::DRAW, IDM_DRAW, ICON_DRAWING_DOCUMENT, DRAW_URL },
167 { SvtModuleOptions::EModule::DATABASE, IDM_BASE, ICON_DATABASE_DOCUMENT, BASE_URL },
168 { SvtModuleOptions::EModule::MATH, IDM_MATH, ICON_MATH_DOCUMENT, MATH_URL },
171 // insert the menu entries for launching the applications
172 for (const auto& [eModuleIdentifier, nMenuItemID, nMenuIconID, sURL] : aMenuItems)
174 if ( !aModuleOptions.IsModuleInstalled( eModuleIdentifier ) )
175 // the complete application is not even installed
176 continue;
178 if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() )
179 // the application is installed, but the entry has been configured to *not* appear in the File/New
180 // menu => also let not appear it in the quickstarter
181 continue;
183 addMenuItem( hMenu, nMenuItemID, nMenuIconID,
184 ShutdownIcon::GetUrlDescription( sURL ), pos, true, "" );
188 // insert the remaining menu entries
189 addMenuItem( hMenu, IDM_TEMPLATE, ICON_TEMPLATE,
190 SfxResId( STR_QUICKSTART_FROMTEMPLATE ), pos, true, "");
191 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, "" );
192 addMenuItem( hMenu, IDM_OPEN, ICON_OPEN, SfxResId(STR_QUICKSTART_FILEOPEN), pos, true, "SHELL32");
193 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, "" );
194 addMenuItem( hMenu, IDM_INSTALL,0, SfxResId(STR_QUICKSTART_PRELAUNCH), pos, false, "" );
195 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, "" );
196 addMenuItem( hMenu, IDM_EXIT, 0, SfxResId(STR_QUICKSTART_EXIT), pos, false, "" );
198 // indicate status of autostart folder
199 CheckMenuItem( hMenu, IDM_INSTALL, MF_BYCOMMAND | (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
201 return hMenu;
205 static void deleteSystrayMenu( HMENU hMenu )
207 if( !hMenu || !IsMenu( hMenu ))
208 return;
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))
217 delete pMyItem;
218 mi.fMask = MIIM_DATA;
223 static void addTaskbarIcon( HWND hWnd )
225 OUString strTip = SfxResId(STR_QUICKSTART_TIP);
227 // add taskbar icon
228 NOTIFYICONDATAW nid;
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);
236 nid.hWnd = hWnd;
237 nid.uID = ID_QUICKSTART;
238 nid.uCallbackMessage = SFX_TASKBAR_NOTIFICATION;
239 nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON;
241 Shell_NotifyIconW(NIM_ADD, &nid);
245 static LRESULT CALLBACK listenerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
247 static UINT s_uTaskbarRestart = 0;
248 static UINT s_uMsgKillTray = 0;
250 switch (uMsg)
252 case WM_NCCREATE:
253 return TRUE;
254 case WM_CREATE:
256 // request notification when taskbar is recreated
257 // we then have to add our icon again
258 s_uTaskbarRestart = RegisterWindowMessageW(L"TaskbarCreated");
259 s_uMsgKillTray = RegisterWindowMessageW( SHUTDOWN_QUICKSTART_MESSAGE );
261 // create the menu
262 if( !popupMenu )
263 if( (popupMenu = createSystrayMenu( )) == nullptr )
264 return -1;
266 // and the icon
267 addTaskbarIcon( hWnd );
269 // disable shutdown
270 ShutdownIcon::getInstance()->SetVeto( true );
271 ShutdownIcon::addTerminateListener();
273 return 0;
275 case WM_MEASUREITEM:
276 OnMeasureItem(hWnd, reinterpret_cast<LPMEASUREITEMSTRUCT>(lParam));
277 return TRUE;
279 case WM_DRAWITEM:
280 OnDrawItem(hWnd, reinterpret_cast<LPDRAWITEMSTRUCT>(lParam));
281 return TRUE;
283 case SFX_TASKBAR_NOTIFICATION:
284 switch( lParam )
286 case WM_LBUTTONDOWN:
288 bool const ret = PostMessageW(aExecuterWindow, WM_COMMAND, IDM_STARTCENTER, reinterpret_cast<LPARAM>(hWnd));
289 SAL_WARN_IF(!ret, "sfx.appl", "ERROR: PostMessage() failed!");
290 break;
293 case WM_RBUTTONDOWN:
295 POINT pt;
296 GetCursorPos(&pt);
297 SetForegroundWindow( hWnd );
299 // update status before showing menu, could have been changed from option page
300 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
302 EnableMenuItem( popupMenu, IDM_EXIT, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
303 EnableMenuItem( popupMenu, IDM_OPEN, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
304 EnableMenuItem( popupMenu, IDM_TEMPLATE, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
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!");
309 switch( m )
311 case IDM_OPEN:
312 case IDM_WRITER:
313 case IDM_CALC:
314 case IDM_IMPRESS:
315 case IDM_DRAW:
316 case IDM_TEMPLATE:
317 case IDM_BASE:
318 case IDM_MATH:
319 break;
320 case IDM_INSTALL:
321 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
322 break;
323 case IDM_EXIT:
324 // delete taskbar icon
325 NOTIFYICONDATAW nid;
326 nid.cbSize=sizeof(nid);
327 nid.hWnd = hWnd;
328 nid.uID = ID_QUICKSTART;
329 Shell_NotifyIconW(NIM_DELETE, &nid);
330 break;
333 bool const ret2 = PostMessageW(aExecuterWindow, WM_COMMAND, m, reinterpret_cast<LPARAM>(hWnd));
334 SAL_WARN_IF(!ret2, "sfx.appl", "ERROR: PostMessage() failed!");
336 break;
338 break;
339 case WM_DESTROY:
340 deleteSystrayMenu( popupMenu );
341 // We don't need the Systray Thread anymore
342 PostQuitMessage( 0 );
343 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
344 default:
345 if( uMsg == s_uTaskbarRestart )
347 // re-create taskbar icon
348 addTaskbarIcon( hWnd );
350 else if ( uMsg == s_uMsgKillTray )
352 // delete taskbar icon
353 NOTIFYICONDATAW nid;
354 nid.cbSize=sizeof(nid);
355 nid.hWnd = hWnd;
356 nid.uID = ID_QUICKSTART;
357 Shell_NotifyIconW(NIM_DELETE, &nid);
359 bool const ret = PostMessageW(aExecuterWindow, WM_COMMAND, IDM_EXIT, reinterpret_cast<LPARAM>(hWnd));
360 SAL_WARN_IF(!ret, "sfx.appl", "ERROR: PostMessage() failed!");
362 else
363 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
365 return 0;
369 static LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
371 switch (uMsg)
373 case WM_NCCREATE:
374 return TRUE;
375 case WM_CREATE:
376 return 0;
378 case WM_COMMAND:
379 switch( LOWORD(wParam) )
381 case IDM_OPEN:
382 if ( !ShutdownIcon::bModalMode )
383 ShutdownIcon::FileOpen();
384 break;
385 case IDM_WRITER:
386 ShutdownIcon::OpenURL( WRITER_URL, "_default" );
387 break;
388 case IDM_CALC:
389 ShutdownIcon::OpenURL( CALC_URL, "_default" );
390 break;
391 case IDM_IMPRESS:
392 ShutdownIcon::OpenURL( IMPRESS_WIZARD_URL, "_default" );
393 break;
394 case IDM_DRAW:
395 ShutdownIcon::OpenURL( DRAW_URL, "_default" );
396 break;
397 case IDM_BASE:
398 ShutdownIcon::OpenURL( BASE_URL, "_default" );
399 break;
400 case IDM_MATH:
401 ShutdownIcon::OpenURL( MATH_URL, "_default" );
402 break;
403 case IDM_STARTCENTER:
404 ShutdownIcon::OpenURL( STARTMODULE_URL, "_default" );
405 break;
406 case IDM_TEMPLATE:
407 if ( !ShutdownIcon::bModalMode )
408 ShutdownIcon::FromTemplate();
409 break;
410 case IDM_INSTALL:
411 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() );
412 break;
413 case IDM_EXIT:
414 // remove listener and
415 // terminate office if running in background
416 if ( !ShutdownIcon::bModalMode )
417 ShutdownIcon::terminateDesktop();
418 break;
420 break;
421 case WM_DESTROY:
422 default:
423 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
425 return 0;
429 static unsigned __stdcall SystrayThread(void* /*lpParam*/)
431 osl_setThreadName("SystrayThread");
433 aListenerWindow = CreateWindowExW(0,
434 QUICKSTART_CLASSNAME, // registered class name
435 QUICKSTART_WINDOWNAME, // window name
436 0, // window style
437 CW_USEDEFAULT, // horizontal position of window
438 CW_USEDEFAULT, // vertical position of window
439 CW_USEDEFAULT, // window width
440 CW_USEDEFAULT, // window height
441 nullptr, // handle to parent or owner window
442 nullptr, // menu handle or child identifier
443 GetModuleHandleW( nullptr ), // handle to application instance
444 nullptr // window-creation data
447 MSG msg;
449 for (;;)
451 int const bRet = GetMessageW(&msg, nullptr, 0, 0);
452 if (bRet == 0)
454 break;
456 if (-1 == bRet)
458 SAL_WARN("sfx.appl", "GetMessageW failed: " << WindowsErrorString(GetLastError()));
459 return 1;
461 TranslateMessage( &msg );
462 DispatchMessageW( &msg );
465 return msg.wParam; // Exit code of WM_QUIT
469 void win32_init_sys_tray()
471 if ( ShutdownIcon::IsQuickstarterInstalled() )
473 WNDCLASSEXW listenerClass;
474 listenerClass.cbSize = sizeof(listenerClass);
475 listenerClass.style = 0;
476 listenerClass.lpfnWndProc = listenerWndProc;
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;
492 executerClass.lpfnWndProc = executerWndProc;
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;
500 executerClass.lpszClassName = EXECUTER_WINDOWCLASS;
501 executerClass.hIconSm = nullptr;
503 RegisterClassExW( &executerClass );
505 aExecuterWindow = CreateWindowExW(0,
506 EXECUTER_WINDOWCLASS, // registered class name
507 EXECUTER_WINDOWNAME, // window name
508 0, // window style
509 CW_USEDEFAULT, // horizontal position of window
510 CW_USEDEFAULT, // vertical position of window
511 CW_USEDEFAULT, // window width
512 CW_USEDEFAULT, // window height
513 nullptr, // handle to parent or owner window
514 nullptr, // menu handle or child identifier
515 GetModuleHandleW( nullptr ), // handle to application instance
516 nullptr // window-creation data
519 CloseHandle(reinterpret_cast<HANDLE>(
520 _beginthreadex(nullptr, 0, SystrayThread, nullptr, 0, nullptr)));
525 void win32_shutdown_sys_tray()
527 if ( ShutdownIcon::IsQuickstarterInstalled() )
529 if( IsWindow( aListenerWindow ) )
531 DestroyWindow( aListenerWindow );
532 aListenerWindow = nullptr;
533 DestroyWindow( aExecuterWindow );
534 aExecuterWindow = nullptr;
536 UnregisterClassW( QUICKSTART_CLASSNAME, GetModuleHandleW( nullptr ) );
537 UnregisterClassW( EXECUTER_WINDOWCLASS, GetModuleHandleW( nullptr ) );
542 void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
544 MYITEM *pMyItem = reinterpret_cast<MYITEM *>(lpmis->itemData);
545 HDC hdc = GetDC(hwnd);
546 SIZE size;
548 NONCLIENTMETRICSW ncm = {};
549 ncm.cbSize = sizeof(ncm);
551 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
553 // Assume every menu item can be default and printed bold
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);
569 void OnDrawItem(HWND /*hwnd*/, LPDRAWITEMSTRUCT lpdis)
571 MYITEM *pMyItem = reinterpret_cast<MYITEM *>(lpdis->itemData);
572 COLORREF clrPrevText, clrPrevBkgnd;
573 HFONT hfntOld;
574 HBRUSH hbrOld;
575 int x, y;
576 bool fSelected = lpdis->itemState & ODS_SELECTED;
577 bool fDisabled = lpdis->itemState & (ODS_DISABLED | ODS_GRAYED);
579 // Set the appropriate foreground and background colors.
581 RECT aRect = lpdis->rcItem;
583 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
585 if ( fDisabled )
586 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) );
587 else
588 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
590 if ( fSelected )
591 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) );
592 else
593 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
595 hbrOld = static_cast<HBRUSH>(SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) ));
597 // Fill background
598 PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY);
600 int height = aRect.bottom-aRect.top;
602 x = aRect.left;
603 y = 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 ),
621 IMAGE_ICON, cx, cy,
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 );
631 x += cx + 4; // space for icon
632 aRect.left = x;
634 NONCLIENTMETRICSW ncm = {};
635 ncm.cbSize = sizeof(ncm);
637 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
639 // Print default menu entry with bold font
640 if ( lpdis->itemState & ODS_DEFAULT )
641 ncm.lfMenuFont.lfWeight = FW_BOLD;
643 hfntOld = static_cast<HFONT>(SelectObject(lpdis->hDC, CreateFontIndirectW( &ncm.lfMenuFont )));
646 SIZE size;
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) );
651 // Restore the original font and colors.
652 DeleteObject( SelectObject( lpdis->hDC, hbrOld ) );
653 DeleteObject( SelectObject( lpdis->hDC, hfntOld) );
654 SetTextColor(lpdis->hDC, clrPrevText);
655 SetBkColor(lpdis->hDC, clrPrevBkgnd);
659 // code from setup2 project
661 static OUString SHGetSpecialFolder( int nFolderID )
664 LPITEMIDLIST pidl;
665 HRESULT hHdl = SHGetSpecialFolderLocation( nullptr, nFolderID, &pidl );
666 OUString aFolder;
668 if( hHdl == NOERROR )
670 auto xFolder = std::make_unique<WCHAR[]>(16000);
671 SHGetPathFromIDListW(pidl, xFolder.get());
672 aFolder = o3tl::toU(xFolder.get());
675 return aFolder;
678 OUString ShutdownIcon::GetAutostartFolderNameW32()
680 return SHGetSpecialFolder(CSIDL_STARTUP);
683 static HRESULT WINAPI SHCoCreateInstance( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv )
685 HRESULT hResult = E_NOTIMPL;
686 HMODULE hModShell = GetModuleHandleW( L"SHELL32" );
688 if ( hModShell != nullptr )
690 typedef HRESULT (WINAPI *SHCoCreateInstance_PROC)( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv );
692 SHCoCreateInstance_PROC lpfnSHCoCreateInstance = reinterpret_cast<SHCoCreateInstance_PROC>(GetProcAddress( hModShell, MAKEINTRESOURCEA(102) ));
694 if ( lpfnSHCoCreateInstance )
695 hResult = lpfnSHCoCreateInstance( lpszReserved, clsid, pUnkUnknown, iid, ppv );
697 return hResult;
700 static bool CreateShortcut( const OUString& rAbsObject, const OUString& rAbsObjectPath,
701 const OUString& rAbsShortcut, const OUString& rDescription, const OUString& rParameter )
703 HRESULT hres;
704 IShellLinkW* psl;
705 CLSID clsid_ShellLink = CLSID_ShellLink;
706 CLSID clsid_IShellLink = IID_IShellLinkW;
708 hres = CoCreateInstance( clsid_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
709 clsid_IShellLink, reinterpret_cast<void**>(&psl) );
710 if( FAILED(hres) )
711 hres = SHCoCreateInstance( nullptr, clsid_ShellLink, nullptr, clsid_IShellLink, reinterpret_cast<void**>(&psl) );
713 if( SUCCEEDED(hres) )
715 IPersistFile* ppf;
716 psl->SetPath( o3tl::toW(rAbsObject.getStr()) );
717 psl->SetWorkingDirectory( o3tl::toW(rAbsObjectPath.getStr()) );
718 psl->SetDescription( o3tl::toW(rDescription.getStr()) );
719 if( rParameter.getLength() )
720 psl->SetArguments( o3tl::toW(rParameter.getStr()) );
722 CLSID clsid_IPersistFile = IID_IPersistFile;
723 hres = psl->QueryInterface( clsid_IPersistFile, reinterpret_cast<void**>(&ppf) );
725 if( SUCCEEDED(hres) )
727 hres = ppf->Save( o3tl::toW(rAbsShortcut.getStr()), TRUE );
728 ppf->Release();
729 } else return false;
730 psl->Release();
731 } else return false;
732 return true;
736 // install/uninstall
738 static bool FileExistsW( LPCWSTR lpPath )
740 bool bExists = false;
741 WIN32_FIND_DATAW aFindData;
743 HANDLE hFind = FindFirstFileW( lpPath, &aFindData );
745 if ( INVALID_HANDLE_VALUE != hFind )
747 bExists = true;
748 FindClose( hFind );
751 return bExists;
754 bool ShutdownIcon::IsQuickstarterInstalled()
756 wchar_t aPath[_MAX_PATH];
757 GetModuleFileNameW( nullptr, aPath, _MAX_PATH-1);
759 OUString aOfficepath( o3tl::toU(aPath) );
760 int i = aOfficepath.lastIndexOf('\\');
761 if( i != -1 )
762 aOfficepath = aOfficepath.copy(0, i);
764 OUString quickstartExe(aOfficepath + "\\quickstart.exe");
766 return FileExistsW( o3tl::toW(quickstartExe.getStr()) );
769 void ShutdownIcon::EnableAutostartW32( const OUString &aShortcut )
771 wchar_t aPath[_MAX_PATH];
772 GetModuleFileNameW( nullptr, aPath, _MAX_PATH-1);
774 OUString aOfficepath( o3tl::toU(aPath) );
775 int i = aOfficepath.lastIndexOf('\\');
776 if( i != -1 )
777 aOfficepath = aOfficepath.copy(0, i);
779 OUString quickstartExe(aOfficepath + "\\quickstart.exe");
781 CreateShortcut( quickstartExe, aOfficepath, aShortcut, OUString(), OUString() );
785 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */