bump product version to 4.1.6.2
[LibreOffice.git] / sfx2 / source / appl / shutdowniconw32.cxx
blob6c374da5655690494006fdc3429ad125de4abe2b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/macros.h>
22 #ifdef WNT
24 // necessary to include system headers without warnings
25 #ifdef _MSC_VER
26 #pragma warning(disable:4668 4917)
27 #endif
29 // Support Windows 95 too
30 #undef WINVER
31 #define WINVER 0x0400
32 #define USE_APP_SHORTCUTS
33 // the systray icon is only available on windows
35 #include <unotools/moduleoptions.hxx>
36 #include <unotools/dynamicmenuoptions.hxx>
38 #include "shutdownicon.hxx"
39 #include "app.hrc"
40 #include <shlobj.h>
41 #include <objidl.h>
42 #include <osl/thread.h>
43 #include <systools/win32/qswin32.h>
44 #include <comphelper/sequenceashashmap.hxx>
46 #include <set>
48 using namespace ::rtl;
49 using namespace ::osl;
51 using ::com::sun::star::uno::Sequence;
52 using ::com::sun::star::beans::PropertyValue;
55 #define EXECUTER_WINDOWCLASS "SO Executer Class"
56 #define EXECUTER_WINDOWNAME "SO Executer Window"
59 #define ID_QUICKSTART 1
60 #define IDM_EXIT 2
61 #if defined(USE_APP_SHORTCUTS)
62 # define IDM_OPEN 3
63 # define IDM_WRITER 4
64 # define IDM_CALC 5
65 # define IDM_IMPRESS 6
66 # define IDM_DRAW 7
67 # define IDM_BASE 8
68 # define IDM_TEMPLATE 9
69 # define IDM_MATH 12
70 #endif
71 #define IDM_INSTALL 10
74 #define ICON_LO_DEFAULT 1
75 #define ICON_TEXT_DOCUMENT 2
76 #define ICON_SPREADSHEET_DOCUMENT 4
77 #define ICON_DRAWING_DOCUMENT 6
78 #define ICON_PRESENTATION_DOCUMENT 8
79 #define ICON_TEMPLATE 11
80 #define ICON_DATABASE_DOCUMENT 12
81 #define ICON_MATH_DOCUMENT 13
82 #define ICON_OPEN 5 // See index of open folder icon in shell32.dll
84 #define SFX_TASKBAR_NOTIFICATION WM_USER+1
86 static HWND aListenerWindow = NULL;
87 static HWND aExecuterWindow = NULL;
88 static HMENU popupMenu = NULL;
90 static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis);
91 static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis);
93 typedef struct tagMYITEM
95 OUString text;
96 OUString module;
97 UINT iconId;
98 } MYITEM;
100 // -------------------------------
102 static void addMenuItem( HMENU hMenu, UINT id, UINT iconId, const OUString& text, int& pos, int bOwnerdraw, const OUString& module )
104 MENUITEMINFOW mi;
105 memset( &mi, 0, sizeof( MENUITEMINFOW ) );
107 mi.cbSize = sizeof( MENUITEMINFOW );
108 if( id == static_cast<UINT>( -1 ) )
110 mi.fMask=MIIM_TYPE;
111 mi.fType=MFT_SEPARATOR;
113 else
115 if( bOwnerdraw )
117 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
118 mi.fType=MFT_OWNERDRAW;
119 mi.fState=MFS_ENABLED;
120 mi.wID = id;
122 MYITEM *pMyItem = new MYITEM;
123 pMyItem->text = text;
124 pMyItem->iconId = iconId;
125 pMyItem->module = module;
126 mi.dwItemData = (DWORD) pMyItem;
128 else
130 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
131 mi.fType=MFT_STRING;
132 mi.fState=MFS_ENABLED;
133 mi.wID = id;
134 mi.dwTypeData = (LPWSTR) text.getStr();
135 mi.cch = text.getLength();
138 #if defined(USE_APP_SHORTCUTS)
139 if ( IDM_TEMPLATE == id )
140 mi.fState |= MFS_DEFAULT;
141 #endif
144 InsertMenuItemW( hMenu, pos++, TRUE, &mi );
147 // -------------------------------
149 static HMENU createSystrayMenu( )
151 SvtModuleOptions aModuleOptions;
153 HMENU hMenu = CreatePopupMenu();
154 int pos=0;
156 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
157 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!");
159 if( !pShutdownIcon )
160 return NULL;
162 #if defined(USE_APP_SHORTCUTS)
163 // collect the URLs of the entries in the File/New menu
164 ::std::set< OUString > aFileNewAppsAvailable;
165 SvtDynamicMenuOptions aOpt;
166 Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU );
167 const OUString sURLKey( "URL" );
169 const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray();
170 const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength();
171 for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu )
173 ::comphelper::SequenceAsHashMap aEntryItems( *pNewMenu );
174 OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, OUString() ) );
175 if ( sURL.getLength() )
176 aFileNewAppsAvailable.insert( sURL );
179 // describe the menu entries for launching the applications
180 struct MenuEntryDescriptor
182 SvtModuleOptions::EModule eModuleIdentifier;
183 UINT nMenuItemID;
184 UINT nMenuIconID;
185 const char* pAsciiURLDescription;
186 } aMenuItems[] =
188 { SvtModuleOptions::E_SWRITER, IDM_WRITER, ICON_TEXT_DOCUMENT, WRITER_URL },
189 { SvtModuleOptions::E_SCALC, IDM_CALC, ICON_SPREADSHEET_DOCUMENT, CALC_URL },
190 { SvtModuleOptions::E_SIMPRESS, IDM_IMPRESS,ICON_PRESENTATION_DOCUMENT, IMPRESS_WIZARD_URL },
191 { SvtModuleOptions::E_SDRAW, IDM_DRAW, ICON_DRAWING_DOCUMENT, DRAW_URL },
192 { SvtModuleOptions::E_SDATABASE, IDM_BASE, ICON_DATABASE_DOCUMENT, BASE_URL },
193 { SvtModuleOptions::E_SMATH, IDM_MATH, ICON_MATH_DOCUMENT, MATH_URL },
196 OUString aEmpty;
198 // insert the menu entries for launching the applications
199 for ( size_t i = 0; i < sizeof( aMenuItems ) / sizeof( aMenuItems[0] ); ++i )
201 if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) )
202 // the complete application is not even installed
203 continue;
205 OUString sURL( OUString::createFromAscii( aMenuItems[i].pAsciiURLDescription ) );
207 if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() )
208 // the application is installed, but the entry has been configured to *not* appear in the File/New
209 // menu => also let not appear it in the quickstarter
210 continue;
212 addMenuItem( hMenu, aMenuItems[i].nMenuItemID, aMenuItems[i].nMenuIconID,
213 pShutdownIcon->GetUrlDescription( sURL ), pos, true, aEmpty );
218 // insert the remaining menu entries
219 addMenuItem( hMenu, IDM_TEMPLATE, ICON_TEMPLATE,
220 pShutdownIcon->GetResString( STR_QUICKSTART_FROMTEMPLATE ), pos, true, aEmpty);
221 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
222 addMenuItem( hMenu, IDM_OPEN, ICON_OPEN, pShutdownIcon->GetResString( STR_QUICKSTART_FILEOPEN ), pos, true, OUString("SHELL32"));
223 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
224 #endif
225 addMenuItem( hMenu, IDM_INSTALL,0, pShutdownIcon->GetResString( STR_QUICKSTART_PRELAUNCH ), pos, false, aEmpty );
226 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
227 addMenuItem( hMenu, IDM_EXIT, 0, pShutdownIcon->GetResString( STR_QUICKSTART_EXIT ), pos, false, aEmpty );
229 // indicate status of autostart folder
230 CheckMenuItem( hMenu, IDM_INSTALL, MF_BYCOMMAND | (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
232 return hMenu;
235 // -------------------------------
237 static void deleteSystrayMenu( HMENU hMenu )
239 if( !hMenu || !IsMenu( hMenu ))
240 return;
242 MENUITEMINFOW mi;
243 MYITEM *pMyItem;
244 int pos=0;
245 memset( &mi, 0, sizeof( mi ) );
246 mi.cbSize = sizeof( mi );
247 mi.fMask = MIIM_DATA;
249 while( GetMenuItemInfoW( hMenu, pos++, true, &mi ) )
251 pMyItem = (MYITEM*) mi.dwItemData;
252 if( pMyItem )
254 pMyItem->text = OUString();
255 delete pMyItem;
257 mi.fMask = MIIM_DATA;
261 // -------------------------------
263 static void addTaskbarIcon( HWND hWnd )
265 OUString strTip;
266 if( ShutdownIcon::getInstance() )
267 strTip = ShutdownIcon::getInstance()->GetResString( STR_QUICKSTART_TIP );
269 // add taskbar icon
270 NOTIFYICONDATAW nid;
271 nid.hIcon = (HICON)LoadImageA( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_LO_DEFAULT ),
272 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ),
273 LR_DEFAULTCOLOR | LR_SHARED );
275 wcsncpy( nid.szTip, reinterpret_cast<LPCWSTR>(strTip.getStr()), 64 );
277 nid.cbSize = sizeof(nid);
278 nid.hWnd = hWnd;
279 nid.uID = ID_QUICKSTART;
280 nid.uCallbackMessage = SFX_TASKBAR_NOTIFICATION;
281 nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON;
283 Shell_NotifyIconW(NIM_ADD, &nid);
286 // -------------------------------
288 LRESULT CALLBACK listenerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
290 static UINT s_uTaskbarRestart = 0;
291 static UINT s_uMsgKillTray = 0;
293 switch (uMsg)
295 case WM_NCCREATE:
296 return TRUE;
297 case WM_CREATE:
299 // request notfication when taskbar is recreated
300 // we then have to add our icon again
301 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
302 s_uMsgKillTray = RegisterWindowMessage( SHUTDOWN_QUICKSTART_MESSAGE );
304 // create the menu
305 if( !popupMenu )
306 if( (popupMenu = createSystrayMenu( )) == NULL )
307 return -1;
309 // and the icon
310 addTaskbarIcon( hWnd );
312 // disable shutdown
313 ShutdownIcon::getInstance()->SetVeto( true );
314 ShutdownIcon::getInstance()->addTerminateListener();
316 return 0;
318 case WM_MEASUREITEM:
319 OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT) lParam);
320 return TRUE;
322 case WM_DRAWITEM:
323 OnDrawItem(hWnd, (LPDRAWITEMSTRUCT) lParam);
324 return TRUE;
326 case SFX_TASKBAR_NOTIFICATION:
327 switch( lParam )
329 case WM_LBUTTONDBLCLK:
330 #if defined(USE_APP_SHORTCUTS)
331 PostMessage( aExecuterWindow, WM_COMMAND, IDM_TEMPLATE, (LPARAM)hWnd );
332 #endif
333 break;
335 case WM_RBUTTONDOWN:
337 POINT pt;
338 GetCursorPos(&pt);
339 SetForegroundWindow( hWnd );
341 // update status before showing menu, could have been changed from option page
342 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
344 EnableMenuItem( popupMenu, IDM_EXIT, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
345 #if defined(USE_APP_SHORTCUTS)
346 EnableMenuItem( popupMenu, IDM_OPEN, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
347 EnableMenuItem( popupMenu, IDM_TEMPLATE, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
348 #endif
349 int m = TrackPopupMenuEx( popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON,
350 pt.x, pt.y, hWnd, NULL );
351 PostMessage( hWnd, 0, 0, 0 );
352 switch( m )
354 #if defined(USE_APP_SHORTCUTS)
355 case IDM_OPEN:
356 case IDM_WRITER:
357 case IDM_CALC:
358 case IDM_IMPRESS:
359 case IDM_DRAW:
360 case IDM_TEMPLATE:
361 case IDM_BASE:
362 case IDM_MATH:
363 break;
364 #endif
365 case IDM_INSTALL:
366 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
367 break;
368 case IDM_EXIT:
369 // delete taskbar icon
370 NOTIFYICONDATAA nid;
371 nid.cbSize=sizeof(NOTIFYICONDATA);
372 nid.hWnd = hWnd;
373 nid.uID = ID_QUICKSTART;
374 Shell_NotifyIconA(NIM_DELETE, &nid);
375 break;
378 PostMessage( aExecuterWindow, WM_COMMAND, m, (LPARAM)hWnd );
380 break;
382 break;
383 case WM_DESTROY:
384 deleteSystrayMenu( popupMenu );
385 // We don't need the Systray Thread anymore
386 PostQuitMessage( 0 );
387 return DefWindowProc(hWnd, uMsg, wParam, lParam);
388 default:
389 if( uMsg == s_uTaskbarRestart )
391 // re-create taskbar icon
392 addTaskbarIcon( hWnd );
394 else if ( uMsg == s_uMsgKillTray )
396 // delete taskbar icon
397 NOTIFYICONDATAA nid;
398 nid.cbSize=sizeof(NOTIFYICONDATA);
399 nid.hWnd = hWnd;
400 nid.uID = ID_QUICKSTART;
401 Shell_NotifyIconA(NIM_DELETE, &nid);
403 PostMessage( aExecuterWindow, WM_COMMAND, IDM_EXIT, (LPARAM)hWnd );
405 else
406 return DefWindowProc(hWnd, uMsg, wParam, lParam);
408 return 0;
411 // -------------------------------
413 LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
415 switch (uMsg)
417 case WM_NCCREATE:
418 return TRUE;
419 case WM_CREATE:
420 return 0;
422 case WM_COMMAND:
423 switch( LOWORD(wParam) )
425 #if defined(USE_APP_SHORTCUTS)
426 case IDM_OPEN:
427 if ( !ShutdownIcon::bModalMode )
428 ShutdownIcon::FileOpen();
429 break;
430 case IDM_WRITER:
431 ShutdownIcon::OpenURL( OUString( WRITER_URL ), OUString( "_default" ) );
432 break;
433 case IDM_CALC:
434 ShutdownIcon::OpenURL( OUString( CALC_URL ), OUString( "_default" ) );
435 break;
436 case IDM_IMPRESS:
437 ShutdownIcon::OpenURL( OUString( IMPRESS_WIZARD_URL ), OUString( "_default" ) );
438 break;
439 case IDM_DRAW:
440 ShutdownIcon::OpenURL( OUString( DRAW_URL ), OUString( "_default" ) );
441 break;
442 case IDM_BASE:
443 ShutdownIcon::OpenURL( OUString( BASE_URL ), OUString( "_default" ) );
444 break;
445 case IDM_MATH:
446 ShutdownIcon::OpenURL( OUString( MATH_URL ), OUString( "_default" ) );
447 break;
448 case IDM_TEMPLATE:
449 if ( !ShutdownIcon::bModalMode )
450 ShutdownIcon::FromTemplate();
451 break;
452 #endif
453 case IDM_INSTALL:
454 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() );
455 break;
456 case IDM_EXIT:
457 // remove listener and
458 // terminate office if running in background
459 if ( !ShutdownIcon::bModalMode )
460 ShutdownIcon::terminateDesktop();
461 break;
463 break;
464 case WM_DESTROY:
465 default:
466 return DefWindowProc(hWnd, uMsg, wParam, lParam);
468 return 0;
471 // -------------------------------
474 DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ )
476 aListenerWindow = CreateWindowExA(0,
477 QUICKSTART_CLASSNAME, // registered class name
478 QUICKSTART_WINDOWNAME, // window name
479 0, // window style
480 CW_USEDEFAULT, // horizontal position of window
481 CW_USEDEFAULT, // vertical position of window
482 CW_USEDEFAULT, // window width
483 CW_USEDEFAULT, // window height
484 (HWND) NULL, // handle to parent or owner window
485 NULL, // menu handle or child identifier
486 (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance
487 NULL // window-creation data
490 MSG msg;
492 while ( GetMessage( &msg, NULL, 0, 0 ) )
494 TranslateMessage( &msg );
495 DispatchMessage( &msg );
498 return msg.wParam; // Exit code of WM_QUIT
501 // -------------------------------
503 void win32_init_sys_tray()
505 if ( ShutdownIcon::IsQuickstarterInstalled() )
507 WNDCLASSEXA listenerClass;
508 listenerClass.cbSize = sizeof(WNDCLASSEX);
509 listenerClass.style = 0;
510 listenerClass.lpfnWndProc = listenerWndProc;
511 listenerClass.cbClsExtra = 0;
512 listenerClass.cbWndExtra = 0;
513 listenerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL );
514 listenerClass.hIcon = NULL;
515 listenerClass.hCursor = NULL;
516 listenerClass.hbrBackground = NULL;
517 listenerClass.lpszMenuName = NULL;
518 listenerClass.lpszClassName = QUICKSTART_CLASSNAME;
519 listenerClass.hIconSm = NULL;
521 RegisterClassExA(&listenerClass);
523 WNDCLASSEXA executerClass;
524 executerClass.cbSize = sizeof(WNDCLASSEX);
525 executerClass.style = 0;
526 executerClass.lpfnWndProc = executerWndProc;
527 executerClass.cbClsExtra = 0;
528 executerClass.cbWndExtra = 0;
529 executerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL );
530 executerClass.hIcon = NULL;
531 executerClass.hCursor = NULL;
532 executerClass.hbrBackground = NULL;
533 executerClass.lpszMenuName = NULL;
534 executerClass.lpszClassName = EXECUTER_WINDOWCLASS;
535 executerClass.hIconSm = NULL;
537 RegisterClassExA( &executerClass );
539 aExecuterWindow = CreateWindowExA(0,
540 EXECUTER_WINDOWCLASS, // registered class name
541 EXECUTER_WINDOWNAME, // window name
542 0, // window style
543 CW_USEDEFAULT, // horizontal position of window
544 CW_USEDEFAULT, // vertical position of window
545 CW_USEDEFAULT, // window width
546 CW_USEDEFAULT, // window height
547 (HWND) NULL, // handle to parent or owner window
548 NULL, // menu handle or child identifier
549 (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance
550 NULL // window-creation data
553 DWORD dwThreadId;
554 CreateThread( NULL, 0, SystrayThread, NULL, 0, &dwThreadId );
558 // -------------------------------
560 void win32_shutdown_sys_tray()
562 if ( ShutdownIcon::IsQuickstarterInstalled() )
564 if( IsWindow( aListenerWindow ) )
566 DestroyWindow( aListenerWindow );
567 aListenerWindow = NULL;
568 DestroyWindow( aExecuterWindow );
569 aExecuterWindow = NULL;
571 UnregisterClassA( QUICKSTART_CLASSNAME, GetModuleHandle( NULL ) );
572 UnregisterClassA( EXECUTER_WINDOWCLASS, GetModuleHandle( NULL ) );
578 // -------------------------------
580 void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
582 MYITEM *pMyItem = (MYITEM *) lpmis->itemData;
583 HDC hdc = GetDC(hwnd);
584 SIZE size;
586 NONCLIENTMETRICS ncm;
587 memset(&ncm, 0, sizeof(ncm));
588 ncm.cbSize = sizeof(ncm);
590 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0);
592 // Assume every menu item can be default and printed bold
593 ncm.lfMenuFont.lfWeight = FW_BOLD;
595 HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
597 GetTextExtentPoint32W(hdc, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()),
598 pMyItem->text.getLength(), &size);
600 lpmis->itemWidth = size.cx + 4 + GetSystemMetrics( SM_CXSMICON );
601 lpmis->itemHeight = (size.cy > GetSystemMetrics( SM_CYSMICON )) ? size.cy : GetSystemMetrics( SM_CYSMICON );
602 lpmis->itemHeight += 4;
604 DeleteObject( SelectObject(hdc, hfntOld) );
605 ReleaseDC(hwnd, hdc);
608 void OnDrawItem(HWND /*hwnd*/, LPDRAWITEMSTRUCT lpdis)
610 MYITEM *pMyItem = (MYITEM *) lpdis->itemData;
611 COLORREF clrPrevText, clrPrevBkgnd;
612 HFONT hfntOld;
613 HBRUSH hbrOld;
614 int x, y;
615 BOOL fSelected = lpdis->itemState & ODS_SELECTED;
616 BOOL fDisabled = lpdis->itemState & (ODS_DISABLED | ODS_GRAYED);
618 // Set the appropriate foreground and background colors.
620 RECT aRect = lpdis->rcItem;
622 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
624 if ( fDisabled )
625 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) );
626 else
627 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
629 if ( fSelected )
630 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) );
631 else
632 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
634 hbrOld = (HBRUSH)SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) );
636 // Fill background
637 PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY);
639 int height = aRect.bottom-aRect.top;
641 x = aRect.left;
642 y = aRect.top;
644 int cx = GetSystemMetrics( SM_CXSMICON );
645 int cy = GetSystemMetrics( SM_CYSMICON );
646 HICON hIcon( 0 );
647 HMODULE hModule( GetModuleHandle( NULL ) );
649 if ( pMyItem->module.getLength() > 0 )
651 LPCWSTR pModuleName = reinterpret_cast<LPCWSTR>( pMyItem->module.getStr() );
652 hModule = GetModuleHandleW( pModuleName );
653 if ( hModule == NULL )
655 LoadLibraryW( pModuleName );
656 hModule = GetModuleHandleW( pModuleName );
660 hIcon = (HICON) LoadImageA( hModule, MAKEINTRESOURCE( pMyItem->iconId ),
661 IMAGE_ICON, cx, cy,
662 LR_DEFAULTCOLOR | LR_SHARED );
665 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
667 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) );
669 DeleteObject( hbrIcon );
671 x += cx + 4; // space for icon
672 aRect.left = x;
674 NONCLIENTMETRICS ncm;
675 memset(&ncm, 0, sizeof(ncm));
676 ncm.cbSize = sizeof(ncm);
678 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0);
680 // Print default menu entry with bold font
681 if ( lpdis->itemState & ODS_DEFAULT )
682 ncm.lfMenuFont.lfWeight = FW_BOLD;
684 hfntOld = (HFONT) SelectObject(lpdis->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
687 SIZE size;
688 GetTextExtentPointW( lpdis->hDC, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()), pMyItem->text.getLength(), &size );
690 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) );
692 // Restore the original font and colors.
693 DeleteObject( SelectObject( lpdis->hDC, hbrOld ) );
694 DeleteObject( SelectObject( lpdis->hDC, hfntOld) );
695 SetTextColor(lpdis->hDC, clrPrevText);
696 SetBkColor(lpdis->hDC, clrPrevBkgnd);
699 // -------------------------------
700 // code from setup2 project
701 // -------------------------------
703 void _SHFree( void *pv )
705 IMalloc *pMalloc;
706 if( NOERROR == SHGetMalloc(&pMalloc) )
708 pMalloc->Free( pv );
709 pMalloc->Release();
713 #define ALLOC(type, n) ((type *) HeapAlloc(GetProcessHeap(), 0, sizeof(type) * n ))
714 #define FREE(p) HeapFree(GetProcessHeap(), 0, p)
716 static OUString _SHGetSpecialFolder( int nFolderID )
719 LPITEMIDLIST pidl;
720 HRESULT hHdl = SHGetSpecialFolderLocation( NULL, nFolderID, &pidl );
721 OUString aFolder;
723 if( hHdl == NOERROR )
725 WCHAR *lpFolderA;
726 lpFolderA = ALLOC( WCHAR, 16000 );
728 SHGetPathFromIDListW( pidl, lpFolderA );
729 aFolder = OUString( reinterpret_cast<const sal_Unicode*>(lpFolderA) );
731 FREE( lpFolderA );
732 _SHFree( pidl );
734 return aFolder;
737 OUString ShutdownIcon::GetAutostartFolderNameW32()
739 return _SHGetSpecialFolder(CSIDL_STARTUP);
742 static HRESULT WINAPI SHCoCreateInstance( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv )
744 HRESULT hResult = E_NOTIMPL;
745 HMODULE hModShell = GetModuleHandle( "SHELL32" );
747 if ( hModShell != NULL )
749 typedef HRESULT (WINAPI *SHCoCreateInstance_PROC)( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknwon, REFIID iid, LPVOID *ppv );
751 SHCoCreateInstance_PROC lpfnSHCoCreateInstance = (SHCoCreateInstance_PROC)GetProcAddress( hModShell, MAKEINTRESOURCE(102) );
753 if ( lpfnSHCoCreateInstance )
754 hResult = lpfnSHCoCreateInstance( lpszReserved, clsid, pUnkUnknown, iid, ppv );
756 return hResult;
759 BOOL CreateShortcut( const OUString& rAbsObject, const OUString& rAbsObjectPath,
760 const OUString& rAbsShortcut, const OUString& rDescription, const OUString& rParameter )
762 HRESULT hres;
763 IShellLink* psl;
764 CLSID clsid_ShellLink = CLSID_ShellLink;
765 CLSID clsid_IShellLink = IID_IShellLink;
767 hres = CoCreateInstance( clsid_ShellLink, NULL, CLSCTX_INPROC_SERVER,
768 clsid_IShellLink, (void**)&psl );
769 if( FAILED(hres) )
770 hres = SHCoCreateInstance( NULL, clsid_ShellLink, NULL, clsid_IShellLink, (void**)&psl );
772 if( SUCCEEDED(hres) )
774 IPersistFile* ppf;
775 psl->SetPath( OUStringToOString(rAbsObject, osl_getThreadTextEncoding()).getStr() );
776 psl->SetWorkingDirectory( OUStringToOString(rAbsObjectPath, osl_getThreadTextEncoding()).getStr() );
777 psl->SetDescription( OUStringToOString(rDescription, osl_getThreadTextEncoding()).getStr() );
778 if( rParameter.getLength() )
779 psl->SetArguments( OUStringToOString(rParameter, osl_getThreadTextEncoding()).getStr() );
781 CLSID clsid_IPersistFile = IID_IPersistFile;
782 hres = psl->QueryInterface( clsid_IPersistFile, (void**)&ppf );
784 if( SUCCEEDED(hres) )
786 hres = ppf->Save( reinterpret_cast<LPCOLESTR>(rAbsShortcut.getStr()), TRUE );
787 ppf->Release();
788 } else return FALSE;
789 psl->Release();
790 } else return FALSE;
791 return TRUE;
794 // ------------------
795 // install/uninstall
797 static bool FileExistsW( LPCWSTR lpPath )
799 bool bExists = false;
800 WIN32_FIND_DATAW aFindData;
802 HANDLE hFind = FindFirstFileW( lpPath, &aFindData );
804 if ( INVALID_HANDLE_VALUE != hFind )
806 bExists = true;
807 FindClose( hFind );
810 return bExists;
813 bool ShutdownIcon::IsQuickstarterInstalled()
815 wchar_t aPath[_MAX_PATH];
816 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1);
818 OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) );
819 int i = aOfficepath.lastIndexOf((sal_Char) '\\');
820 if( i != -1 )
821 aOfficepath = aOfficepath.copy(0, i);
823 OUString quickstartExe(aOfficepath);
824 quickstartExe += "\\quickstart.exe";
826 return FileExistsW( reinterpret_cast<LPCWSTR>(quickstartExe.getStr()) );
829 void ShutdownIcon::EnableAutostartW32( const OUString &aShortcut )
831 wchar_t aPath[_MAX_PATH];
832 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1);
834 OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) );
835 int i = aOfficepath.lastIndexOf((sal_Char) '\\');
836 if( i != -1 )
837 aOfficepath = aOfficepath.copy(0, i);
839 OUString quickstartExe(aOfficepath);
840 quickstartExe += "\\quickstart.exe";
842 CreateShortcut( quickstartExe, aOfficepath, aShortcut, OUString(), OUString() );
845 #endif // WNT
848 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */