bump product version to 4.2.0.1
[LibreOffice.git] / sfx2 / source / appl / shutdowniconw32.cxx
blob8c7a6a1cd42f6fea54ba6a74ab043250b8ee9012
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 ::rtl;
48 using namespace ::osl;
50 using ::com::sun::star::uno::Sequence;
51 using ::com::sun::star::beans::PropertyValue;
54 #define EXECUTER_WINDOWCLASS "SO Executer Class"
55 #define EXECUTER_WINDOWNAME "SO Executer Window"
58 #define ID_QUICKSTART 1
59 #define IDM_EXIT 2
60 #if defined(USE_APP_SHORTCUTS)
61 # define IDM_OPEN 3
62 # define IDM_WRITER 4
63 # define IDM_CALC 5
64 # define IDM_IMPRESS 6
65 # define IDM_DRAW 7
66 # define IDM_BASE 8
67 # define IDM_TEMPLATE 9
68 # define IDM_MATH 12
69 #endif
70 #define IDM_INSTALL 10
73 #define ICON_LO_DEFAULT 1
74 #define ICON_TEXT_DOCUMENT 2
75 #define ICON_SPREADSHEET_DOCUMENT 4
76 #define ICON_DRAWING_DOCUMENT 6
77 #define ICON_PRESENTATION_DOCUMENT 8
78 #define ICON_TEMPLATE 11
79 #define ICON_DATABASE_DOCUMENT 12
80 #define ICON_MATH_DOCUMENT 13
81 #define ICON_OPEN 5 // See index of open folder icon in shell32.dll
83 #define SFX_TASKBAR_NOTIFICATION WM_USER+1
85 static HWND aListenerWindow = NULL;
86 static HWND aExecuterWindow = NULL;
87 static HMENU popupMenu = NULL;
89 static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis);
90 static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis);
92 typedef struct tagMYITEM
94 OUString text;
95 OUString module;
96 UINT iconId;
97 } MYITEM;
99 // -------------------------------
101 static void addMenuItem( HMENU hMenu, UINT id, UINT iconId, const OUString& text, int& pos, int bOwnerdraw, const OUString& module )
103 MENUITEMINFOW mi;
104 memset( &mi, 0, sizeof( MENUITEMINFOW ) );
106 mi.cbSize = sizeof( MENUITEMINFOW );
107 if( id == static_cast<UINT>( -1 ) )
109 mi.fMask=MIIM_TYPE;
110 mi.fType=MFT_SEPARATOR;
112 else
114 if( bOwnerdraw )
116 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
117 mi.fType=MFT_OWNERDRAW;
118 mi.fState=MFS_ENABLED;
119 mi.wID = id;
121 MYITEM *pMyItem = new MYITEM;
122 pMyItem->text = text;
123 pMyItem->iconId = iconId;
124 pMyItem->module = module;
125 mi.dwItemData = (DWORD_PTR) pMyItem;
127 else
129 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
130 mi.fType=MFT_STRING;
131 mi.fState=MFS_ENABLED;
132 mi.wID = id;
133 mi.dwTypeData = (LPWSTR) text.getStr();
134 mi.cch = text.getLength();
137 #if defined(USE_APP_SHORTCUTS)
138 if ( IDM_TEMPLATE == id )
139 mi.fState |= MFS_DEFAULT;
140 #endif
143 InsertMenuItemW( hMenu, pos++, TRUE, &mi );
146 // -------------------------------
148 static HMENU createSystrayMenu( )
150 SvtModuleOptions aModuleOptions;
152 HMENU hMenu = CreatePopupMenu();
153 int pos=0;
155 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
156 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!");
158 if( !pShutdownIcon )
159 return NULL;
161 #if defined(USE_APP_SHORTCUTS)
162 // collect the URLs of the entries in the File/New menu
163 ::std::set< OUString > aFileNewAppsAvailable;
164 SvtDynamicMenuOptions aOpt;
165 Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU );
166 const OUString sURLKey( "URL" );
168 const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray();
169 const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength();
170 for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu )
172 ::comphelper::SequenceAsHashMap aEntryItems( *pNewMenu );
173 OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, OUString() ) );
174 if ( sURL.getLength() )
175 aFileNewAppsAvailable.insert( sURL );
178 // describe the menu entries for launching the applications
179 struct MenuEntryDescriptor
181 SvtModuleOptions::EModule eModuleIdentifier;
182 UINT nMenuItemID;
183 UINT nMenuIconID;
184 const char* pAsciiURLDescription;
185 } aMenuItems[] =
187 { SvtModuleOptions::E_SWRITER, IDM_WRITER, ICON_TEXT_DOCUMENT, WRITER_URL },
188 { SvtModuleOptions::E_SCALC, IDM_CALC, ICON_SPREADSHEET_DOCUMENT, CALC_URL },
189 { SvtModuleOptions::E_SIMPRESS, IDM_IMPRESS,ICON_PRESENTATION_DOCUMENT, IMPRESS_WIZARD_URL },
190 { SvtModuleOptions::E_SDRAW, IDM_DRAW, ICON_DRAWING_DOCUMENT, DRAW_URL },
191 { SvtModuleOptions::E_SDATABASE, IDM_BASE, ICON_DATABASE_DOCUMENT, BASE_URL },
192 { SvtModuleOptions::E_SMATH, IDM_MATH, ICON_MATH_DOCUMENT, MATH_URL },
195 OUString aEmpty;
197 // insert the menu entries for launching the applications
198 for ( size_t i = 0; i < sizeof( aMenuItems ) / sizeof( aMenuItems[0] ); ++i )
200 if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) )
201 // the complete application is not even installed
202 continue;
204 OUString sURL( OUString::createFromAscii( aMenuItems[i].pAsciiURLDescription ) );
206 if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() )
207 // the application is installed, but the entry has been configured to *not* appear in the File/New
208 // menu => also let not appear it in the quickstarter
209 continue;
211 addMenuItem( hMenu, aMenuItems[i].nMenuItemID, aMenuItems[i].nMenuIconID,
212 pShutdownIcon->GetUrlDescription( sURL ), pos, true, aEmpty );
217 // insert the remaining menu entries
218 addMenuItem( hMenu, IDM_TEMPLATE, ICON_TEMPLATE,
219 pShutdownIcon->GetResString( STR_QUICKSTART_FROMTEMPLATE ), pos, true, aEmpty);
220 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
221 addMenuItem( hMenu, IDM_OPEN, ICON_OPEN, pShutdownIcon->GetResString( STR_QUICKSTART_FILEOPEN ), pos, true, OUString("SHELL32"));
222 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
223 #endif
224 addMenuItem( hMenu, IDM_INSTALL,0, pShutdownIcon->GetResString( STR_QUICKSTART_PRELAUNCH ), pos, false, aEmpty );
225 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
226 addMenuItem( hMenu, IDM_EXIT, 0, pShutdownIcon->GetResString( STR_QUICKSTART_EXIT ), pos, false, aEmpty );
228 // indicate status of autostart folder
229 CheckMenuItem( hMenu, IDM_INSTALL, MF_BYCOMMAND | (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
231 return hMenu;
234 // -------------------------------
236 static void deleteSystrayMenu( HMENU hMenu )
238 if( !hMenu || !IsMenu( hMenu ))
239 return;
241 MENUITEMINFOW mi;
242 MYITEM *pMyItem;
243 int pos=0;
244 memset( &mi, 0, sizeof( mi ) );
245 mi.cbSize = sizeof( mi );
246 mi.fMask = MIIM_DATA;
248 while( GetMenuItemInfoW( hMenu, pos++, true, &mi ) )
250 pMyItem = (MYITEM*) mi.dwItemData;
251 if( pMyItem )
253 pMyItem->text = OUString();
254 delete pMyItem;
256 mi.fMask = MIIM_DATA;
260 // -------------------------------
262 static void addTaskbarIcon( HWND hWnd )
264 OUString strTip;
265 if( ShutdownIcon::getInstance() )
266 strTip = ShutdownIcon::getInstance()->GetResString( STR_QUICKSTART_TIP );
268 // add taskbar icon
269 NOTIFYICONDATAW nid;
270 nid.hIcon = (HICON)LoadImageA( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_LO_DEFAULT ),
271 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ),
272 LR_DEFAULTCOLOR | LR_SHARED );
274 wcsncpy( nid.szTip, reinterpret_cast<LPCWSTR>(strTip.getStr()), 64 );
276 nid.cbSize = sizeof(nid);
277 nid.hWnd = hWnd;
278 nid.uID = ID_QUICKSTART;
279 nid.uCallbackMessage = SFX_TASKBAR_NOTIFICATION;
280 nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON;
282 Shell_NotifyIconW(NIM_ADD, &nid);
285 // -------------------------------
287 LRESULT CALLBACK listenerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
289 static UINT s_uTaskbarRestart = 0;
290 static UINT s_uMsgKillTray = 0;
292 switch (uMsg)
294 case WM_NCCREATE:
295 return TRUE;
296 case WM_CREATE:
298 // request notfication when taskbar is recreated
299 // we then have to add our icon again
300 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
301 s_uMsgKillTray = RegisterWindowMessage( SHUTDOWN_QUICKSTART_MESSAGE );
303 // create the menu
304 if( !popupMenu )
305 if( (popupMenu = createSystrayMenu( )) == NULL )
306 return -1;
308 // and the icon
309 addTaskbarIcon( hWnd );
311 // disable shutdown
312 ShutdownIcon::getInstance()->SetVeto( true );
313 ShutdownIcon::getInstance()->addTerminateListener();
315 return 0;
317 case WM_MEASUREITEM:
318 OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT) lParam);
319 return TRUE;
321 case WM_DRAWITEM:
322 OnDrawItem(hWnd, (LPDRAWITEMSTRUCT) lParam);
323 return TRUE;
325 case SFX_TASKBAR_NOTIFICATION:
326 switch( lParam )
328 case WM_LBUTTONDBLCLK:
329 #if defined(USE_APP_SHORTCUTS)
330 PostMessage( aExecuterWindow, WM_COMMAND, IDM_TEMPLATE, (LPARAM)hWnd );
331 #endif
332 break;
334 case WM_RBUTTONDOWN:
336 POINT pt;
337 GetCursorPos(&pt);
338 SetForegroundWindow( hWnd );
340 // update status before showing menu, could have been changed from option page
341 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
343 EnableMenuItem( popupMenu, IDM_EXIT, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
344 #if defined(USE_APP_SHORTCUTS)
345 EnableMenuItem( popupMenu, IDM_OPEN, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
346 EnableMenuItem( popupMenu, IDM_TEMPLATE, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
347 #endif
348 int m = TrackPopupMenuEx( popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON,
349 pt.x, pt.y, hWnd, NULL );
350 PostMessage( hWnd, 0, 0, 0 );
351 switch( m )
353 #if defined(USE_APP_SHORTCUTS)
354 case IDM_OPEN:
355 case IDM_WRITER:
356 case IDM_CALC:
357 case IDM_IMPRESS:
358 case IDM_DRAW:
359 case IDM_TEMPLATE:
360 case IDM_BASE:
361 case IDM_MATH:
362 break;
363 #endif
364 case IDM_INSTALL:
365 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
366 break;
367 case IDM_EXIT:
368 // delete taskbar icon
369 NOTIFYICONDATAA nid;
370 nid.cbSize=sizeof(NOTIFYICONDATA);
371 nid.hWnd = hWnd;
372 nid.uID = ID_QUICKSTART;
373 Shell_NotifyIconA(NIM_DELETE, &nid);
374 break;
377 PostMessage( aExecuterWindow, WM_COMMAND, m, (LPARAM)hWnd );
379 break;
381 break;
382 case WM_DESTROY:
383 deleteSystrayMenu( popupMenu );
384 // We don't need the Systray Thread anymore
385 PostQuitMessage( 0 );
386 return DefWindowProc(hWnd, uMsg, wParam, lParam);
387 default:
388 if( uMsg == s_uTaskbarRestart )
390 // re-create taskbar icon
391 addTaskbarIcon( hWnd );
393 else if ( uMsg == s_uMsgKillTray )
395 // delete taskbar icon
396 NOTIFYICONDATAA nid;
397 nid.cbSize=sizeof(NOTIFYICONDATA);
398 nid.hWnd = hWnd;
399 nid.uID = ID_QUICKSTART;
400 Shell_NotifyIconA(NIM_DELETE, &nid);
402 PostMessage( aExecuterWindow, WM_COMMAND, IDM_EXIT, (LPARAM)hWnd );
404 else
405 return DefWindowProc(hWnd, uMsg, wParam, lParam);
407 return 0;
410 // -------------------------------
412 LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
414 switch (uMsg)
416 case WM_NCCREATE:
417 return TRUE;
418 case WM_CREATE:
419 return 0;
421 case WM_COMMAND:
422 switch( LOWORD(wParam) )
424 #if defined(USE_APP_SHORTCUTS)
425 case IDM_OPEN:
426 if ( !ShutdownIcon::bModalMode )
427 ShutdownIcon::FileOpen();
428 break;
429 case IDM_WRITER:
430 ShutdownIcon::OpenURL( OUString( WRITER_URL ), OUString( "_default" ) );
431 break;
432 case IDM_CALC:
433 ShutdownIcon::OpenURL( OUString( CALC_URL ), OUString( "_default" ) );
434 break;
435 case IDM_IMPRESS:
436 ShutdownIcon::OpenURL( OUString( IMPRESS_WIZARD_URL ), OUString( "_default" ) );
437 break;
438 case IDM_DRAW:
439 ShutdownIcon::OpenURL( OUString( DRAW_URL ), OUString( "_default" ) );
440 break;
441 case IDM_BASE:
442 ShutdownIcon::OpenURL( OUString( BASE_URL ), OUString( "_default" ) );
443 break;
444 case IDM_MATH:
445 ShutdownIcon::OpenURL( OUString( MATH_URL ), OUString( "_default" ) );
446 break;
447 case IDM_TEMPLATE:
448 if ( !ShutdownIcon::bModalMode )
449 ShutdownIcon::FromTemplate();
450 break;
451 #endif
452 case IDM_INSTALL:
453 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() );
454 break;
455 case IDM_EXIT:
456 // remove listener and
457 // terminate office if running in background
458 if ( !ShutdownIcon::bModalMode )
459 ShutdownIcon::terminateDesktop();
460 break;
462 break;
463 case WM_DESTROY:
464 default:
465 return DefWindowProc(hWnd, uMsg, wParam, lParam);
467 return 0;
470 // -------------------------------
473 DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ )
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
500 // -------------------------------
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 );
557 // -------------------------------
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 ) );
577 // -------------------------------
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);
698 // -------------------------------
699 // code from setup2 project
700 // -------------------------------
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;
793 // ------------------
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: */