Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / appl / shutdowniconw32.cxx
blob28f783be28eb12dd76883985b6a42ee27ad443a6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <sal/macros.h>
31 #ifdef WNT
33 // necessary to include system headers without warnings
34 #ifdef _MSC_VER
35 #pragma warning(disable:4668 4917)
36 #endif
38 // Support Windows 95 too
39 #undef WINVER
40 #define WINVER 0x0400
41 #define USE_APP_SHORTCUTS
42 // the systray icon is only available on windows
44 #include <unotools/moduleoptions.hxx>
45 #include <unotools/dynamicmenuoptions.hxx>
47 #include "shutdownicon.hxx"
48 #include "app.hrc"
49 #include <shlobj.h>
50 #include <objidl.h>
51 #include <osl/thread.h>
52 #include <systools/win32/qswin32.h>
53 #include <comphelper/sequenceashashmap.hxx>
55 #include <set>
57 using namespace ::rtl;
58 using namespace ::osl;
60 using ::com::sun::star::uno::Sequence;
61 using ::com::sun::star::beans::PropertyValue;
64 #define EXECUTER_WINDOWCLASS "SO Executer Class"
65 #define EXECUTER_WINDOWNAME "SO Executer Window"
68 #define ID_QUICKSTART 1
69 #define IDM_EXIT 2
70 #if defined(USE_APP_SHORTCUTS)
71 # define IDM_OPEN 3
72 # define IDM_WRITER 4
73 # define IDM_CALC 5
74 # define IDM_IMPRESS 6
75 # define IDM_DRAW 7
76 # define IDM_BASE 8
77 # define IDM_TEMPLATE 9
78 # define IDM_MATH 12
79 #endif
80 #define IDM_INSTALL 10
81 #define IDM_UNINSTALL 11
84 #define ICON_LO_DEFAULT 1
85 #define ICON_TEXT_DOCUMENT 2
86 #define ICON_TEXT_TEMPLATE 3
87 #define ICON_SPREADSHEET_DOCUMENT 4
88 #define ICON_SPREADSHEET_TEMPLATE 5
89 #define ICON_DRAWING_DOCUMENT 6
90 #define ICON_DRAWING_TEMPLATE 7
91 #define ICON_PRESENTATION_DOCUMENT 8
92 #define ICON_PRESENTATION_TEMPLATE 9
93 #define ICON_MASTER_DOCUMENT 10
94 #define ICON_TEMPLATE 11
95 #define ICON_DATABASE_DOCUMENT 12
96 #define ICON_MATH_DOCUMENT 13
97 #define ICON_MACROLIBRARY 1
98 #define ICON_OPEN 5 // See index of open folder icon in shell32.dll
99 #define ICON_SETUP 500
101 #define SFX_TASKBAR_NOTIFICATION WM_USER+1
103 static HWND aListenerWindow = NULL;
104 static HWND aExecuterWindow = NULL;
105 static HMENU popupMenu = NULL;
107 static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis);
108 static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis);
110 typedef struct tagMYITEM
112 OUString text;
113 OUString module;
114 UINT iconId;
115 } MYITEM;
117 // -------------------------------
119 static void addMenuItem( HMENU hMenu, UINT id, UINT iconId, const OUString& text, int& pos, int bOwnerdraw, const OUString& module )
121 MENUITEMINFOW mi;
122 memset( &mi, 0, sizeof( MENUITEMINFOW ) );
124 mi.cbSize = sizeof( MENUITEMINFOW );
125 if( id == static_cast<UINT>( -1 ) )
127 mi.fMask=MIIM_TYPE;
128 mi.fType=MFT_SEPARATOR;
130 else
132 if( bOwnerdraw )
134 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
135 mi.fType=MFT_OWNERDRAW;
136 mi.fState=MFS_ENABLED;
137 mi.wID = id;
139 MYITEM *pMyItem = new MYITEM;
140 pMyItem->text = text;
141 pMyItem->iconId = iconId;
142 pMyItem->module = module;
143 mi.dwItemData = (DWORD) pMyItem;
145 else
147 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
148 mi.fType=MFT_STRING;
149 mi.fState=MFS_ENABLED;
150 mi.wID = id;
151 mi.dwTypeData = (LPWSTR) text.getStr();
152 mi.cch = text.getLength();
155 #if defined(USE_APP_SHORTCUTS)
156 if ( IDM_TEMPLATE == id )
157 mi.fState |= MFS_DEFAULT;
158 #endif
161 InsertMenuItemW( hMenu, pos++, TRUE, &mi );
164 // -------------------------------
166 static HMENU createSystrayMenu( )
168 SvtModuleOptions aModuleOptions;
170 HMENU hMenu = CreatePopupMenu();
171 int pos=0;
173 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
174 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!");
176 if( !pShutdownIcon )
177 return NULL;
179 #if defined(USE_APP_SHORTCUTS)
180 // collect the URLs of the entries in the File/New menu
181 ::std::set< ::rtl::OUString > aFileNewAppsAvailable;
182 SvtDynamicMenuOptions aOpt;
183 Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU );
184 const ::rtl::OUString sURLKey( "URL" );
186 const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray();
187 const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength();
188 for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu )
190 ::comphelper::SequenceAsHashMap aEntryItems( *pNewMenu );
191 ::rtl::OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, ::rtl::OUString() ) );
192 if ( sURL.getLength() )
193 aFileNewAppsAvailable.insert( sURL );
196 // describe the menu entries for launching the applications
197 struct MenuEntryDescriptor
199 SvtModuleOptions::EModule eModuleIdentifier;
200 UINT nMenuItemID;
201 UINT nMenuIconID;
202 const char* pAsciiURLDescription;
203 } aMenuItems[] =
205 { SvtModuleOptions::E_SWRITER, IDM_WRITER, ICON_TEXT_DOCUMENT, WRITER_URL },
206 { SvtModuleOptions::E_SCALC, IDM_CALC, ICON_SPREADSHEET_DOCUMENT, CALC_URL },
207 { SvtModuleOptions::E_SIMPRESS, IDM_IMPRESS,ICON_PRESENTATION_DOCUMENT, IMPRESS_WIZARD_URL },
208 { SvtModuleOptions::E_SDRAW, IDM_DRAW, ICON_DRAWING_DOCUMENT, DRAW_URL },
209 { SvtModuleOptions::E_SDATABASE, IDM_BASE, ICON_DATABASE_DOCUMENT, BASE_URL },
210 { SvtModuleOptions::E_SMATH, IDM_MATH, ICON_MATH_DOCUMENT, MATH_URL },
213 OUString aEmpty;
215 // insert the menu entries for launching the applications
216 for ( size_t i = 0; i < sizeof( aMenuItems ) / sizeof( aMenuItems[0] ); ++i )
218 if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) )
219 // the complete application is not even installed
220 continue;
222 ::rtl::OUString sURL( ::rtl::OUString::createFromAscii( aMenuItems[i].pAsciiURLDescription ) );
224 if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() )
225 // the application is installed, but the entry has been configured to *not* appear in the File/New
226 // menu => also let not appear it in the quickstarter
227 continue;
229 addMenuItem( hMenu, aMenuItems[i].nMenuItemID, aMenuItems[i].nMenuIconID,
230 pShutdownIcon->GetUrlDescription( sURL ), pos, true, aEmpty );
235 // insert the remaining menu entries
236 addMenuItem( hMenu, IDM_TEMPLATE, ICON_TEMPLATE,
237 pShutdownIcon->GetResString( STR_QUICKSTART_FROMTEMPLATE ), pos, true, aEmpty);
238 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
239 addMenuItem( hMenu, IDM_OPEN, ICON_OPEN, pShutdownIcon->GetResString( STR_QUICKSTART_FILEOPEN ), pos, true, OUString("SHELL32"));
240 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
241 #endif
242 addMenuItem( hMenu, IDM_INSTALL,0, pShutdownIcon->GetResString( STR_QUICKSTART_PRELAUNCH ), pos, false, aEmpty );
243 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty );
244 addMenuItem( hMenu, IDM_EXIT, 0, pShutdownIcon->GetResString( STR_QUICKSTART_EXIT ), pos, false, aEmpty );
246 // indicate status of autostart folder
247 CheckMenuItem( hMenu, IDM_INSTALL, MF_BYCOMMAND | (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
249 return hMenu;
252 // -------------------------------
254 static void deleteSystrayMenu( HMENU hMenu )
256 if( !hMenu || !IsMenu( hMenu ))
257 return;
259 MENUITEMINFOW mi;
260 MYITEM *pMyItem;
261 int pos=0;
262 memset( &mi, 0, sizeof( mi ) );
263 mi.cbSize = sizeof( mi );
264 mi.fMask = MIIM_DATA;
266 while( GetMenuItemInfoW( hMenu, pos++, true, &mi ) )
268 pMyItem = (MYITEM*) mi.dwItemData;
269 if( pMyItem )
271 pMyItem->text = OUString();
272 delete pMyItem;
274 mi.fMask = MIIM_DATA;
278 // -------------------------------
280 static void addTaskbarIcon( HWND hWnd )
282 OUString strTip;
283 if( ShutdownIcon::getInstance() )
284 strTip = ShutdownIcon::getInstance()->GetResString( STR_QUICKSTART_TIP );
286 // add taskbar icon
287 NOTIFYICONDATAW nid;
288 nid.hIcon = (HICON)LoadImageA( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_LO_DEFAULT ),
289 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ),
290 LR_DEFAULTCOLOR | LR_SHARED );
292 wcsncpy( nid.szTip, strTip.getStr(), 64 );
294 nid.cbSize = sizeof(nid);
295 nid.hWnd = hWnd;
296 nid.uID = ID_QUICKSTART;
297 nid.uCallbackMessage = SFX_TASKBAR_NOTIFICATION;
298 nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON;
300 Shell_NotifyIconW(NIM_ADD, &nid);
303 // -------------------------------
305 LRESULT CALLBACK listenerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
307 static UINT s_uTaskbarRestart = 0;
308 static UINT s_uMsgKillTray = 0;
310 switch (uMsg)
312 case WM_NCCREATE:
313 return TRUE;
314 case WM_CREATE:
316 // request notfication when taskbar is recreated
317 // we then have to add our icon again
318 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
319 s_uMsgKillTray = RegisterWindowMessage( SHUTDOWN_QUICKSTART_MESSAGE );
321 // create the menu
322 if( !popupMenu )
323 if( (popupMenu = createSystrayMenu( )) == NULL )
324 return -1;
326 // and the icon
327 addTaskbarIcon( hWnd );
329 // disable shutdown
330 ShutdownIcon::getInstance()->SetVeto( true );
331 ShutdownIcon::getInstance()->addTerminateListener();
333 return 0;
335 case WM_MEASUREITEM:
336 OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT) lParam);
337 return TRUE;
339 case WM_DRAWITEM:
340 OnDrawItem(hWnd, (LPDRAWITEMSTRUCT) lParam);
341 return TRUE;
343 case SFX_TASKBAR_NOTIFICATION:
344 switch( lParam )
346 case WM_LBUTTONDBLCLK:
347 #if defined(USE_APP_SHORTCUTS)
348 PostMessage( aExecuterWindow, WM_COMMAND, IDM_TEMPLATE, (LPARAM)hWnd );
349 #endif
350 break;
352 case WM_RBUTTONDOWN:
354 POINT pt;
355 GetCursorPos(&pt);
356 SetForegroundWindow( hWnd );
358 // update status before showing menu, could have been changed from option page
359 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
361 EnableMenuItem( popupMenu, IDM_EXIT, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
362 #if defined(USE_APP_SHORTCUTS)
363 EnableMenuItem( popupMenu, IDM_OPEN, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
364 EnableMenuItem( popupMenu, IDM_TEMPLATE, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) );
365 #endif
366 int m = TrackPopupMenuEx( popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON,
367 pt.x, pt.y, hWnd, NULL );
368 PostMessage( hWnd, 0, 0, 0 );
369 switch( m )
371 #if defined(USE_APP_SHORTCUTS)
372 case IDM_OPEN:
373 case IDM_WRITER:
374 case IDM_CALC:
375 case IDM_IMPRESS:
376 case IDM_DRAW:
377 case IDM_TEMPLATE:
378 case IDM_BASE:
379 case IDM_MATH:
380 break;
381 #endif
382 case IDM_INSTALL:
383 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
384 break;
385 case IDM_EXIT:
386 // delete taskbar icon
387 NOTIFYICONDATAA nid;
388 nid.cbSize=sizeof(NOTIFYICONDATA);
389 nid.hWnd = hWnd;
390 nid.uID = ID_QUICKSTART;
391 Shell_NotifyIconA(NIM_DELETE, &nid);
392 break;
395 PostMessage( aExecuterWindow, WM_COMMAND, m, (LPARAM)hWnd );
397 break;
399 break;
400 case WM_DESTROY:
401 deleteSystrayMenu( popupMenu );
402 // We don't need the Systray Thread anymore
403 PostQuitMessage( 0 );
404 return DefWindowProc(hWnd, uMsg, wParam, lParam);
405 default:
406 if( uMsg == s_uTaskbarRestart )
408 // re-create taskbar icon
409 addTaskbarIcon( hWnd );
411 else if ( uMsg == s_uMsgKillTray )
413 // delete taskbar icon
414 NOTIFYICONDATAA nid;
415 nid.cbSize=sizeof(NOTIFYICONDATA);
416 nid.hWnd = hWnd;
417 nid.uID = ID_QUICKSTART;
418 Shell_NotifyIconA(NIM_DELETE, &nid);
420 PostMessage( aExecuterWindow, WM_COMMAND, IDM_EXIT, (LPARAM)hWnd );
422 else
423 return DefWindowProc(hWnd, uMsg, wParam, lParam);
425 return 0;
428 // -------------------------------
430 LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
432 switch (uMsg)
434 case WM_NCCREATE:
435 return TRUE;
436 case WM_CREATE:
437 return 0;
439 case WM_COMMAND:
440 switch( LOWORD(wParam) )
442 #if defined(USE_APP_SHORTCUTS)
443 case IDM_OPEN:
444 if ( !ShutdownIcon::bModalMode )
445 ShutdownIcon::FileOpen();
446 break;
447 case IDM_WRITER:
448 ShutdownIcon::OpenURL( OUString( WRITER_URL ), OUString( "_default" ) );
449 break;
450 case IDM_CALC:
451 ShutdownIcon::OpenURL( OUString( CALC_URL ), OUString( "_default" ) );
452 break;
453 case IDM_IMPRESS:
454 ShutdownIcon::OpenURL( OUString( IMPRESS_WIZARD_URL ), OUString( "_default" ) );
455 break;
456 case IDM_DRAW:
457 ShutdownIcon::OpenURL( OUString( DRAW_URL ), OUString( "_default" ) );
458 break;
459 case IDM_BASE:
460 ShutdownIcon::OpenURL( OUString( BASE_URL ), OUString( "_default" ) );
461 break;
462 case IDM_MATH:
463 ShutdownIcon::OpenURL( OUString( MATH_URL ), OUString( "_default" ) );
464 break;
465 case IDM_TEMPLATE:
466 if ( !ShutdownIcon::bModalMode )
467 ShutdownIcon::FromTemplate();
468 break;
469 #endif
470 case IDM_INSTALL:
471 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() );
472 break;
473 case IDM_EXIT:
474 // remove listener and
475 // terminate office if running in background
476 if ( !ShutdownIcon::bModalMode )
477 ShutdownIcon::terminateDesktop();
478 break;
480 break;
481 case WM_DESTROY:
482 default:
483 return DefWindowProc(hWnd, uMsg, wParam, lParam);
485 return 0;
488 // -------------------------------
491 DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ )
493 aListenerWindow = CreateWindowExA(0,
494 QUICKSTART_CLASSNAME, // registered class name
495 QUICKSTART_WINDOWNAME, // window name
496 0, // window style
497 CW_USEDEFAULT, // horizontal position of window
498 CW_USEDEFAULT, // vertical position of window
499 CW_USEDEFAULT, // window width
500 CW_USEDEFAULT, // window height
501 (HWND) NULL, // handle to parent or owner window
502 NULL, // menu handle or child identifier
503 (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance
504 NULL // window-creation data
507 MSG msg;
509 while ( GetMessage( &msg, NULL, 0, 0 ) )
511 TranslateMessage( &msg );
512 DispatchMessage( &msg );
515 return msg.wParam; // Exit code of WM_QUIT
518 // -------------------------------
520 void win32_init_sys_tray()
522 if ( ShutdownIcon::IsQuickstarterInstalled() )
524 WNDCLASSEXA listenerClass;
525 listenerClass.cbSize = sizeof(WNDCLASSEX);
526 listenerClass.style = 0;
527 listenerClass.lpfnWndProc = listenerWndProc;
528 listenerClass.cbClsExtra = 0;
529 listenerClass.cbWndExtra = 0;
530 listenerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL );
531 listenerClass.hIcon = NULL;
532 listenerClass.hCursor = NULL;
533 listenerClass.hbrBackground = NULL;
534 listenerClass.lpszMenuName = NULL;
535 listenerClass.lpszClassName = QUICKSTART_CLASSNAME;
536 listenerClass.hIconSm = NULL;
538 RegisterClassExA(&listenerClass);
540 WNDCLASSEXA executerClass;
541 executerClass.cbSize = sizeof(WNDCLASSEX);
542 executerClass.style = 0;
543 executerClass.lpfnWndProc = executerWndProc;
544 executerClass.cbClsExtra = 0;
545 executerClass.cbWndExtra = 0;
546 executerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL );
547 executerClass.hIcon = NULL;
548 executerClass.hCursor = NULL;
549 executerClass.hbrBackground = NULL;
550 executerClass.lpszMenuName = NULL;
551 executerClass.lpszClassName = EXECUTER_WINDOWCLASS;
552 executerClass.hIconSm = NULL;
554 RegisterClassExA( &executerClass );
556 aExecuterWindow = CreateWindowExA(0,
557 EXECUTER_WINDOWCLASS, // registered class name
558 EXECUTER_WINDOWNAME, // window name
559 0, // window style
560 CW_USEDEFAULT, // horizontal position of window
561 CW_USEDEFAULT, // vertical position of window
562 CW_USEDEFAULT, // window width
563 CW_USEDEFAULT, // window height
564 (HWND) NULL, // handle to parent or owner window
565 NULL, // menu handle or child identifier
566 (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance
567 NULL // window-creation data
570 DWORD dwThreadId;
571 CreateThread( NULL, 0, SystrayThread, NULL, 0, &dwThreadId );
575 // -------------------------------
577 void win32_shutdown_sys_tray()
579 if ( ShutdownIcon::IsQuickstarterInstalled() )
581 if( IsWindow( aListenerWindow ) )
583 DestroyWindow( aListenerWindow );
584 aListenerWindow = NULL;
585 DestroyWindow( aExecuterWindow );
586 aExecuterWindow = NULL;
588 UnregisterClassA( QUICKSTART_CLASSNAME, GetModuleHandle( NULL ) );
589 UnregisterClassA( EXECUTER_WINDOWCLASS, GetModuleHandle( NULL ) );
595 // -------------------------------
597 void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
599 MYITEM *pMyItem = (MYITEM *) lpmis->itemData;
600 HDC hdc = GetDC(hwnd);
601 SIZE size;
603 NONCLIENTMETRICS ncm;
604 memset(&ncm, 0, sizeof(ncm));
605 ncm.cbSize = sizeof(ncm);
607 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0);
609 // Assume every menu item can be default and printed bold
610 ncm.lfMenuFont.lfWeight = FW_BOLD;
612 HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
614 GetTextExtentPoint32W(hdc, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()),
615 pMyItem->text.getLength(), &size);
617 lpmis->itemWidth = size.cx + 4 + GetSystemMetrics( SM_CXSMICON );
618 lpmis->itemHeight = (size.cy > GetSystemMetrics( SM_CYSMICON )) ? size.cy : GetSystemMetrics( SM_CYSMICON );
619 lpmis->itemHeight += 4;
621 DeleteObject( SelectObject(hdc, hfntOld) );
622 ReleaseDC(hwnd, hdc);
625 void OnDrawItem(HWND /*hwnd*/, LPDRAWITEMSTRUCT lpdis)
627 MYITEM *pMyItem = (MYITEM *) lpdis->itemData;
628 COLORREF clrPrevText, clrPrevBkgnd;
629 HFONT hfntOld;
630 HBRUSH hbrOld;
631 int x, y;
632 BOOL fSelected = lpdis->itemState & ODS_SELECTED;
633 BOOL fDisabled = lpdis->itemState & (ODS_DISABLED | ODS_GRAYED);
635 // Set the appropriate foreground and background colors.
637 RECT aRect = lpdis->rcItem;
639 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
641 if ( fDisabled )
642 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) );
643 else
644 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
646 if ( fSelected )
647 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) );
648 else
649 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
651 hbrOld = (HBRUSH)SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) );
653 // Fill background
654 PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY);
656 int height = aRect.bottom-aRect.top;
658 x = aRect.left;
659 y = aRect.top;
661 int cx = GetSystemMetrics( SM_CXSMICON );
662 int cy = GetSystemMetrics( SM_CYSMICON );
663 HICON hIcon( 0 );
664 HMODULE hModule( GetModuleHandle( NULL ) );
666 if ( pMyItem->module.getLength() > 0 )
668 LPCWSTR pModuleName = reinterpret_cast<LPCWSTR>( pMyItem->module.getStr() );
669 hModule = GetModuleHandleW( pModuleName );
670 if ( hModule == NULL )
672 LoadLibraryW( pModuleName );
673 hModule = GetModuleHandleW( pModuleName );
677 hIcon = (HICON) LoadImageA( hModule, MAKEINTRESOURCE( pMyItem->iconId ),
678 IMAGE_ICON, cx, cy,
679 LR_DEFAULTCOLOR | LR_SHARED );
682 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) );
684 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) );
686 DeleteObject( hbrIcon );
688 x += cx + 4; // space for icon
689 aRect.left = x;
691 NONCLIENTMETRICS ncm;
692 memset(&ncm, 0, sizeof(ncm));
693 ncm.cbSize = sizeof(ncm);
695 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0);
697 // Print default menu entry with bold font
698 if ( lpdis->itemState & ODS_DEFAULT )
699 ncm.lfMenuFont.lfWeight = FW_BOLD;
701 hfntOld = (HFONT) SelectObject(lpdis->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont ));
704 SIZE size;
705 GetTextExtentPointW( lpdis->hDC, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()), pMyItem->text.getLength(), &size );
707 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) );
709 // Restore the original font and colors.
710 DeleteObject( SelectObject( lpdis->hDC, hbrOld ) );
711 DeleteObject( SelectObject( lpdis->hDC, hfntOld) );
712 SetTextColor(lpdis->hDC, clrPrevText);
713 SetBkColor(lpdis->hDC, clrPrevBkgnd);
716 // -------------------------------
717 // code from setup2 project
718 // -------------------------------
720 void _SHFree( void *pv )
722 IMalloc *pMalloc;
723 if( NOERROR == SHGetMalloc(&pMalloc) )
725 pMalloc->Free( pv );
726 pMalloc->Release();
730 #define ALLOC(type, n) ((type *) HeapAlloc(GetProcessHeap(), 0, sizeof(type) * n ))
731 #define FREE(p) HeapFree(GetProcessHeap(), 0, p)
733 static OUString _SHGetSpecialFolder( int nFolderID )
736 LPITEMIDLIST pidl;
737 HRESULT hHdl = SHGetSpecialFolderLocation( NULL, nFolderID, &pidl );
738 OUString aFolder;
740 if( hHdl == NOERROR )
742 WCHAR *lpFolderA;
743 lpFolderA = ALLOC( WCHAR, 16000 );
745 SHGetPathFromIDListW( pidl, lpFolderA );
746 aFolder = OUString( reinterpret_cast<const sal_Unicode*>(lpFolderA) );
748 FREE( lpFolderA );
749 _SHFree( pidl );
751 return aFolder;
754 OUString ShutdownIcon::GetAutostartFolderNameW32()
756 return _SHGetSpecialFolder(CSIDL_STARTUP);
759 static HRESULT WINAPI SHCoCreateInstance( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv )
761 HRESULT hResult = E_NOTIMPL;
762 HMODULE hModShell = GetModuleHandle( "SHELL32" );
764 if ( hModShell != NULL )
766 typedef HRESULT (WINAPI *SHCoCreateInstance_PROC)( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknwon, REFIID iid, LPVOID *ppv );
768 SHCoCreateInstance_PROC lpfnSHCoCreateInstance = (SHCoCreateInstance_PROC)GetProcAddress( hModShell, MAKEINTRESOURCE(102) );
770 if ( lpfnSHCoCreateInstance )
771 hResult = lpfnSHCoCreateInstance( lpszReserved, clsid, pUnkUnknown, iid, ppv );
773 return hResult;
776 BOOL CreateShortcut( const OUString& rAbsObject, const OUString& rAbsObjectPath,
777 const OUString& rAbsShortcut, const OUString& rDescription, const OUString& rParameter )
779 HRESULT hres;
780 IShellLink* psl;
781 CLSID clsid_ShellLink = CLSID_ShellLink;
782 CLSID clsid_IShellLink = IID_IShellLink;
784 hres = CoCreateInstance( clsid_ShellLink, NULL, CLSCTX_INPROC_SERVER,
785 clsid_IShellLink, (void**)&psl );
786 if( FAILED(hres) )
787 hres = SHCoCreateInstance( NULL, clsid_ShellLink, NULL, clsid_IShellLink, (void**)&psl );
789 if( SUCCEEDED(hres) )
791 IPersistFile* ppf;
792 psl->SetPath( OUStringToOString(rAbsObject, osl_getThreadTextEncoding()).getStr() );
793 psl->SetWorkingDirectory( OUStringToOString(rAbsObjectPath, osl_getThreadTextEncoding()).getStr() );
794 psl->SetDescription( OUStringToOString(rDescription, osl_getThreadTextEncoding()).getStr() );
795 if( rParameter.getLength() )
796 psl->SetArguments( OUStringToOString(rParameter, osl_getThreadTextEncoding()).getStr() );
798 CLSID clsid_IPersistFile = IID_IPersistFile;
799 hres = psl->QueryInterface( clsid_IPersistFile, (void**)&ppf );
801 if( SUCCEEDED(hres) )
803 hres = ppf->Save( reinterpret_cast<LPCOLESTR>(rAbsShortcut.getStr()), TRUE );
804 ppf->Release();
805 } else return FALSE;
806 psl->Release();
807 } else return FALSE;
808 return TRUE;
811 // ------------------
812 // install/uninstall
814 static bool FileExistsW( LPCWSTR lpPath )
816 bool bExists = false;
817 WIN32_FIND_DATAW aFindData;
819 HANDLE hFind = FindFirstFileW( lpPath, &aFindData );
821 if ( INVALID_HANDLE_VALUE != hFind )
823 bExists = true;
824 FindClose( hFind );
827 return bExists;
830 bool ShutdownIcon::IsQuickstarterInstalled()
832 wchar_t aPath[_MAX_PATH];
833 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1);
835 OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) );
836 int i = aOfficepath.lastIndexOf((sal_Char) '\\');
837 if( i != -1 )
838 aOfficepath = aOfficepath.copy(0, i);
840 OUString quickstartExe(aOfficepath);
841 quickstartExe += OUString( "\\quickstart.exe" );
843 return FileExistsW( reinterpret_cast<LPCWSTR>(quickstartExe.getStr()) );
846 void ShutdownIcon::EnableAutostartW32( const rtl::OUString &aShortcut )
848 wchar_t aPath[_MAX_PATH];
849 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1);
851 OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) );
852 int i = aOfficepath.lastIndexOf((sal_Char) '\\');
853 if( i != -1 )
854 aOfficepath = aOfficepath.copy(0, i);
856 OUString quickstartExe(aOfficepath);
857 quickstartExe += OUString( "\\quickstart.exe" );
859 CreateShortcut( quickstartExe, aOfficepath, aShortcut, OUString(), OUString() );
862 #endif // WNT
865 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */