Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / appl / shutdowniconw32.cxx
blob05b855f4cad4ea1c902a764b16f81f36d45be468
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/thread.h>
34 #include <systools/win32/qswin32.h>
35 #include <comphelper/sequenceashashmap.hxx>
36 #include <o3tl/char16_t2wchar_t.hxx>
38 #include <set>
40 using namespace ::osl;
42 using ::com::sun::star::uno::Sequence;
43 using ::com::sun::star::beans::PropertyValue;
46 #define EXECUTER_WINDOWCLASS L"SO Executer Class"
47 #define EXECUTER_WINDOWNAME L"SO Executer Window"
50 #define ID_QUICKSTART 1
51 #define IDM_EXIT 2
52 #define IDM_OPEN 3
53 #define IDM_WRITER 4
54 #define IDM_CALC 5
55 #define IDM_IMPRESS 6
56 #define IDM_DRAW 7
57 #define IDM_BASE 8
58 #define IDM_TEMPLATE 9
59 #define IDM_MATH 12
60 #define IDM_INSTALL 10
61 #define IDM_STARTCENTER 14
64 #define ICON_LO_DEFAULT 1
65 #define ICON_TEXT_DOCUMENT 2
66 #define ICON_SPREADSHEET_DOCUMENT 4
67 #define ICON_DRAWING_DOCUMENT 6
68 #define ICON_PRESENTATION_DOCUMENT 8
69 #define ICON_TEMPLATE 11
70 #define ICON_DATABASE_DOCUMENT 12
71 #define ICON_MATH_DOCUMENT 13
72 #define ICON_OPEN 5 // See index of open folder icon in shell32.dll
74 #define SFX_TASKBAR_NOTIFICATION WM_USER+1
76 static HWND aListenerWindow = nullptr;
77 static HWND aExecuterWindow = nullptr;
78 static HMENU popupMenu = nullptr;
80 static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis);
81 static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis);
83 namespace {
85 typedef struct tagMYITEM
87 OUString text;
88 OUString module;
89 UINT iconId;
90 } MYITEM;
94 static void addMenuItem( HMENU hMenu, UINT id, UINT iconId, const OUString& text, int& pos, bool bOwnerdraw, const OUString& module )
96 MENUITEMINFOW mi = {};
98 mi.cbSize = sizeof( mi );
99 if( id == static_cast<UINT>( -1 ) )
101 mi.fMask=MIIM_TYPE;
102 mi.fType=MFT_SEPARATOR;
104 else
106 if( bOwnerdraw )
108 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
109 mi.fType=MFT_OWNERDRAW;
110 mi.fState=MFS_ENABLED;
111 mi.wID = id;
113 MYITEM *pMyItem = new MYITEM;
114 pMyItem->text = text;
115 pMyItem->iconId = iconId;
116 pMyItem->module = module;
117 mi.dwItemData = reinterpret_cast<DWORD_PTR>(pMyItem);
119 else
121 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
122 mi.fType=MFT_STRING;
123 mi.fState=MFS_ENABLED;
124 mi.wID = id;
125 mi.dwTypeData = o3tl::toW(
126 const_cast<sal_Unicode *>(text.getStr()));
127 mi.cch = text.getLength();
130 if ( IDM_TEMPLATE == id )
131 mi.fState |= MFS_DEFAULT;
134 InsertMenuItemW( hMenu, pos++, TRUE, &mi );
138 static HMENU createSystrayMenu( )
140 SvtModuleOptions aModuleOptions;
142 HMENU hMenu = CreatePopupMenu();
143 int pos=0;
145 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
146 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!");
148 if( !pShutdownIcon )
149 return nullptr;
151 // collect the URLs of the entries in the File/New menu
152 ::std::set< OUString > aFileNewAppsAvailable;
153 SvtDynamicMenuOptions aOpt;
154 Sequence < Sequence < PropertyValue > > const aNewMenu = aOpt.GetMenu( EDynamicMenuType::NewMenu );
155 const OUString sURLKey( "URL" );
157 for ( auto const & newMenuProp : aNewMenu )
159 ::comphelper::SequenceAsHashMap aEntryItems( newMenuProp );
160 OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, OUString() ) );
161 if ( sURL.getLength() )
162 aFileNewAppsAvailable.insert( sURL );
165 // describe the menu entries for launching the applications
166 struct MenuEntryDescriptor
168 SvtModuleOptions::EModule eModuleIdentifier;
169 UINT nMenuItemID;
170 UINT nMenuIconID;
171 const char* pAsciiURLDescription;
172 } aMenuItems[] =
174 { SvtModuleOptions::EModule::WRITER, IDM_WRITER, ICON_TEXT_DOCUMENT, WRITER_URL },
175 { SvtModuleOptions::EModule::CALC, IDM_CALC, ICON_SPREADSHEET_DOCUMENT, CALC_URL },
176 { SvtModuleOptions::EModule::IMPRESS, IDM_IMPRESS,ICON_PRESENTATION_DOCUMENT, IMPRESS_WIZARD_URL },
177 { SvtModuleOptions::EModule::DRAW, IDM_DRAW, ICON_DRAWING_DOCUMENT, DRAW_URL },
178 { SvtModuleOptions::EModule::DATABASE, IDM_BASE, ICON_DATABASE_DOCUMENT, BASE_URL },
179 { SvtModuleOptions::EModule::MATH, IDM_MATH, ICON_MATH_DOCUMENT, MATH_URL },
182 // insert the menu entries for launching the applications
183 for ( size_t i = 0; i < SAL_N_ELEMENTS(aMenuItems); ++i )
185 if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) )
186 // the complete application is not even installed
187 continue;
189 OUString sURL( OUString::createFromAscii( aMenuItems[i].pAsciiURLDescription ) );
191 if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() )
192 // the application is installed, but the entry has been configured to *not* appear in the File/New
193 // menu => also let not appear it in the quickstarter
194 continue;
196 addMenuItem( hMenu, aMenuItems[i].nMenuItemID, aMenuItems[i].nMenuIconID,
197 ShutdownIcon::GetUrlDescription( sURL ), pos, true, "" );
201 // insert the remaining menu entries
202 addMenuItem( hMenu, IDM_TEMPLATE, ICON_TEMPLATE,
203 SfxResId( STR_QUICKSTART_FROMTEMPLATE ), pos, true, "");
204 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, "" );
205 addMenuItem( hMenu, IDM_OPEN, ICON_OPEN, SfxResId(STR_QUICKSTART_FILEOPEN), pos, true, "SHELL32");
206 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, "" );
207 addMenuItem( hMenu, IDM_INSTALL,0, SfxResId(STR_QUICKSTART_PRELAUNCH), pos, false, "" );
208 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, "" );
209 addMenuItem( hMenu, IDM_EXIT, 0, SfxResId(STR_QUICKSTART_EXIT), pos, false, "" );
211 // indicate status of autostart folder
212 CheckMenuItem( hMenu, IDM_INSTALL, MF_BYCOMMAND | (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
214 return hMenu;
218 static void deleteSystrayMenu( HMENU hMenu )
220 if( !hMenu || !IsMenu( hMenu ))
221 return;
223 MENUITEMINFOW mi = {};
224 int pos=0;
225 mi.cbSize = sizeof( mi );
226 mi.fMask = MIIM_DATA;
228 while( GetMenuItemInfoW( hMenu, pos++, true, &mi ) )
230 MYITEM *pMyItem = reinterpret_cast<MYITEM*>(mi.dwItemData);
231 if( pMyItem )
233 pMyItem->text.clear();
234 delete pMyItem;
236 mi.fMask = MIIM_DATA;
241 static void addTaskbarIcon( HWND hWnd )
243 OUString strTip = SfxResId(STR_QUICKSTART_TIP);
245 // add taskbar icon
246 NOTIFYICONDATAW nid;
247 nid.hIcon = static_cast<HICON>(LoadImageW( GetModuleHandleW( nullptr ), MAKEINTRESOURCEW( ICON_LO_DEFAULT ),
248 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ),
249 LR_DEFAULTCOLOR | LR_SHARED ));
251 wcsncpy( nid.szTip, o3tl::toW(strTip.getStr()), 64 );
253 nid.cbSize = sizeof(nid);
254 nid.hWnd = hWnd;
255 nid.uID = ID_QUICKSTART;
256 nid.uCallbackMessage = SFX_TASKBAR_NOTIFICATION;
257 nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON;
259 Shell_NotifyIconW(NIM_ADD, &nid);
263 static LRESULT CALLBACK listenerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
265 static UINT s_uTaskbarRestart = 0;
266 static UINT s_uMsgKillTray = 0;
268 switch (uMsg)
270 case WM_NCCREATE:
271 return TRUE;
272 case WM_CREATE:
274 // request notification when taskbar is recreated
275 // we then have to add our icon again
276 s_uTaskbarRestart = RegisterWindowMessageW(L"TaskbarCreated");
277 s_uMsgKillTray = RegisterWindowMessageW( SHUTDOWN_QUICKSTART_MESSAGE );
279 // create the menu
280 if( !popupMenu )
281 if( (popupMenu = createSystrayMenu( )) == nullptr )
282 return -1;
284 // and the icon
285 addTaskbarIcon( hWnd );
287 // disable shutdown
288 ShutdownIcon::getInstance()->SetVeto( true );
289 ShutdownIcon::addTerminateListener();
291 return 0;
293 case WM_MEASUREITEM:
294 OnMeasureItem(hWnd, reinterpret_cast<LPMEASUREITEMSTRUCT>(lParam));
295 return TRUE;
297 case WM_DRAWITEM:
298 OnDrawItem(hWnd, reinterpret_cast<LPDRAWITEMSTRUCT>(lParam));
299 return TRUE;
301 case SFX_TASKBAR_NOTIFICATION:
302 switch( lParam )
304 case WM_LBUTTONDOWN:
306 bool const ret = PostMessageW(aExecuterWindow, WM_COMMAND, IDM_STARTCENTER, reinterpret_cast<LPARAM>(hWnd));
307 SAL_WARN_IF(!ret, "sfx.appl", "ERROR: PostMessage() failed!");
308 break;
311 case WM_RBUTTONDOWN:
313 POINT pt;
314 GetCursorPos(&pt);
315 SetForegroundWindow( hWnd );
317 // update status before showing menu, could have been changed from option page
318 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
320 EnableMenuItem( popupMenu, IDM_EXIT, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
321 EnableMenuItem( popupMenu, IDM_OPEN, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
322 EnableMenuItem( popupMenu, IDM_TEMPLATE, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
323 int m = TrackPopupMenuEx( popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON,
324 pt.x, pt.y, hWnd, nullptr );
325 bool const ret = PostMessageW( hWnd, 0, 0, 0 );
326 SAL_WARN_IF(!ret, "sfx.appl", "ERROR: PostMessage() failed!");
327 switch( m )
329 case IDM_OPEN:
330 case IDM_WRITER:
331 case IDM_CALC:
332 case IDM_IMPRESS:
333 case IDM_DRAW:
334 case IDM_TEMPLATE:
335 case IDM_BASE:
336 case IDM_MATH:
337 break;
338 case IDM_INSTALL:
339 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
340 break;
341 case IDM_EXIT:
342 // delete taskbar icon
343 NOTIFYICONDATAW nid;
344 nid.cbSize=sizeof(nid);
345 nid.hWnd = hWnd;
346 nid.uID = ID_QUICKSTART;
347 Shell_NotifyIconW(NIM_DELETE, &nid);
348 break;
351 bool const ret2 = PostMessageW(aExecuterWindow, WM_COMMAND, m, reinterpret_cast<LPARAM>(hWnd));
352 SAL_WARN_IF(!ret2, "sfx.appl", "ERROR: PostMessage() failed!");
354 break;
356 break;
357 case WM_DESTROY:
358 deleteSystrayMenu( popupMenu );
359 // We don't need the Systray Thread anymore
360 PostQuitMessage( 0 );
361 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
362 default:
363 if( uMsg == s_uTaskbarRestart )
365 // re-create taskbar icon
366 addTaskbarIcon( hWnd );
368 else if ( uMsg == s_uMsgKillTray )
370 // delete taskbar icon
371 NOTIFYICONDATAW nid;
372 nid.cbSize=sizeof(nid);
373 nid.hWnd = hWnd;
374 nid.uID = ID_QUICKSTART;
375 Shell_NotifyIconW(NIM_DELETE, &nid);
377 bool const ret = PostMessageW(aExecuterWindow, WM_COMMAND, IDM_EXIT, reinterpret_cast<LPARAM>(hWnd));
378 SAL_WARN_IF(!ret, "sfx.appl", "ERROR: PostMessage() failed!");
380 else
381 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
383 return 0;
387 static LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
389 switch (uMsg)
391 case WM_NCCREATE:
392 return TRUE;
393 case WM_CREATE:
394 return 0;
396 case WM_COMMAND:
397 switch( LOWORD(wParam) )
399 case IDM_OPEN:
400 if ( !ShutdownIcon::bModalMode )
401 ShutdownIcon::FileOpen();
402 break;
403 case IDM_WRITER:
404 ShutdownIcon::OpenURL( WRITER_URL, "_default" );
405 break;
406 case IDM_CALC:
407 ShutdownIcon::OpenURL( CALC_URL, "_default" );
408 break;
409 case IDM_IMPRESS:
410 ShutdownIcon::OpenURL( IMPRESS_WIZARD_URL, "_default" );
411 break;
412 case IDM_DRAW:
413 ShutdownIcon::OpenURL( DRAW_URL, "_default" );
414 break;
415 case IDM_BASE:
416 ShutdownIcon::OpenURL( BASE_URL, "_default" );
417 break;
418 case IDM_MATH:
419 ShutdownIcon::OpenURL( MATH_URL, "_default" );
420 break;
421 case IDM_STARTCENTER:
422 ShutdownIcon::OpenURL( STARTMODULE_URL, "_default" );
423 break;
424 case IDM_TEMPLATE:
425 if ( !ShutdownIcon::bModalMode )
426 ShutdownIcon::FromTemplate();
427 break;
428 case IDM_INSTALL:
429 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() );
430 break;
431 case IDM_EXIT:
432 // remove listener and
433 // terminate office if running in background
434 if ( !ShutdownIcon::bModalMode )
435 ShutdownIcon::terminateDesktop();
436 break;
438 break;
439 case WM_DESTROY:
440 default:
441 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
443 return 0;
447 static DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ )
449 osl_setThreadName("SystrayThread");
451 aListenerWindow = CreateWindowExW(0,
452 QUICKSTART_CLASSNAME, // registered class name
453 QUICKSTART_WINDOWNAME, // window name
454 0, // window style
455 CW_USEDEFAULT, // horizontal position of window
456 CW_USEDEFAULT, // vertical position of window
457 CW_USEDEFAULT, // window width
458 CW_USEDEFAULT, // window height
459 nullptr, // handle to parent or owner window
460 nullptr, // menu handle or child identifier
461 GetModuleHandleW( nullptr ), // handle to application instance
462 nullptr // window-creation data
465 MSG msg;
467 while ( GetMessageW( &msg, nullptr, 0, 0 ) )
469 TranslateMessage( &msg );
470 DispatchMessageW( &msg );
473 return msg.wParam; // Exit code of WM_QUIT
477 void win32_init_sys_tray()
479 if ( ShutdownIcon::IsQuickstarterInstalled() )
481 WNDCLASSEXW listenerClass;
482 listenerClass.cbSize = sizeof(listenerClass);
483 listenerClass.style = 0;
484 listenerClass.lpfnWndProc = listenerWndProc;
485 listenerClass.cbClsExtra = 0;
486 listenerClass.cbWndExtra = 0;
487 listenerClass.hInstance = GetModuleHandleW( nullptr );
488 listenerClass.hIcon = nullptr;
489 listenerClass.hCursor = nullptr;
490 listenerClass.hbrBackground = nullptr;
491 listenerClass.lpszMenuName = nullptr;
492 listenerClass.lpszClassName = QUICKSTART_CLASSNAME;
493 listenerClass.hIconSm = nullptr;
495 RegisterClassExW(&listenerClass);
497 WNDCLASSEXW executerClass;
498 executerClass.cbSize = sizeof(executerClass);
499 executerClass.style = 0;
500 executerClass.lpfnWndProc = executerWndProc;
501 executerClass.cbClsExtra = 0;
502 executerClass.cbWndExtra = 0;
503 executerClass.hInstance = GetModuleHandleW( nullptr );
504 executerClass.hIcon = nullptr;
505 executerClass.hCursor = nullptr;
506 executerClass.hbrBackground = nullptr;
507 executerClass.lpszMenuName = nullptr;
508 executerClass.lpszClassName = EXECUTER_WINDOWCLASS;
509 executerClass.hIconSm = nullptr;
511 RegisterClassExW( &executerClass );
513 aExecuterWindow = CreateWindowExW(0,
514 EXECUTER_WINDOWCLASS, // registered class name
515 EXECUTER_WINDOWNAME, // window name
516 0, // window style
517 CW_USEDEFAULT, // horizontal position of window
518 CW_USEDEFAULT, // vertical position of window
519 CW_USEDEFAULT, // window width
520 CW_USEDEFAULT, // window height
521 nullptr, // handle to parent or owner window
522 nullptr, // menu handle or child identifier
523 GetModuleHandleW( nullptr ), // handle to application instance
524 nullptr // window-creation data
527 DWORD dwThreadId;
528 CloseHandle(CreateThread(nullptr, 0, SystrayThread, nullptr, 0, &dwThreadId));
533 void win32_shutdown_sys_tray()
535 if ( ShutdownIcon::IsQuickstarterInstalled() )
537 if( IsWindow( aListenerWindow ) )
539 DestroyWindow( aListenerWindow );
540 aListenerWindow = nullptr;
541 DestroyWindow( aExecuterWindow );
542 aExecuterWindow = nullptr;
544 UnregisterClassW( QUICKSTART_CLASSNAME, GetModuleHandleW( nullptr ) );
545 UnregisterClassW( EXECUTER_WINDOWCLASS, GetModuleHandleW( nullptr ) );
550 void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
552 MYITEM *pMyItem = reinterpret_cast<MYITEM *>(lpmis->itemData);
553 HDC hdc = GetDC(hwnd);
554 SIZE size;
556 NONCLIENTMETRICSW ncm = {};
557 ncm.cbSize = sizeof(ncm);
559 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
561 // Assume every menu item can be default and printed bold
562 ncm.lfMenuFont.lfWeight = FW_BOLD;
564 HFONT hfntOld = static_cast<HFONT>(SelectObject(hdc, CreateFontIndirectW( &ncm.lfMenuFont )));
566 GetTextExtentPoint32W(hdc, o3tl::toW(pMyItem->text.getStr()),
567 pMyItem->text.getLength(), &size);
569 lpmis->itemWidth = size.cx + 4 + GetSystemMetrics( SM_CXSMICON );
570 lpmis->itemHeight = std::max<int>(size.cy, GetSystemMetrics( SM_CYSMICON ));
571 lpmis->itemHeight += 4;
573 DeleteObject( SelectObject(hdc, hfntOld) );
574 ReleaseDC(hwnd, hdc);
577 void OnDrawItem(HWND /*hwnd*/, LPDRAWITEMSTRUCT lpdis)
579 MYITEM *pMyItem = reinterpret_cast<MYITEM *>(lpdis->itemData);
580 COLORREF clrPrevText, clrPrevBkgnd;
581 HFONT hfntOld;
582 HBRUSH hbrOld;
583 int x, y;
584 bool fSelected = lpdis->itemState & ODS_SELECTED;
585 bool fDisabled = lpdis->itemState & (ODS_DISABLED | ODS_GRAYED);
587 // Set the appropriate foreground and background colors.
589 RECT aRect = lpdis->rcItem;
591 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
593 if ( fDisabled )
594 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) );
595 else
596 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
598 if ( fSelected )
599 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) );
600 else
601 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
603 hbrOld = static_cast<HBRUSH>(SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) ));
605 // Fill background
606 PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY);
608 int height = aRect.bottom-aRect.top;
610 x = aRect.left;
611 y = aRect.top;
613 int cx = GetSystemMetrics( SM_CXSMICON );
614 int cy = GetSystemMetrics( SM_CYSMICON );
615 HICON hIcon( nullptr );
616 HMODULE hModule( GetModuleHandleW( nullptr ) );
618 if ( pMyItem->module.getLength() > 0 )
620 LPCWSTR pModuleName = o3tl::toW( pMyItem->module.getStr() );
621 hModule = GetModuleHandleW( pModuleName );
622 if ( hModule == nullptr )
624 hModule = LoadLibraryW(pModuleName);
628 hIcon = static_cast<HICON>(LoadImageW( hModule, MAKEINTRESOURCEW( pMyItem->iconId ),
629 IMAGE_ICON, cx, cy,
630 LR_DEFAULTCOLOR | LR_SHARED ));
633 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
635 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) );
637 DeleteObject( hbrIcon );
639 x += cx + 4; // space for icon
640 aRect.left = x;
642 NONCLIENTMETRICSW ncm = {};
643 ncm.cbSize = sizeof(ncm);
645 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
647 // Print default menu entry with bold font
648 if ( lpdis->itemState & ODS_DEFAULT )
649 ncm.lfMenuFont.lfWeight = FW_BOLD;
651 hfntOld = static_cast<HFONT>(SelectObject(lpdis->hDC, CreateFontIndirectW( &ncm.lfMenuFont )));
654 SIZE size;
655 GetTextExtentPointW( lpdis->hDC, o3tl::toW(pMyItem->text.getStr()), pMyItem->text.getLength(), &size );
657 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) );
659 // Restore the original font and colors.
660 DeleteObject( SelectObject( lpdis->hDC, hbrOld ) );
661 DeleteObject( SelectObject( lpdis->hDC, hfntOld) );
662 SetTextColor(lpdis->hDC, clrPrevText);
663 SetBkColor(lpdis->hDC, clrPrevBkgnd);
667 // code from setup2 project
670 static void SHFree_( void *pv )
672 IMalloc *pMalloc;
673 if( NOERROR == SHGetMalloc(&pMalloc) )
675 pMalloc->Free( pv );
676 pMalloc->Release();
680 #define ALLOC(type, n) static_cast<type *>(HeapAlloc(GetProcessHeap(), 0, sizeof(type) * n ))
681 #define FREE(p) HeapFree(GetProcessHeap(), 0, p)
683 static OUString SHGetSpecialFolder( int nFolderID )
686 LPITEMIDLIST pidl;
687 HRESULT hHdl = SHGetSpecialFolderLocation( nullptr, nFolderID, &pidl );
688 OUString aFolder;
690 if( hHdl == NOERROR )
692 WCHAR *lpFolderA;
693 lpFolderA = ALLOC( WCHAR, 16000 );
695 SHGetPathFromIDListW( pidl, lpFolderA );
696 aFolder = o3tl::toU( lpFolderA );
698 FREE( lpFolderA );
699 SHFree_( pidl );
701 return aFolder;
704 OUString ShutdownIcon::GetAutostartFolderNameW32()
706 return SHGetSpecialFolder(CSIDL_STARTUP);
709 static HRESULT WINAPI SHCoCreateInstance( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv )
711 HRESULT hResult = E_NOTIMPL;
712 HMODULE hModShell = GetModuleHandleW( L"SHELL32" );
714 if ( hModShell != nullptr )
716 typedef HRESULT (WINAPI *SHCoCreateInstance_PROC)( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv );
718 SHCoCreateInstance_PROC lpfnSHCoCreateInstance = reinterpret_cast<SHCoCreateInstance_PROC>(GetProcAddress( hModShell, MAKEINTRESOURCEA(102) ));
720 if ( lpfnSHCoCreateInstance )
721 hResult = lpfnSHCoCreateInstance( lpszReserved, clsid, pUnkUnknown, iid, ppv );
723 return hResult;
726 static bool CreateShortcut( const OUString& rAbsObject, const OUString& rAbsObjectPath,
727 const OUString& rAbsShortcut, const OUString& rDescription, const OUString& rParameter )
729 HRESULT hres;
730 IShellLinkW* psl;
731 CLSID clsid_ShellLink = CLSID_ShellLink;
732 CLSID clsid_IShellLink = IID_IShellLinkW;
734 hres = CoCreateInstance( clsid_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
735 clsid_IShellLink, reinterpret_cast<void**>(&psl) );
736 if( FAILED(hres) )
737 hres = SHCoCreateInstance( nullptr, clsid_ShellLink, nullptr, clsid_IShellLink, reinterpret_cast<void**>(&psl) );
739 if( SUCCEEDED(hres) )
741 IPersistFile* ppf;
742 psl->SetPath( o3tl::toW(rAbsObject.getStr()) );
743 psl->SetWorkingDirectory( o3tl::toW(rAbsObjectPath.getStr()) );
744 psl->SetDescription( o3tl::toW(rDescription.getStr()) );
745 if( rParameter.getLength() )
746 psl->SetArguments( o3tl::toW(rParameter.getStr()) );
748 CLSID clsid_IPersistFile = IID_IPersistFile;
749 hres = psl->QueryInterface( clsid_IPersistFile, reinterpret_cast<void**>(&ppf) );
751 if( SUCCEEDED(hres) )
753 hres = ppf->Save( o3tl::toW(rAbsShortcut.getStr()), TRUE );
754 ppf->Release();
755 } else return false;
756 psl->Release();
757 } else return false;
758 return true;
762 // install/uninstall
764 static bool FileExistsW( LPCWSTR lpPath )
766 bool bExists = false;
767 WIN32_FIND_DATAW aFindData;
769 HANDLE hFind = FindFirstFileW( lpPath, &aFindData );
771 if ( INVALID_HANDLE_VALUE != hFind )
773 bExists = true;
774 FindClose( hFind );
777 return bExists;
780 bool ShutdownIcon::IsQuickstarterInstalled()
782 wchar_t aPath[_MAX_PATH];
783 GetModuleFileNameW( nullptr, aPath, _MAX_PATH-1);
785 OUString aOfficepath( o3tl::toU(aPath) );
786 int i = aOfficepath.lastIndexOf('\\');
787 if( i != -1 )
788 aOfficepath = aOfficepath.copy(0, i);
790 OUString quickstartExe(aOfficepath + "\\quickstart.exe");
792 return FileExistsW( o3tl::toW(quickstartExe.getStr()) );
795 void ShutdownIcon::EnableAutostartW32( const OUString &aShortcut )
797 wchar_t aPath[_MAX_PATH];
798 GetModuleFileNameW( nullptr, aPath, _MAX_PATH-1);
800 OUString aOfficepath( o3tl::toU(aPath) );
801 int i = aOfficepath.lastIndexOf('\\');
802 if( i != -1 )
803 aOfficepath = aOfficepath.copy(0, i);
805 OUString quickstartExe(aOfficepath + "\\quickstart.exe");
807 CreateShortcut( quickstartExe, aOfficepath, aShortcut, OUString(), OUString() );
811 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */