1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shutdowniconw32.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
36 // necessary to include system headers without warnings
38 #pragma warning(disable:4668 4917)
41 // Support Windows 95 too
44 #define USE_APP_SHORTCUTS
46 // the systray icon is only available on windows
48 #include <svtools/moduleoptions.hxx>
50 #include <svtools/dynamicmenuoptions.hxx>
52 #include "shutdownicon.hxx"
58 #include <osl/thread.h>
59 #include <setup_native/qswin32.h>
60 #include <comphelper/sequenceashashmap.hxx>
61 #include <comphelper/processfactory.hxx>
62 #include <com/sun/star/uno/Reference.h>
63 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
64 #include <com/sun/star/task/XJob.hpp>
65 #include <com/sun/star/beans/NamedValue.hpp>
69 using namespace ::rtl
;
70 using namespace ::com::sun::star::uno
;
71 using namespace ::com::sun::star::task
;
72 using namespace ::com::sun::star::lang
;
73 using namespace ::com::sun::star::beans
;
74 using namespace ::osl
;
77 #define EXECUTER_WINDOWCLASS "SO Executer Class"
78 #define EXECUTER_WINDOWNAME "SO Executer Window"
81 #define ID_QUICKSTART 1
83 #if defined(USE_APP_SHORTCUTS)
87 # define IDM_IMPRESS 6
90 # define IDM_TEMPLATE 9
93 #define IDM_INSTALL 10
94 #define IDM_UNINSTALL 11
97 #define ICON_SO_DEFAULT 1
98 #define ICON_TEXT_DOCUMENT 2
99 #define ICON_TEXT_TEMPLATE 3
100 #define ICON_SPREADSHEET_DOCUMENT 4
101 #define ICON_SPREADSHEET_TEMPLATE 5
102 #define ICON_DRAWING_DOCUMENT 6
103 #define ICON_DRAWING_TEMPLATE 7
104 #define ICON_PRESENTATION_DOCUMENT 8
105 #define ICON_PRESENTATION_TEMPLATE 9
106 #define ICON_PRESENTATION_COMPRESSED 10
107 #define ICON_GLOBAL_DOCUMENT 11
108 #define ICON_HTML_DOCUMENT 12
109 #define ICON_CHART_DOCUMENT 13
110 #define ICON_DATABASE_DOCUMENT 14
111 #define ICON_MATH_DOCUMENT 15
112 #define ICON_TEMPLATE 16
113 #define ICON_MACROLIBRARY 17
114 #define ICON_CONFIGURATION 18
116 #define ICON_SETUP 500
118 #define SFX_TASKBAR_NOTIFICATION WM_USER+1
120 static HWND aListenerWindow
= NULL
;
121 static HWND aExecuterWindow
= NULL
;
122 static HMENU popupMenu
= NULL
;
124 static void OnMeasureItem(HWND hwnd
, LPMEASUREITEMSTRUCT lpmis
);
125 static void OnDrawItem(HWND hwnd
, LPDRAWITEMSTRUCT lpdis
);
127 typedef struct tagMYITEM
133 // -------------------------------
137 static bool bInitialized
= false;
138 static bool bWnt
= false;
144 OSVERSIONINFO aVerInfo
;
145 aVerInfo
.dwOSVersionInfoSize
= sizeof( aVerInfo
);
146 if ( GetVersionEx( &aVerInfo
) )
148 if ( aVerInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
156 // -------------------------------
158 static void addMenuItem( HMENU hMenu
, UINT id
, UINT iconId
, const OUString
& text
, int& pos
, int bOwnerdraw
)
161 memset( &mi
, 0, sizeof( MENUITEMINFOW
) );
163 mi
.cbSize
= sizeof( MENUITEMINFOW
);
167 mi
.fType
=MFT_SEPARATOR
;
173 mi
.fMask
=MIIM_TYPE
| MIIM_STATE
| MIIM_ID
| MIIM_DATA
;
174 mi
.fType
=MFT_OWNERDRAW
;
175 mi
.fState
=MFS_ENABLED
;
178 MYITEM
*pMyItem
= new MYITEM
;
179 pMyItem
->text
= text
;
180 pMyItem
->iconId
= iconId
;
181 mi
.dwItemData
= (DWORD
) pMyItem
;
185 mi
.fMask
=MIIM_TYPE
| MIIM_STATE
| MIIM_ID
| MIIM_DATA
;
187 mi
.fState
=MFS_ENABLED
;
189 mi
.dwTypeData
= (LPWSTR
) text
.getStr();
190 mi
.cch
= text
.getLength();
193 #if defined(USE_APP_SHORTCUTS)
194 if ( IDM_TEMPLATE
== id
)
195 mi
.fState
|= MFS_DEFAULT
;
199 InsertMenuItemW( hMenu
, pos
++, TRUE
, &mi
);
202 // -------------------------------
204 static HMENU
createSystrayMenu( )
206 SvtModuleOptions aModuleOptions
;
208 HMENU hMenu
= CreatePopupMenu();
211 ShutdownIcon
*pShutdownIcon
= ShutdownIcon::getInstance();
212 OSL_ENSURE( pShutdownIcon
, "ShutdownIcon instance empty!");
217 #if defined(USE_APP_SHORTCUTS)
218 // collect the URLs of the entries in the File/New menu
219 ::std::set
< ::rtl::OUString
> aFileNewAppsAvailable
;
220 SvtDynamicMenuOptions aOpt
;
221 Sequence
< Sequence
< PropertyValue
> > aNewMenu
= aOpt
.GetMenu( E_NEWMENU
);
222 const ::rtl::OUString
sURLKey( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
224 const Sequence
< PropertyValue
>* pNewMenu
= aNewMenu
.getConstArray();
225 const Sequence
< PropertyValue
>* pNewMenuEnd
= aNewMenu
.getConstArray() + aNewMenu
.getLength();
226 for ( ; pNewMenu
!= pNewMenuEnd
; ++pNewMenu
)
228 ::comphelper::SequenceAsHashMap
aEntryItems( *pNewMenu
);
229 ::rtl::OUString
sURL( aEntryItems
.getUnpackedValueOrDefault( sURLKey
, ::rtl::OUString() ) );
230 if ( sURL
.getLength() )
231 aFileNewAppsAvailable
.insert( sURL
);
234 // describe the menu entries for launching the applications
235 struct MenuEntryDescriptor
237 SvtModuleOptions::EModule eModuleIdentifier
;
240 const char* pAsciiURLDescription
;
243 { SvtModuleOptions::E_SWRITER
, IDM_WRITER
, ICON_TEXT_DOCUMENT
, WRITER_URL
},
244 { SvtModuleOptions::E_SCALC
, IDM_CALC
, ICON_SPREADSHEET_DOCUMENT
, CALC_URL
},
245 { SvtModuleOptions::E_SIMPRESS
, IDM_IMPRESS
,ICON_PRESENTATION_DOCUMENT
, IMPRESS_WIZARD_URL
},
246 { SvtModuleOptions::E_SDRAW
, IDM_DRAW
, ICON_DRAWING_DOCUMENT
, DRAW_URL
},
247 { SvtModuleOptions::E_SDATABASE
, IDM_BASE
, ICON_DATABASE_DOCUMENT
, BASE_URL
},
248 { SvtModuleOptions::E_SMATH
, IDM_MATH
, ICON_MATH_DOCUMENT
, MATH_URL
},
251 // insert the menu entries for launching the applications
252 for ( size_t i
= 0; i
< sizeof( aMenuItems
) / sizeof( aMenuItems
[0] ); ++i
)
254 if ( !aModuleOptions
.IsModuleInstalled( aMenuItems
[i
].eModuleIdentifier
) )
255 // the complete application is not even installed
258 ::rtl::OUString
sURL( ::rtl::OUString::createFromAscii( aMenuItems
[i
].pAsciiURLDescription
) );
260 if ( aFileNewAppsAvailable
.find( sURL
) == aFileNewAppsAvailable
.end() )
261 // the application is installed, but the entry has been configured to *not* appear in the File/New
262 // menu => also let not appear it in the quickstarter
265 addMenuItem( hMenu
, aMenuItems
[i
].nMenuItemID
, aMenuItems
[i
].nMenuIconID
,
266 pShutdownIcon
->GetUrlDescription( sURL
), pos
, true );
269 // insert the remaining menu entries
270 addMenuItem( hMenu
, IDM_TEMPLATE
, ICON_TEMPLATE
,
271 pShutdownIcon
->GetResString( STR_QUICKSTART_FROMTEMPLATE
), pos
, true);
272 addMenuItem( hMenu
, static_cast< UINT
>( -1 ), 0, OUString(), pos
, false );
273 addMenuItem( hMenu
, IDM_OPEN
, ICON_OPEN
, pShutdownIcon
->GetResString( STR_QUICKSTART_FILEOPEN
), pos
, true );
274 addMenuItem( hMenu
, static_cast< UINT
>( -1 ), 0, OUString(), pos
, false );
276 addMenuItem( hMenu
, IDM_INSTALL
,0, pShutdownIcon
->GetResString( STR_QUICKSTART_PRELAUNCH
), pos
, false );
277 addMenuItem( hMenu
, static_cast< UINT
>( -1 ), 0, OUString(), pos
, false );
278 addMenuItem( hMenu
, IDM_EXIT
, 0, pShutdownIcon
->GetResString( STR_QUICKSTART_EXIT
), pos
, false );
280 // indicate status of autostart folder
281 CheckMenuItem( hMenu
, IDM_INSTALL
, MF_BYCOMMAND
| (ShutdownIcon::GetAutostart() ? MF_CHECKED
: MF_UNCHECKED
) );
286 // -------------------------------
288 static void deleteSystrayMenu( HMENU hMenu
)
290 if( !hMenu
|| !IsMenu( hMenu
))
296 memset( &mi
, 0, sizeof( mi
) );
297 mi
.cbSize
= sizeof( mi
);
298 mi
.fMask
= MIIM_DATA
;
300 while( GetMenuItemInfoW( hMenu
, pos
++, true, &mi
) )
302 pMyItem
= (MYITEM
*) mi
.dwItemData
;
305 pMyItem
->text
= OUString();
308 mi
.fMask
= MIIM_DATA
;
312 // -------------------------------
314 static void addTaskbarIcon( HWND hWnd
)
317 if( ShutdownIcon::getInstance() )
318 strTip
= ShutdownIcon::getInstance()->GetResString( STR_QUICKSTART_TIP
);
322 nid
.hIcon
= (HICON
)LoadImageA( GetModuleHandle( NULL
), MAKEINTRESOURCE( ICON_SO_DEFAULT
),
323 IMAGE_ICON
, GetSystemMetrics( SM_CXSMICON
), GetSystemMetrics( SM_CYSMICON
),
324 LR_DEFAULTCOLOR
| LR_SHARED
);
326 // better use unicode wrapper here ?
327 strncpy( nid
.szTip
, ( OUStringToOString(strTip
, osl_getThreadTextEncoding()).getStr() ), 64 );
329 nid
.cbSize
= sizeof(nid
);
331 nid
.uID
= ID_QUICKSTART
;
332 nid
.uCallbackMessage
= SFX_TASKBAR_NOTIFICATION
;
333 nid
.uFlags
= NIF_MESSAGE
|NIF_TIP
|NIF_ICON
;
335 Shell_NotifyIconA(NIM_ADD
, &nid
);
338 // -------------------------------
341 static void removeTaskbarIcon()
343 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
344 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!");
349 if ( IsWindow( aListenerWindow ))
351 deleteSystrayMenu( popupMenu );
354 nid.cbSize=sizeof(NOTIFYICONDATA);
355 nid.hWnd = aListenerWindow;
356 nid.uID = ID_QUICKSTART;
357 Shell_NotifyIconA(NIM_DELETE, &nid);
362 // -------------------------------
364 LRESULT CALLBACK
listenerWndProc( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
366 static UINT s_uTaskbarRestart
= 0;
367 static UINT s_uMsgKillTray
= 0;
375 // request notfication when taskbar is recreated
376 // we then have to add our icon again
377 s_uTaskbarRestart
= RegisterWindowMessage(TEXT("TaskbarCreated"));
378 s_uMsgKillTray
= RegisterWindowMessage( SHUTDOWN_QUICKSTART_MESSAGE
);
382 if( (popupMenu
= createSystrayMenu( )) == NULL
)
386 addTaskbarIcon( hWnd
);
389 ShutdownIcon::getInstance()->SetVeto( true );
390 ShutdownIcon::getInstance()->addTerminateListener();
395 OnMeasureItem(hWnd
, (LPMEASUREITEMSTRUCT
) lParam
);
399 OnDrawItem(hWnd
, (LPDRAWITEMSTRUCT
) lParam
);
402 case SFX_TASKBAR_NOTIFICATION
:
405 case WM_LBUTTONDBLCLK
:
406 #if defined(USE_APP_SHORTCUTS)
407 PostMessage( aExecuterWindow
, WM_COMMAND
, IDM_TEMPLATE
, (LPARAM
)hWnd
);
415 SetForegroundWindow( hWnd
);
417 // update status before showing menu, could have been changed from option page
418 CheckMenuItem( popupMenu
, IDM_INSTALL
, MF_BYCOMMAND
| (ShutdownIcon::GetAutostart() ? MF_CHECKED
: MF_UNCHECKED
) );
420 EnableMenuItem( popupMenu
, IDM_EXIT
, MF_BYCOMMAND
| (ShutdownIcon::bModalMode
? MF_GRAYED
: MF_ENABLED
) );
421 #if defined(USE_APP_SHORTCUTS)
422 EnableMenuItem( popupMenu
, IDM_OPEN
, MF_BYCOMMAND
| (ShutdownIcon::bModalMode
? MF_GRAYED
: MF_ENABLED
) );
423 EnableMenuItem( popupMenu
, IDM_TEMPLATE
, MF_BYCOMMAND
| (ShutdownIcon::bModalMode
? MF_GRAYED
: MF_ENABLED
) );
425 int m
= TrackPopupMenuEx( popupMenu
, TPM_RETURNCMD
|TPM_LEFTALIGN
|TPM_RIGHTBUTTON
,
426 pt
.x
, pt
.y
, hWnd
, NULL
);
427 // BUGFIX: See Q135788 (PRB: Menus for Notification Icons Don't Work Correctly)
428 PostMessage( hWnd
, NULL
, 0, 0 );
431 #if defined(USE_APP_SHORTCUTS)
443 CheckMenuItem( popupMenu
, IDM_INSTALL
, MF_BYCOMMAND
| (ShutdownIcon::GetAutostart() ? MF_CHECKED
: MF_UNCHECKED
) );
446 // delete taskbar icon
448 nid
.cbSize
=sizeof(NOTIFYICONDATA
);
450 nid
.uID
= ID_QUICKSTART
;
451 Shell_NotifyIconA(NIM_DELETE
, &nid
);
455 PostMessage( aExecuterWindow
, WM_COMMAND
, m
, (LPARAM
)hWnd
);
461 deleteSystrayMenu( popupMenu
);
462 // We don't need the Systray Thread anymore
463 PostQuitMessage( 0 );
464 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
466 if( uMsg
== s_uTaskbarRestart
)
468 // re-create taskbar icon
469 addTaskbarIcon( hWnd
);
471 else if ( uMsg
== s_uMsgKillTray
)
473 // delete taskbar icon
475 nid
.cbSize
=sizeof(NOTIFYICONDATA
);
477 nid
.uID
= ID_QUICKSTART
;
478 Shell_NotifyIconA(NIM_DELETE
, &nid
);
480 PostMessage( aExecuterWindow
, WM_COMMAND
, IDM_EXIT
, (LPARAM
)hWnd
);
483 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
488 // -------------------------------
490 static sal_Bool
checkOEM() {
491 Reference
<XMultiServiceFactory
> rFactory
= ::comphelper::getProcessServiceFactory();
492 Reference
<XJob
> rOemJob(rFactory
->createInstance(
493 OUString::createFromAscii("com.sun.star.office.OEMPreloadJob")),
495 Sequence
<NamedValue
> args
;
496 sal_Bool bResult
= sal_False
;
499 Any aResult
= rOemJob
->execute(args
);
501 } else bResult
= sal_True
;
505 LRESULT CALLBACK
executerWndProc( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
515 switch( LOWORD(wParam
) )
517 #if defined(USE_APP_SHORTCUTS)
519 if ( !ShutdownIcon::bModalMode
&& checkOEM() )
520 ShutdownIcon::FileOpen();
524 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( WRITER_URL
) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
528 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( CALC_URL
) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
532 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( IMPRESS_WIZARD_URL
) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
536 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( DRAW_URL
) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
540 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( BASE_URL
) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
544 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( MATH_URL
) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
547 if ( !ShutdownIcon::bModalMode
&& checkOEM())
548 ShutdownIcon::FromTemplate();
552 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() );
555 // remove listener and
556 // terminate office if running in background
557 if ( !ShutdownIcon::bModalMode
)
558 ShutdownIcon::terminateDesktop();
564 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
569 // -------------------------------
572 DWORD WINAPI
SystrayThread( LPVOID
/*lpParam*/ )
574 aListenerWindow
= CreateWindowExA(0,
575 QUICKSTART_CLASSNAME
, // registered class name
576 QUICKSTART_WINDOWNAME
, // window name
578 CW_USEDEFAULT
, // horizontal position of window
579 CW_USEDEFAULT
, // vertical position of window
580 CW_USEDEFAULT
, // window width
581 CW_USEDEFAULT
, // window height
582 (HWND
) NULL
, // handle to parent or owner window
583 NULL
, // menu handle or child identifier
584 (HINSTANCE
) GetModuleHandle( NULL
), // handle to application instance
585 NULL
// window-creation data
590 while ( GetMessage( &msg
, NULL
, 0, 0 ) )
592 TranslateMessage( &msg
);
593 DispatchMessage( &msg
);
596 return msg
.wParam
; // Exit code of WM_QUIT
599 // -------------------------------
601 void win32_init_sys_tray()
603 if ( ShutdownIcon::IsQuickstarterInstalled() )
605 WNDCLASSEXA listenerClass
;
606 listenerClass
.cbSize
= sizeof(WNDCLASSEX
);
607 listenerClass
.style
= 0;
608 listenerClass
.lpfnWndProc
= listenerWndProc
;
609 listenerClass
.cbClsExtra
= 0;
610 listenerClass
.cbWndExtra
= 0;
611 listenerClass
.hInstance
= (HINSTANCE
) GetModuleHandle( NULL
);
612 listenerClass
.hIcon
= NULL
;
613 listenerClass
.hCursor
= NULL
;
614 listenerClass
.hbrBackground
= NULL
;
615 listenerClass
.lpszMenuName
= NULL
;
616 listenerClass
.lpszClassName
= QUICKSTART_CLASSNAME
;
617 listenerClass
.hIconSm
= NULL
;
619 RegisterClassExA(&listenerClass
);
621 WNDCLASSEXA executerClass
;
622 executerClass
.cbSize
= sizeof(WNDCLASSEX
);
623 executerClass
.style
= 0;
624 executerClass
.lpfnWndProc
= executerWndProc
;
625 executerClass
.cbClsExtra
= 0;
626 executerClass
.cbWndExtra
= 0;
627 executerClass
.hInstance
= (HINSTANCE
) GetModuleHandle( NULL
);
628 executerClass
.hIcon
= NULL
;
629 executerClass
.hCursor
= NULL
;
630 executerClass
.hbrBackground
= NULL
;
631 executerClass
.lpszMenuName
= NULL
;
632 executerClass
.lpszClassName
= EXECUTER_WINDOWCLASS
;
633 executerClass
.hIconSm
= NULL
;
635 RegisterClassExA( &executerClass
);
637 aExecuterWindow
= CreateWindowExA(0,
638 EXECUTER_WINDOWCLASS
, // registered class name
639 EXECUTER_WINDOWNAME
, // window name
641 CW_USEDEFAULT
, // horizontal position of window
642 CW_USEDEFAULT
, // vertical position of window
643 CW_USEDEFAULT
, // window width
644 CW_USEDEFAULT
, // window height
645 (HWND
) NULL
, // handle to parent or owner window
646 NULL
, // menu handle or child identifier
647 (HINSTANCE
) GetModuleHandle( NULL
), // handle to application instance
648 NULL
// window-creation data
652 CreateThread( NULL
, 0, SystrayThread
, NULL
, 0, &dwThreadId
);
656 // -------------------------------
658 void win32_shutdown_sys_tray()
660 if ( ShutdownIcon::IsQuickstarterInstalled() )
662 if( IsWindow( aListenerWindow
) )
664 DestroyWindow( aListenerWindow
);
665 aListenerWindow
= NULL
;
666 DestroyWindow( aExecuterWindow
);
667 aExecuterWindow
= NULL
;
669 UnregisterClassA( QUICKSTART_CLASSNAME
, GetModuleHandle( NULL
) );
670 UnregisterClassA( EXECUTER_WINDOWCLASS
, GetModuleHandle( NULL
) );
676 // -------------------------------
678 void OnMeasureItem(HWND hwnd
, LPMEASUREITEMSTRUCT lpmis
)
680 MYITEM
*pMyItem
= (MYITEM
*) lpmis
->itemData
;
681 HDC hdc
= GetDC(hwnd
);
684 NONCLIENTMETRICS ncm
;
685 memset(&ncm
, 0, sizeof(ncm
));
686 ncm
.cbSize
= sizeof(ncm
);
688 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, (PVOID
) &ncm
, 0);
690 // Assume every menu item can be default and printed bold
691 ncm
.lfMenuFont
.lfWeight
= FW_BOLD
;
693 HFONT hfntOld
= (HFONT
) SelectObject(hdc
, (HFONT
) CreateFontIndirect( &ncm
.lfMenuFont
));
695 GetTextExtentPoint32W(hdc
, reinterpret_cast<LPCWSTR
>(pMyItem
->text
.getStr()),
696 pMyItem
->text
.getLength(), &size
);
698 lpmis
->itemWidth
= size
.cx
+ 4 + GetSystemMetrics( SM_CXSMICON
);
699 lpmis
->itemHeight
= (size
.cy
> GetSystemMetrics( SM_CYSMICON
)) ? size
.cy
: GetSystemMetrics( SM_CYSMICON
);
700 lpmis
->itemHeight
+= 4;
702 DeleteObject( SelectObject(hdc
, hfntOld
) );
703 ReleaseDC(hwnd
, hdc
);
706 void OnDrawItem(HWND
/*hwnd*/, LPDRAWITEMSTRUCT lpdis
)
708 MYITEM
*pMyItem
= (MYITEM
*) lpdis
->itemData
;
709 COLORREF clrPrevText
, clrPrevBkgnd
;
713 BOOL fSelected
= lpdis
->itemState
& ODS_SELECTED
;
714 BOOL fDisabled
= lpdis
->itemState
& (ODS_DISABLED
| ODS_GRAYED
);
716 // Set the appropriate foreground and background colors.
718 RECT aRect
= lpdis
->rcItem
;
720 clrPrevBkgnd
= SetBkColor( lpdis
->hDC
, GetSysColor(COLOR_MENU
) );
723 clrPrevText
= SetTextColor( lpdis
->hDC
, GetSysColor( COLOR_GRAYTEXT
) );
725 clrPrevText
= SetTextColor( lpdis
->hDC
, GetSysColor( fSelected
? COLOR_HIGHLIGHTTEXT
: COLOR_MENUTEXT
) );
728 clrPrevBkgnd
= SetBkColor( lpdis
->hDC
, GetSysColor(COLOR_HIGHLIGHT
) );
730 clrPrevBkgnd
= SetBkColor( lpdis
->hDC
, GetSysColor(COLOR_MENU
) );
732 hbrOld
= (HBRUSH
)SelectObject( lpdis
->hDC
, CreateSolidBrush( GetBkColor( lpdis
->hDC
) ) );
735 PatBlt(lpdis
->hDC
, aRect
.left
, aRect
.top
, aRect
.right
-aRect
.left
, aRect
.bottom
-aRect
.top
, PATCOPY
);
737 int height
= aRect
.bottom
-aRect
.top
;
742 int cx
= GetSystemMetrics( SM_CXSMICON
);
743 int cy
= GetSystemMetrics( SM_CYSMICON
);
744 HICON hIcon
= (HICON
) LoadImageA( GetModuleHandle( NULL
), MAKEINTRESOURCE( pMyItem
->iconId
),
746 LR_DEFAULTCOLOR
| LR_SHARED
);
748 // DrawIconEx( lpdis->hDC, x, y+(height-cy)/2, hIcon, cx, cy, 0, NULL, DI_NORMAL );
750 HBRUSH hbrIcon
= CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT
) );
752 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
) );
754 DeleteObject( hbrIcon
);
756 x
+= cx
+ 4; // space for icon
759 NONCLIENTMETRICS ncm
;
760 memset(&ncm
, 0, sizeof(ncm
));
761 ncm
.cbSize
= sizeof(ncm
);
763 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, (PVOID
) &ncm
, 0);
765 // Print default menu entry with bold font
766 if ( lpdis
->itemState
& ODS_DEFAULT
)
767 ncm
.lfMenuFont
.lfWeight
= FW_BOLD
;
769 hfntOld
= (HFONT
) SelectObject(lpdis
->hDC
, (HFONT
) CreateFontIndirect( &ncm
.lfMenuFont
));
773 GetTextExtentPointW( lpdis
->hDC
, reinterpret_cast<LPCWSTR
>(pMyItem
->text
.getStr()), pMyItem
->text
.getLength(), &size
);
775 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
) );
777 // Restore the original font and colors.
778 DeleteObject( SelectObject( lpdis
->hDC
, hbrOld
) );
779 DeleteObject( SelectObject( lpdis
->hDC
, hfntOld
) );
780 SetTextColor(lpdis
->hDC
, clrPrevText
);
781 SetBkColor(lpdis
->hDC
, clrPrevBkgnd
);
784 // -------------------------------
785 // code from setup2 project
786 // -------------------------------
788 void _SHFree( void *pv
)
791 if( NOERROR
== SHGetMalloc(&pMalloc
) )
798 #define ALLOC(type, n) ((type *) HeapAlloc(GetProcessHeap(), 0, sizeof(type) * n ))
799 #define FREE(p) HeapFree(GetProcessHeap(), 0, p)
801 static OUString
_SHGetSpecialFolder( int nFolderID
)
805 HRESULT hHdl
= SHGetSpecialFolderLocation( NULL
, nFolderID
, &pidl
);
808 if( hHdl
== NOERROR
)
811 lpFolderA
= ALLOC( WCHAR
, 16000 );
813 SHGetPathFromIDListW( pidl
, lpFolderA
);
814 aFolder
= OUString( reinterpret_cast<const sal_Unicode
*>(lpFolderA
) );
822 OUString
ShutdownIcon::GetAutostartFolderNameW32()
824 return _SHGetSpecialFolder(CSIDL_STARTUP
);
827 static HRESULT WINAPI
SHCoCreateInstance( LPVOID lpszReserved
, REFCLSID clsid
, LPUNKNOWN pUnkUnknown
, REFIID iid
, LPVOID
*ppv
)
829 HRESULT hResult
= E_NOTIMPL
;
830 HMODULE hModShell
= GetModuleHandle( "SHELL32" );
832 if ( hModShell
!= NULL
)
834 typedef HRESULT (WINAPI
*SHCoCreateInstance_PROC
)( LPVOID lpszReserved
, REFCLSID clsid
, LPUNKNOWN pUnkUnknwon
, REFIID iid
, LPVOID
*ppv
);
836 SHCoCreateInstance_PROC lpfnSHCoCreateInstance
= (SHCoCreateInstance_PROC
)GetProcAddress( hModShell
, MAKEINTRESOURCE(102) );
838 if ( lpfnSHCoCreateInstance
)
839 hResult
= lpfnSHCoCreateInstance( lpszReserved
, clsid
, pUnkUnknown
, iid
, ppv
);
844 BOOL
CreateShortcut( const OUString
& rAbsObject
, const OUString
& rAbsObjectPath
,
845 const OUString
& rAbsShortcut
, const OUString
& rDescription
, const OUString
& rParameter
)
849 CLSID clsid_ShellLink
= CLSID_ShellLink
;
850 CLSID clsid_IShellLink
= IID_IShellLink
;
852 hres
= CoCreateInstance( clsid_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
853 clsid_IShellLink
, (void**)&psl
);
855 hres
= SHCoCreateInstance( NULL
, clsid_ShellLink
, NULL
, clsid_IShellLink
, (void**)&psl
);
857 if( SUCCEEDED(hres
) )
860 psl
->SetPath( OUStringToOString(rAbsObject
, osl_getThreadTextEncoding()).getStr() );
861 psl
->SetWorkingDirectory( OUStringToOString(rAbsObjectPath
, osl_getThreadTextEncoding()).getStr() );
862 psl
->SetDescription( OUStringToOString(rDescription
, osl_getThreadTextEncoding()).getStr() );
863 if( rParameter
.getLength() )
864 psl
->SetArguments( OUStringToOString(rParameter
, osl_getThreadTextEncoding()).getStr() );
866 CLSID clsid_IPersistFile
= IID_IPersistFile
;
867 hres
= psl
->QueryInterface( clsid_IPersistFile
, (void**)&ppf
);
869 if( SUCCEEDED(hres
) )
871 hres
= ppf
->Save( reinterpret_cast<LPCOLESTR
>(rAbsShortcut
.getStr()), TRUE
);
879 // ------------------
882 static bool FileExistsW( LPCWSTR lpPath
)
884 bool bExists
= false;
885 WIN32_FIND_DATAW aFindData
;
887 HANDLE hFind
= FindFirstFileW( lpPath
, &aFindData
);
889 if ( INVALID_HANDLE_VALUE
!= hFind
)
898 bool ShutdownIcon::IsQuickstarterInstalled()
900 wchar_t aPath
[_MAX_PATH
];
903 GetModuleFileNameW( NULL
, aPath
, _MAX_PATH
-1);
907 char szPathA
[_MAX_PATH
];
908 GetModuleFileNameA( NULL
, szPathA
, _MAX_PATH
-1);
910 // calc the string wcstr len
911 int nNeededWStrBuffSize
= MultiByteToWideChar( CP_ACP
, 0, szPathA
, -1, NULL
, 0 );
913 // copy the string if necessary
914 if ( nNeededWStrBuffSize
> 0 )
915 MultiByteToWideChar( CP_ACP
, 0, szPathA
, -1, aPath
, nNeededWStrBuffSize
);
918 OUString
aOfficepath( reinterpret_cast<const sal_Unicode
*>(aPath
) );
919 int i
= aOfficepath
.lastIndexOf((sal_Char
) '\\');
921 aOfficepath
= aOfficepath
.copy(0, i
);
923 OUString
quickstartExe(aOfficepath
);
924 quickstartExe
+= OUString( RTL_CONSTASCII_USTRINGPARAM( "\\quickstart.exe" ) );
926 return FileExistsW( reinterpret_cast<LPCWSTR
>(quickstartExe
.getStr()) );
929 void ShutdownIcon::EnableAutostartW32( const rtl::OUString
&aShortcut
)
931 wchar_t aPath
[_MAX_PATH
];
933 GetModuleFileNameW( NULL
, aPath
, _MAX_PATH
-1);
936 char szPathA
[_MAX_PATH
];
937 GetModuleFileNameA( NULL
, szPathA
, _MAX_PATH
-1);
939 // calc the string wcstr len
940 int nNeededWStrBuffSize
= MultiByteToWideChar( CP_ACP
, 0, szPathA
, -1, NULL
, 0 );
942 // copy the string if necessary
943 if ( nNeededWStrBuffSize
> 0 )
944 MultiByteToWideChar( CP_ACP
, 0, szPathA
, -1, aPath
, nNeededWStrBuffSize
);
947 OUString
aOfficepath( reinterpret_cast<const sal_Unicode
*>(aPath
) );
948 int i
= aOfficepath
.lastIndexOf((sal_Char
) '\\');
950 aOfficepath
= aOfficepath
.copy(0, i
);
952 OUString
quickstartExe(aOfficepath
);
953 quickstartExe
+= OUString( RTL_CONSTASCII_USTRINGPARAM( "\\quickstart.exe" ) );
955 CreateShortcut( quickstartExe
, aOfficepath
, aShortcut
, OUString(), OUString() );