Branch libreoffice-5-0-4
[LibreOffice.git] / sfx2 / source / appl / shutdowniconw32.cxx
blob55b0d5bae421d1a4a4164f6125321b7810e8ba46
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>
21 #ifdef WNT
23 // necessary to include system headers without warnings
24 #ifdef _MSC_VER
25 #pragma warning(disable:4668 4917)
26 #endif
28 #define USE_APP_SHORTCUTS
29 // the systray icon is only available on windows
31 #include <unotools/moduleoptions.hxx>
32 #include <unotools/dynamicmenuoptions.hxx>
34 #undef WB_LEFT
35 #undef WB_RIGHT
37 #include "shutdownicon.hxx"
38 #include "app.hrc"
39 #include <shlobj.h>
40 #include <objidl.h>
41 #include <osl/thread.h>
42 #include <systools/win32/qswin32.h>
43 #include <comphelper/sequenceashashmap.hxx>
45 #include <set>
47 using namespace ::osl;
49 using ::com::sun::star::uno::Sequence;
50 using ::com::sun::star::beans::PropertyValue;
53 #define EXECUTER_WINDOWCLASS "SO Executer Class"
54 #define EXECUTER_WINDOWNAME "SO Executer Window"
57 #define ID_QUICKSTART 1
58 #define IDM_EXIT 2
59 #if defined(USE_APP_SHORTCUTS)
60 # define IDM_OPEN 3
61 # define IDM_WRITER 4
62 # define IDM_CALC 5
63 # define IDM_IMPRESS 6
64 # define IDM_DRAW 7
65 # define IDM_BASE 8
66 # define IDM_TEMPLATE 9
67 # define IDM_MATH 12
68 #endif
69 #define IDM_INSTALL 10
72 #define ICON_LO_DEFAULT 1
73 #define ICON_TEXT_DOCUMENT 2
74 #define ICON_SPREADSHEET_DOCUMENT 4
75 #define ICON_DRAWING_DOCUMENT 6
76 #define ICON_PRESENTATION_DOCUMENT 8
77 #define ICON_TEMPLATE 11
78 #define ICON_DATABASE_DOCUMENT 12
79 #define ICON_MATH_DOCUMENT 13
80 #define ICON_OPEN 5 // See index of open folder icon in shell32.dll
82 #define SFX_TASKBAR_NOTIFICATION WM_USER+1
84 static HWND aListenerWindow = NULL;
85 static HWND aExecuterWindow = NULL;
86 static HMENU popupMenu = NULL;
88 static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis);
89 static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis);
91 typedef struct tagMYITEM
93 OUString text;
94 OUString module;
95 UINT iconId;
96 } MYITEM;
100 static void addMenuItem( HMENU hMenu, UINT id, UINT iconId, const OUString& text, int& pos, int bOwnerdraw, const OUString& module )
102 MENUITEMINFOW mi;
103 memset( &mi, 0, sizeof( MENUITEMINFOW ) );
105 mi.cbSize = sizeof( MENUITEMINFOW );
106 if( id == static_cast<UINT>( -1 ) )
108 mi.fMask=MIIM_TYPE;
109 mi.fType=MFT_SEPARATOR;
111 else
113 if( bOwnerdraw )
115 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
116 mi.fType=MFT_OWNERDRAW;
117 mi.fState=MFS_ENABLED;
118 mi.wID = id;
120 MYITEM *pMyItem = new MYITEM;
121 pMyItem->text = text;
122 pMyItem->iconId = iconId;
123 pMyItem->module = module;
124 mi.dwItemData = (DWORD_PTR) pMyItem;
126 else
128 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
129 mi.fType=MFT_STRING;
130 mi.fState=MFS_ENABLED;
131 mi.wID = id;
132 mi.dwTypeData = (LPWSTR) text.getStr();
133 mi.cch = text.getLength();
136 #if defined(USE_APP_SHORTCUTS)
137 if ( IDM_TEMPLATE == id )
138 mi.fState |= MFS_DEFAULT;
139 #endif
142 InsertMenuItemW( hMenu, pos++, TRUE, &mi );
147 static HMENU createSystrayMenu( )
149 SvtModuleOptions aModuleOptions;
151 HMENU hMenu = CreatePopupMenu();
152 int pos=0;
154 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
155 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!");
157 if( !pShutdownIcon )
158 return NULL;
160 #if defined(USE_APP_SHORTCUTS)
161 // collect the URLs of the entries in the File/New menu
162 ::std::set< OUString > aFileNewAppsAvailable;
163 SvtDynamicMenuOptions aOpt;
164 Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU );
165 const OUString sURLKey( "URL" );
167 const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray();
168 const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength();
169 for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu )
171 ::comphelper::SequenceAsHashMap aEntryItems( *pNewMenu );
172 OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, OUString() ) );
173 if ( sURL.getLength() )
174 aFileNewAppsAvailable.insert( sURL );
177 // describe the menu entries for launching the applications
178 struct MenuEntryDescriptor
180 SvtModuleOptions::EModule eModuleIdentifier;
181 UINT nMenuItemID;
182 UINT nMenuIconID;
183 const char* pAsciiURLDescription;
184 } aMenuItems[] =
186 { SvtModuleOptions::EModule::WRITER, IDM_WRITER, ICON_TEXT_DOCUMENT, WRITER_URL },
187 { SvtModuleOptions::EModule::CALC, IDM_CALC, ICON_SPREADSHEET_DOCUMENT, CALC_URL },
188 { SvtModuleOptions::EModule::IMPRESS, IDM_IMPRESS,ICON_PRESENTATION_DOCUMENT, IMPRESS_WIZARD_URL },
189 { SvtModuleOptions::EModule::DRAW, IDM_DRAW, ICON_DRAWING_DOCUMENT, DRAW_URL },
190 { SvtModuleOptions::EModule::DATABASE, IDM_BASE, ICON_DATABASE_DOCUMENT, BASE_URL },
191 { SvtModuleOptions::EModule::MATH, IDM_MATH, ICON_MATH_DOCUMENT, MATH_URL },
194 OUString aEmpty;
196 // insert the menu entries for launching the applications
197 for ( size_t i = 0; i < sizeof( aMenuItems ) / sizeof( aMenuItems[0] ); ++i )
199 if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) )
200 // the complete application is not even installed
201 continue;
203 OUString sURL( OUString::createFromAscii( aMenuItems[i].pAsciiURLDescription ) );
205 if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() )
206 // the application is installed, but the entry has been configured to *not* appear in the File/New
207 // menu => also let not appear it in the quickstarter
208 continue;
210 addMenuItem( hMenu, aMenuItems[i].nMenuItemID, aMenuItems[i].nMenuIconID,
211 pShutdownIcon->GetUrlDescription( sURL ), pos, true, aEmpty );
216 // insert the remaining menu entries
217 addMenuItem( hMenu, IDM_TEMPLATE, ICON_TEMPLATE,
218 pShutdownIcon->GetResString( STR_QUICKSTART_FROMTEMPLATE ), pos, true, aEmpty);
219 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
220 addMenuItem( hMenu, IDM_OPEN, ICON_OPEN, pShutdownIcon->GetResString( STR_QUICKSTART_FILEOPEN ), pos, true, OUString("SHELL32"));
221 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
222 #endif
223 addMenuItem( hMenu, IDM_INSTALL,0, pShutdownIcon->GetResString( STR_QUICKSTART_PRELAUNCH ), pos, false, aEmpty );
224 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
225 addMenuItem( hMenu, IDM_EXIT, 0, pShutdownIcon->GetResString( STR_QUICKSTART_EXIT ), pos, false, aEmpty );
227 // indicate status of autostart folder
228 CheckMenuItem( hMenu, IDM_INSTALL, MF_BYCOMMAND | (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
230 return hMenu;
235 static void deleteSystrayMenu( HMENU hMenu )
237 if( !hMenu || !IsMenu( hMenu ))
238 return;
240 MENUITEMINFOW mi;
241 int pos=0;
242 memset( &mi, 0, sizeof( mi ) );
243 mi.cbSize = sizeof( mi );
244 mi.fMask = MIIM_DATA;
246 while( GetMenuItemInfoW( hMenu, pos++, true, &mi ) )
248 MYITEM *pMyItem = (MYITEM*) mi.dwItemData;
249 if( pMyItem )
251 (pMyItem->text).clear();
252 delete pMyItem;
254 mi.fMask = MIIM_DATA;
260 static void addTaskbarIcon( HWND hWnd )
262 OUString strTip;
263 if( ShutdownIcon::getInstance() )
264 strTip = ShutdownIcon::getInstance()->GetResString( STR_QUICKSTART_TIP );
266 // add taskbar icon
267 NOTIFYICONDATAW nid;
268 nid.hIcon = (HICON)LoadImageA( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_LO_DEFAULT ),
269 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ),
270 LR_DEFAULTCOLOR | LR_SHARED );
272 wcsncpy( nid.szTip, reinterpret_cast<LPCWSTR>(strTip.getStr()), 64 );
274 nid.cbSize = sizeof(nid);
275 nid.hWnd = hWnd;
276 nid.uID = ID_QUICKSTART;
277 nid.uCallbackMessage = SFX_TASKBAR_NOTIFICATION;
278 nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON;
280 Shell_NotifyIconW(NIM_ADD, &nid);
285 LRESULT CALLBACK listenerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
287 static UINT s_uTaskbarRestart = 0;
288 static UINT s_uMsgKillTray = 0;
290 switch (uMsg)
292 case WM_NCCREATE:
293 return TRUE;
294 case WM_CREATE:
296 // request notfication when taskbar is recreated
297 // we then have to add our icon again
298 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
299 s_uMsgKillTray = RegisterWindowMessage( SHUTDOWN_QUICKSTART_MESSAGE );
301 // create the menu
302 if( !popupMenu )
303 if( (popupMenu = createSystrayMenu( )) == NULL )
304 return -1;
306 // and the icon
307 addTaskbarIcon( hWnd );
309 // disable shutdown
310 ShutdownIcon::getInstance()->SetVeto( true );
311 ShutdownIcon::getInstance()->addTerminateListener();
313 return 0;
315 case WM_MEASUREITEM:
316 OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT) lParam);
317 return TRUE;
319 case WM_DRAWITEM:
320 OnDrawItem(hWnd, (LPDRAWITEMSTRUCT) lParam);
321 return TRUE;
323 case SFX_TASKBAR_NOTIFICATION:
324 switch( lParam )
326 case WM_LBUTTONDBLCLK:
327 #if defined(USE_APP_SHORTCUTS)
328 PostMessage( aExecuterWindow, WM_COMMAND, IDM_TEMPLATE, (LPARAM)hWnd );
329 #endif
330 break;
332 case WM_RBUTTONDOWN:
334 POINT pt;
335 GetCursorPos(&pt);
336 SetForegroundWindow( hWnd );
338 // update status before showing menu, could have been changed from option page
339 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
341 EnableMenuItem( popupMenu, IDM_EXIT, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
342 #if defined(USE_APP_SHORTCUTS)
343 EnableMenuItem( popupMenu, IDM_OPEN, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
344 EnableMenuItem( popupMenu, IDM_TEMPLATE, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
345 #endif
346 int m = TrackPopupMenuEx( popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON,
347 pt.x, pt.y, hWnd, NULL );
348 PostMessage( hWnd, 0, 0, 0 );
349 switch( m )
351 #if defined(USE_APP_SHORTCUTS)
352 case IDM_OPEN:
353 case IDM_WRITER:
354 case IDM_CALC:
355 case IDM_IMPRESS:
356 case IDM_DRAW:
357 case IDM_TEMPLATE:
358 case IDM_BASE:
359 case IDM_MATH:
360 break;
361 #endif
362 case IDM_INSTALL:
363 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
364 break;
365 case IDM_EXIT:
366 // delete taskbar icon
367 NOTIFYICONDATAA nid;
368 nid.cbSize=sizeof(NOTIFYICONDATA);
369 nid.hWnd = hWnd;
370 nid.uID = ID_QUICKSTART;
371 Shell_NotifyIconA(NIM_DELETE, &nid);
372 break;
375 PostMessage( aExecuterWindow, WM_COMMAND, m, (LPARAM)hWnd );
377 break;
379 break;
380 case WM_DESTROY:
381 deleteSystrayMenu( popupMenu );
382 // We don't need the Systray Thread anymore
383 PostQuitMessage( 0 );
384 return DefWindowProc(hWnd, uMsg, wParam, lParam);
385 default:
386 if( uMsg == s_uTaskbarRestart )
388 // re-create taskbar icon
389 addTaskbarIcon( hWnd );
391 else if ( uMsg == s_uMsgKillTray )
393 // delete taskbar icon
394 NOTIFYICONDATAA nid;
395 nid.cbSize=sizeof(NOTIFYICONDATA);
396 nid.hWnd = hWnd;
397 nid.uID = ID_QUICKSTART;
398 Shell_NotifyIconA(NIM_DELETE, &nid);
400 PostMessage( aExecuterWindow, WM_COMMAND, IDM_EXIT, (LPARAM)hWnd );
402 else
403 return DefWindowProc(hWnd, uMsg, wParam, lParam);
405 return 0;
410 LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
412 switch (uMsg)
414 case WM_NCCREATE:
415 return TRUE;
416 case WM_CREATE:
417 return 0;
419 case WM_COMMAND:
420 switch( LOWORD(wParam) )
422 #if defined(USE_APP_SHORTCUTS)
423 case IDM_OPEN:
424 if ( !ShutdownIcon::bModalMode )
425 ShutdownIcon::FileOpen();
426 break;
427 case IDM_WRITER:
428 ShutdownIcon::OpenURL( OUString( WRITER_URL ), OUString( "_default" ) );
429 break;
430 case IDM_CALC:
431 ShutdownIcon::OpenURL( OUString( CALC_URL ), OUString( "_default" ) );
432 break;
433 case IDM_IMPRESS:
434 ShutdownIcon::OpenURL( OUString( IMPRESS_WIZARD_URL ), OUString( "_default" ) );
435 break;
436 case IDM_DRAW:
437 ShutdownIcon::OpenURL( OUString( DRAW_URL ), OUString( "_default" ) );
438 break;
439 case IDM_BASE:
440 ShutdownIcon::OpenURL( OUString( BASE_URL ), OUString( "_default" ) );
441 break;
442 case IDM_MATH:
443 ShutdownIcon::OpenURL( OUString( MATH_URL ), OUString( "_default" ) );
444 break;
445 case IDM_TEMPLATE:
446 if ( !ShutdownIcon::bModalMode )
447 ShutdownIcon::FromTemplate();
448 break;
449 #endif
450 case IDM_INSTALL:
451 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() );
452 break;
453 case IDM_EXIT:
454 // remove listener and
455 // terminate office if running in background
456 if ( !ShutdownIcon::bModalMode )
457 ShutdownIcon::terminateDesktop();
458 break;
460 break;
461 case WM_DESTROY:
462 default:
463 return DefWindowProc(hWnd, uMsg, wParam, lParam);
465 return 0;
471 DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ )
473 osl_setThreadName("SystrayThread");
475 aListenerWindow = CreateWindowExA(0,
476 QUICKSTART_CLASSNAME, // registered class name
477 QUICKSTART_WINDOWNAME, // window name
478 0, // window style
479 CW_USEDEFAULT, // horizontal position of window
480 CW_USEDEFAULT, // vertical position of window
481 CW_USEDEFAULT, // window width
482 CW_USEDEFAULT, // window height
483 (HWND) NULL, // handle to parent or owner window
484 NULL, // menu handle or child identifier
485 (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance
486 NULL // window-creation data
489 MSG msg;
491 while ( GetMessage( &msg, NULL, 0, 0 ) )
493 TranslateMessage( &msg );
494 DispatchMessage( &msg );
497 return msg.wParam; // Exit code of WM_QUIT
502 void win32_init_sys_tray()
504 if ( ShutdownIcon::IsQuickstarterInstalled() )
506 WNDCLASSEXA listenerClass;
507 listenerClass.cbSize = sizeof(WNDCLASSEX);
508 listenerClass.style = 0;
509 listenerClass.lpfnWndProc = listenerWndProc;
510 listenerClass.cbClsExtra = 0;
511 listenerClass.cbWndExtra = 0;
512 listenerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL );
513 listenerClass.hIcon = NULL;
514 listenerClass.hCursor = NULL;
515 listenerClass.hbrBackground = NULL;
516 listenerClass.lpszMenuName = NULL;
517 listenerClass.lpszClassName = QUICKSTART_CLASSNAME;
518 listenerClass.hIconSm = NULL;
520 RegisterClassExA(&listenerClass);
522 WNDCLASSEXA executerClass;
523 executerClass.cbSize = sizeof(WNDCLASSEX);
524 executerClass.style = 0;
525 executerClass.lpfnWndProc = executerWndProc;
526 executerClass.cbClsExtra = 0;
527 executerClass.cbWndExtra = 0;
528 executerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL );
529 executerClass.hIcon = NULL;
530 executerClass.hCursor = NULL;
531 executerClass.hbrBackground = NULL;
532 executerClass.lpszMenuName = NULL;
533 executerClass.lpszClassName = EXECUTER_WINDOWCLASS;
534 executerClass.hIconSm = NULL;
536 RegisterClassExA( &executerClass );
538 aExecuterWindow = CreateWindowExA(0,
539 EXECUTER_WINDOWCLASS, // registered class name
540 EXECUTER_WINDOWNAME, // window name
541 0, // window style
542 CW_USEDEFAULT, // horizontal position of window
543 CW_USEDEFAULT, // vertical position of window
544 CW_USEDEFAULT, // window width
545 CW_USEDEFAULT, // window height
546 (HWND) NULL, // handle to parent or owner window
547 NULL, // menu handle or child identifier
548 (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance
549 NULL // window-creation data
552 DWORD dwThreadId;
553 CreateThread( NULL, 0, SystrayThread, NULL, 0, &dwThreadId );
559 void win32_shutdown_sys_tray()
561 if ( ShutdownIcon::IsQuickstarterInstalled() )
563 if( IsWindow( aListenerWindow ) )
565 DestroyWindow( aListenerWindow );
566 aListenerWindow = NULL;
567 DestroyWindow( aExecuterWindow );
568 aExecuterWindow = NULL;
570 UnregisterClassA( QUICKSTART_CLASSNAME, GetModuleHandle( NULL ) );
571 UnregisterClassA( EXECUTER_WINDOWCLASS, GetModuleHandle( NULL ) );
579 void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
581 MYITEM *pMyItem = (MYITEM *) lpmis->itemData;
582 HDC hdc = GetDC(hwnd);
583 SIZE size;
585 NONCLIENTMETRICS ncm;
586 memset(&ncm, 0, sizeof(ncm));
587 ncm.cbSize = sizeof(ncm);
589 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0);
591 // Assume every menu item can be default and printed bold
592 ncm.lfMenuFont.lfWeight = FW_BOLD;
594 HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
596 GetTextExtentPoint32W(hdc, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()),
597 pMyItem->text.getLength(), &size);
599 lpmis->itemWidth = size.cx + 4 + GetSystemMetrics( SM_CXSMICON );
600 lpmis->itemHeight = (size.cy > GetSystemMetrics( SM_CYSMICON )) ? size.cy : GetSystemMetrics( SM_CYSMICON );
601 lpmis->itemHeight += 4;
603 DeleteObject( SelectObject(hdc, hfntOld) );
604 ReleaseDC(hwnd, hdc);
607 void OnDrawItem(HWND /*hwnd*/, LPDRAWITEMSTRUCT lpdis)
609 MYITEM *pMyItem = (MYITEM *) lpdis->itemData;
610 COLORREF clrPrevText, clrPrevBkgnd;
611 HFONT hfntOld;
612 HBRUSH hbrOld;
613 int x, y;
614 BOOL fSelected = lpdis->itemState & ODS_SELECTED;
615 BOOL fDisabled = lpdis->itemState & (ODS_DISABLED | ODS_GRAYED);
617 // Set the appropriate foreground and background colors.
619 RECT aRect = lpdis->rcItem;
621 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
623 if ( fDisabled )
624 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) );
625 else
626 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
628 if ( fSelected )
629 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) );
630 else
631 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
633 hbrOld = (HBRUSH)SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) );
635 // Fill background
636 PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY);
638 int height = aRect.bottom-aRect.top;
640 x = aRect.left;
641 y = aRect.top;
643 int cx = GetSystemMetrics( SM_CXSMICON );
644 int cy = GetSystemMetrics( SM_CYSMICON );
645 HICON hIcon( 0 );
646 HMODULE hModule( GetModuleHandle( NULL ) );
648 if ( pMyItem->module.getLength() > 0 )
650 LPCWSTR pModuleName = reinterpret_cast<LPCWSTR>( pMyItem->module.getStr() );
651 hModule = GetModuleHandleW( pModuleName );
652 if ( hModule == NULL )
654 LoadLibraryW( pModuleName );
655 hModule = GetModuleHandleW( pModuleName );
659 hIcon = (HICON) LoadImageA( hModule, MAKEINTRESOURCE( pMyItem->iconId ),
660 IMAGE_ICON, cx, cy,
661 LR_DEFAULTCOLOR | LR_SHARED );
664 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
666 DrawStateW( lpdis->hDC, (HBRUSH)hbrIcon, (DRAWSTATEPROC)NULL, (LPARAM)hIcon, (WPARAM)0, x, y+(height-cy)/2, 0, 0, DST_ICON | (fDisabled ? (fSelected ? DSS_MONO : DSS_DISABLED) : DSS_NORMAL) );
668 DeleteObject( hbrIcon );
670 x += cx + 4; // space for icon
671 aRect.left = x;
673 NONCLIENTMETRICS ncm;
674 memset(&ncm, 0, sizeof(ncm));
675 ncm.cbSize = sizeof(ncm);
677 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0);
679 // Print default menu entry with bold font
680 if ( lpdis->itemState & ODS_DEFAULT )
681 ncm.lfMenuFont.lfWeight = FW_BOLD;
683 hfntOld = (HFONT) SelectObject(lpdis->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
686 SIZE size;
687 GetTextExtentPointW( lpdis->hDC, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()), pMyItem->text.getLength(), &size );
689 DrawStateW( lpdis->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL, (LPARAM)pMyItem->text.getStr(), (WPARAM)0, aRect.left, aRect.top + (height - size.cy)/2, 0, 0, DST_TEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) );
691 // Restore the original font and colors.
692 DeleteObject( SelectObject( lpdis->hDC, hbrOld ) );
693 DeleteObject( SelectObject( lpdis->hDC, hfntOld) );
694 SetTextColor(lpdis->hDC, clrPrevText);
695 SetBkColor(lpdis->hDC, clrPrevBkgnd);
699 // code from setup2 project
702 void _SHFree( void *pv )
704 IMalloc *pMalloc;
705 if( NOERROR == SHGetMalloc(&pMalloc) )
707 pMalloc->Free( pv );
708 pMalloc->Release();
712 #define ALLOC(type, n) ((type *) HeapAlloc(GetProcessHeap(), 0, sizeof(type) * n ))
713 #define FREE(p) HeapFree(GetProcessHeap(), 0, p)
715 static OUString _SHGetSpecialFolder( int nFolderID )
718 LPITEMIDLIST pidl;
719 HRESULT hHdl = SHGetSpecialFolderLocation( NULL, nFolderID, &pidl );
720 OUString aFolder;
722 if( hHdl == NOERROR )
724 WCHAR *lpFolderA;
725 lpFolderA = ALLOC( WCHAR, 16000 );
727 SHGetPathFromIDListW( pidl, lpFolderA );
728 aFolder = OUString( reinterpret_cast<const sal_Unicode*>(lpFolderA) );
730 FREE( lpFolderA );
731 _SHFree( pidl );
733 return aFolder;
736 OUString ShutdownIcon::GetAutostartFolderNameW32()
738 return _SHGetSpecialFolder(CSIDL_STARTUP);
741 static HRESULT WINAPI SHCoCreateInstance( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv )
743 HRESULT hResult = E_NOTIMPL;
744 HMODULE hModShell = GetModuleHandle( "SHELL32" );
746 if ( hModShell != NULL )
748 typedef HRESULT (WINAPI *SHCoCreateInstance_PROC)( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknwon, REFIID iid, LPVOID *ppv );
750 SHCoCreateInstance_PROC lpfnSHCoCreateInstance = (SHCoCreateInstance_PROC)GetProcAddress( hModShell, MAKEINTRESOURCE(102) );
752 if ( lpfnSHCoCreateInstance )
753 hResult = lpfnSHCoCreateInstance( lpszReserved, clsid, pUnkUnknown, iid, ppv );
755 return hResult;
758 BOOL CreateShortcut( const OUString& rAbsObject, const OUString& rAbsObjectPath,
759 const OUString& rAbsShortcut, const OUString& rDescription, const OUString& rParameter )
761 HRESULT hres;
762 IShellLink* psl;
763 CLSID clsid_ShellLink = CLSID_ShellLink;
764 CLSID clsid_IShellLink = IID_IShellLink;
766 hres = CoCreateInstance( clsid_ShellLink, NULL, CLSCTX_INPROC_SERVER,
767 clsid_IShellLink, (void**)&psl );
768 if( FAILED(hres) )
769 hres = SHCoCreateInstance( NULL, clsid_ShellLink, NULL, clsid_IShellLink, (void**)&psl );
771 if( SUCCEEDED(hres) )
773 IPersistFile* ppf;
774 psl->SetPath( OUStringToOString(rAbsObject, osl_getThreadTextEncoding()).getStr() );
775 psl->SetWorkingDirectory( OUStringToOString(rAbsObjectPath, osl_getThreadTextEncoding()).getStr() );
776 psl->SetDescription( OUStringToOString(rDescription, osl_getThreadTextEncoding()).getStr() );
777 if( rParameter.getLength() )
778 psl->SetArguments( OUStringToOString(rParameter, osl_getThreadTextEncoding()).getStr() );
780 CLSID clsid_IPersistFile = IID_IPersistFile;
781 hres = psl->QueryInterface( clsid_IPersistFile, (void**)&ppf );
783 if( SUCCEEDED(hres) )
785 hres = ppf->Save( reinterpret_cast<LPCOLESTR>(rAbsShortcut.getStr()), TRUE );
786 ppf->Release();
787 } else return FALSE;
788 psl->Release();
789 } else return FALSE;
790 return TRUE;
794 // install/uninstall
796 static bool FileExistsW( LPCWSTR lpPath )
798 bool bExists = false;
799 WIN32_FIND_DATAW aFindData;
801 HANDLE hFind = FindFirstFileW( lpPath, &aFindData );
803 if ( INVALID_HANDLE_VALUE != hFind )
805 bExists = true;
806 FindClose( hFind );
809 return bExists;
812 bool ShutdownIcon::IsQuickstarterInstalled()
814 wchar_t aPath[_MAX_PATH];
815 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1);
817 OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) );
818 int i = aOfficepath.lastIndexOf((sal_Char) '\\');
819 if( i != -1 )
820 aOfficepath = aOfficepath.copy(0, i);
822 OUString quickstartExe(aOfficepath);
823 quickstartExe += "\\quickstart.exe";
825 return FileExistsW( reinterpret_cast<LPCWSTR>(quickstartExe.getStr()) );
828 void ShutdownIcon::EnableAutostartW32( const OUString &aShortcut )
830 wchar_t aPath[_MAX_PATH];
831 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1);
833 OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) );
834 int i = aOfficepath.lastIndexOf((sal_Char) '\\');
835 if( i != -1 )
836 aOfficepath = aOfficepath.copy(0, i);
838 OUString quickstartExe(aOfficepath);
839 quickstartExe += "\\quickstart.exe";
841 CreateShortcut( quickstartExe, aOfficepath, aShortcut, OUString(), OUString() );
844 #endif // WNT
847 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */