update dev300-m58
[ooovba.git] / sfx2 / source / appl / shutdowniconw32.cxx
blob53bbc380add8ac3a7e86650f42dcddb577b31656
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shutdowniconw32.cxx,v $
10 * $Revision: 1.48 $
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"
34 #ifdef WNT
36 // necessary to include system headers without warnings
37 #ifdef _MSC_VER
38 #pragma warning(disable:4668 4917)
39 #endif
41 // Support Windows 95 too
42 #undef WINVER
43 #define WINVER 0x0400
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"
53 #include "app.hrc"
54 #include <shlobj.h>
55 #include <objidl.h>
56 #include <stdio.h>
57 #include <io.h>
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>
67 #include <set>
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
82 #define IDM_EXIT 2
83 #if defined(USE_APP_SHORTCUTS)
84 # define IDM_OPEN 3
85 # define IDM_WRITER 4
86 # define IDM_CALC 5
87 # define IDM_IMPRESS 6
88 # define IDM_DRAW 7
89 # define IDM_BASE 8
90 # define IDM_TEMPLATE 9
91 # define IDM_MATH 12
92 #endif
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
115 #define ICON_OPEN 19
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
129 OUString text;
130 UINT iconId;
131 } MYITEM;
133 // -------------------------------
135 static bool isNT()
137 static bool bInitialized = false;
138 static bool bWnt = false;
140 if( !bInitialized )
142 bInitialized = true;
144 OSVERSIONINFO aVerInfo;
145 aVerInfo.dwOSVersionInfoSize = sizeof( aVerInfo );
146 if ( GetVersionEx( &aVerInfo ) )
148 if ( aVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
149 bWnt = true;
152 return bWnt;
156 // -------------------------------
158 static void addMenuItem( HMENU hMenu, UINT id, UINT iconId, const OUString& text, int& pos, int bOwnerdraw )
160 MENUITEMINFOW mi;
161 memset( &mi, 0, sizeof( MENUITEMINFOW ) );
163 mi.cbSize = sizeof( MENUITEMINFOW );
164 if( id == -1 )
166 mi.fMask=MIIM_TYPE;
167 mi.fType=MFT_SEPARATOR;
169 else
171 if( bOwnerdraw )
173 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
174 mi.fType=MFT_OWNERDRAW;
175 mi.fState=MFS_ENABLED;
176 mi.wID = id;
178 MYITEM *pMyItem = new MYITEM;
179 pMyItem->text = text;
180 pMyItem->iconId = iconId;
181 mi.dwItemData = (DWORD) pMyItem;
183 else
185 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA;
186 mi.fType=MFT_STRING;
187 mi.fState=MFS_ENABLED;
188 mi.wID = id;
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;
196 #endif
199 InsertMenuItemW( hMenu, pos++, TRUE, &mi );
202 // -------------------------------
204 static HMENU createSystrayMenu( )
206 SvtModuleOptions aModuleOptions;
208 HMENU hMenu = CreatePopupMenu();
209 int pos=0;
211 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance();
212 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!");
214 if( !pShutdownIcon )
215 return NULL;
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;
238 UINT nMenuItemID;
239 UINT nMenuIconID;
240 const char* pAsciiURLDescription;
241 } aMenuItems[] =
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
256 continue;
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
263 continue;
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 );
275 #endif
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) );
283 return hMenu;
286 // -------------------------------
288 static void deleteSystrayMenu( HMENU hMenu )
290 if( !hMenu || !IsMenu( hMenu ))
291 return;
293 MENUITEMINFOW mi;
294 MYITEM *pMyItem;
295 int pos=0;
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;
303 if( pMyItem )
305 pMyItem->text = OUString();
306 delete pMyItem;
308 mi.fMask = MIIM_DATA;
312 // -------------------------------
314 static void addTaskbarIcon( HWND hWnd )
316 OUString strTip;
317 if( ShutdownIcon::getInstance() )
318 strTip = ShutdownIcon::getInstance()->GetResString( STR_QUICKSTART_TIP );
320 // add taskbar icon
321 NOTIFYICONDATAA nid;
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);
330 nid.hWnd = hWnd;
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!");
346 if( !pShutdownIcon )
347 return;
349 if ( IsWindow( aListenerWindow ))
351 deleteSystrayMenu( popupMenu );
353 NOTIFYICONDATAA nid;
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;
369 switch (uMsg)
371 case WM_NCCREATE:
372 return TRUE;
373 case WM_CREATE:
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 );
380 // create the menu
381 if( !popupMenu )
382 if( (popupMenu = createSystrayMenu( )) == NULL )
383 return -1;
385 // and the icon
386 addTaskbarIcon( hWnd );
388 // disable shutdown
389 ShutdownIcon::getInstance()->SetVeto( true );
390 ShutdownIcon::getInstance()->addTerminateListener();
392 return 0;
394 case WM_MEASUREITEM:
395 OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT) lParam);
396 return TRUE;
398 case WM_DRAWITEM:
399 OnDrawItem(hWnd, (LPDRAWITEMSTRUCT) lParam);
400 return TRUE;
402 case SFX_TASKBAR_NOTIFICATION:
403 switch( lParam )
405 case WM_LBUTTONDBLCLK:
406 #if defined(USE_APP_SHORTCUTS)
407 PostMessage( aExecuterWindow, WM_COMMAND, IDM_TEMPLATE, (LPARAM)hWnd );
408 #endif
409 break;
411 case WM_RBUTTONDOWN:
413 POINT pt;
414 GetCursorPos(&pt);
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) );
424 #endif
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 );
429 switch( m )
431 #if defined(USE_APP_SHORTCUTS)
432 case IDM_OPEN:
433 case IDM_WRITER:
434 case IDM_CALC:
435 case IDM_IMPRESS:
436 case IDM_DRAW:
437 case IDM_TEMPLATE:
438 case IDM_BASE:
439 case IDM_MATH:
440 break;
441 #endif
442 case IDM_INSTALL:
443 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) );
444 break;
445 case IDM_EXIT:
446 // delete taskbar icon
447 NOTIFYICONDATAA nid;
448 nid.cbSize=sizeof(NOTIFYICONDATA);
449 nid.hWnd = hWnd;
450 nid.uID = ID_QUICKSTART;
451 Shell_NotifyIconA(NIM_DELETE, &nid);
452 break;
455 PostMessage( aExecuterWindow, WM_COMMAND, m, (LPARAM)hWnd );
457 break;
459 break;
460 case WM_DESTROY:
461 deleteSystrayMenu( popupMenu );
462 // We don't need the Systray Thread anymore
463 PostQuitMessage( 0 );
464 return DefWindowProc(hWnd, uMsg, wParam, lParam);
465 default:
466 if( uMsg == s_uTaskbarRestart )
468 // re-create taskbar icon
469 addTaskbarIcon( hWnd );
471 else if ( uMsg == s_uMsgKillTray )
473 // delete taskbar icon
474 NOTIFYICONDATAA nid;
475 nid.cbSize=sizeof(NOTIFYICONDATA);
476 nid.hWnd = hWnd;
477 nid.uID = ID_QUICKSTART;
478 Shell_NotifyIconA(NIM_DELETE, &nid);
480 PostMessage( aExecuterWindow, WM_COMMAND, IDM_EXIT, (LPARAM)hWnd );
482 else
483 return DefWindowProc(hWnd, uMsg, wParam, lParam);
485 return 0;
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")),
494 UNO_QUERY );
495 Sequence<NamedValue> args;
496 sal_Bool bResult = sal_False;
497 if (rOemJob.is())
499 Any aResult = rOemJob->execute(args);
500 aResult >>= bResult;
501 } else bResult = sal_True;
502 return bResult;
505 LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
507 switch (uMsg)
509 case WM_NCCREATE:
510 return TRUE;
511 case WM_CREATE:
512 return 0;
514 case WM_COMMAND:
515 switch( LOWORD(wParam) )
517 #if defined(USE_APP_SHORTCUTS)
518 case IDM_OPEN:
519 if ( !ShutdownIcon::bModalMode && checkOEM() )
520 ShutdownIcon::FileOpen();
521 break;
522 case IDM_WRITER:
523 if (checkOEM())
524 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( WRITER_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
525 break;
526 case IDM_CALC:
527 if (checkOEM())
528 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( CALC_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
529 break;
530 case IDM_IMPRESS:
531 if (checkOEM())
532 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( IMPRESS_WIZARD_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
533 break;
534 case IDM_DRAW:
535 if (checkOEM())
536 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( DRAW_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
537 break;
538 case IDM_BASE:
539 if (checkOEM())
540 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( BASE_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
541 break;
542 case IDM_MATH:
543 if (checkOEM())
544 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( MATH_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) );
545 break;
546 case IDM_TEMPLATE:
547 if ( !ShutdownIcon::bModalMode && checkOEM())
548 ShutdownIcon::FromTemplate();
549 break;
550 #endif
551 case IDM_INSTALL:
552 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() );
553 break;
554 case IDM_EXIT:
555 // remove listener and
556 // terminate office if running in background
557 if ( !ShutdownIcon::bModalMode )
558 ShutdownIcon::terminateDesktop();
559 break;
561 break;
562 case WM_DESTROY:
563 default:
564 return DefWindowProc(hWnd, uMsg, wParam, lParam);
566 return 0;
569 // -------------------------------
572 DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ )
574 aListenerWindow = CreateWindowExA(0,
575 QUICKSTART_CLASSNAME, // registered class name
576 QUICKSTART_WINDOWNAME, // window name
577 0, // window style
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
588 MSG msg;
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
640 0, // window style
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
651 DWORD dwThreadId;
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);
682 SIZE size;
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;
710 HFONT hfntOld;
711 HBRUSH hbrOld;
712 int x, y;
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) );
722 if ( fDisabled )
723 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) );
724 else
725 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) );
727 if ( fSelected )
728 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) );
729 else
730 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) );
732 hbrOld = (HBRUSH)SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) );
734 // Fill background
735 PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY);
737 int height = aRect.bottom-aRect.top;
739 x = aRect.left;
740 y = aRect.top;
742 int cx = GetSystemMetrics( SM_CXSMICON );
743 int cy = GetSystemMetrics( SM_CYSMICON );
744 HICON hIcon = (HICON) LoadImageA( GetModuleHandle( NULL ), MAKEINTRESOURCE( pMyItem->iconId ),
745 IMAGE_ICON, cx, cy,
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
757 aRect.left = x;
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 ));
772 SIZE size;
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 )
790 IMalloc *pMalloc;
791 if( NOERROR == SHGetMalloc(&pMalloc) )
793 pMalloc->Free( pv );
794 pMalloc->Release();
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 )
804 LPITEMIDLIST pidl;
805 HRESULT hHdl = SHGetSpecialFolderLocation( NULL, nFolderID, &pidl );
806 OUString aFolder;
808 if( hHdl == NOERROR )
810 WCHAR *lpFolderA;
811 lpFolderA = ALLOC( WCHAR, 16000 );
813 SHGetPathFromIDListW( pidl, lpFolderA );
814 aFolder = OUString( reinterpret_cast<const sal_Unicode*>(lpFolderA) );
816 FREE( lpFolderA );
817 _SHFree( pidl );
819 return aFolder;
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 );
841 return hResult;
844 BOOL CreateShortcut( const OUString& rAbsObject, const OUString& rAbsObjectPath,
845 const OUString& rAbsShortcut, const OUString& rDescription, const OUString& rParameter )
847 HRESULT hres;
848 IShellLink* psl;
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 );
854 if( FAILED(hres) )
855 hres = SHCoCreateInstance( NULL, clsid_ShellLink, NULL, clsid_IShellLink, (void**)&psl );
857 if( SUCCEEDED(hres) )
859 IPersistFile* ppf;
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 );
872 ppf->Release();
873 } else return FALSE;
874 psl->Release();
875 } else return FALSE;
876 return TRUE;
879 // ------------------
880 // install/uninstall
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 )
891 bExists = true;
892 FindClose( hFind );
895 return bExists;
898 bool ShutdownIcon::IsQuickstarterInstalled()
900 wchar_t aPath[_MAX_PATH];
901 if( isNT() )
903 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1);
905 else
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) '\\');
920 if( i != -1 )
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];
932 if( isNT() )
933 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1);
934 else
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) '\\');
949 if( i != -1 )
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() );
958 #endif // WNT