1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sfx2.hxx" 30 31 #ifdef WNT 32 33 // necessary to include system headers without warnings 34 #ifdef _MSC_VER 35 #pragma warning(disable:4668 4917) 36 #endif 37 38 // Support Windows 95 too 39 #undef WINVER 40 #define WINVER 0x0400 41 #define USE_APP_SHORTCUTS 42 // 43 // the systray icon is only available on windows 44 // 45 46 #include <unotools/moduleoptions.hxx> 47 #include <unotools/dynamicmenuoptions.hxx> 48 49 #include "shutdownicon.hxx" 50 #include "app.hrc" 51 #include <shlobj.h> 52 #include <objidl.h> 53 #include <stdio.h> 54 #include <io.h> 55 #include <osl/thread.h> 56 #include <setup_native/qswin32.h> 57 #include <comphelper/sequenceashashmap.hxx> 58 #include <comphelper/processfactory.hxx> 59 #include <com/sun/star/uno/Reference.h> 60 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 61 #include <com/sun/star/task/XJob.hpp> 62 #include <com/sun/star/beans/NamedValue.hpp> 63 64 #include <set> 65 66 using namespace ::rtl; 67 using namespace ::com::sun::star::uno; 68 using namespace ::com::sun::star::task; 69 using namespace ::com::sun::star::lang; 70 using namespace ::com::sun::star::beans; 71 using namespace ::osl; 72 73 74 #define EXECUTER_WINDOWCLASS "SO Executer Class" 75 #define EXECUTER_WINDOWNAME "SO Executer Window" 76 77 78 #define ID_QUICKSTART 1 79 #define IDM_EXIT 2 80 #if defined(USE_APP_SHORTCUTS) 81 # define IDM_OPEN 3 82 # define IDM_WRITER 4 83 # define IDM_CALC 5 84 # define IDM_IMPRESS 6 85 # define IDM_DRAW 7 86 # define IDM_BASE 8 87 # define IDM_TEMPLATE 9 88 # define IDM_MATH 12 89 #endif 90 #define IDM_INSTALL 10 91 #define IDM_UNINSTALL 11 92 93 94 #define ICON_SO_DEFAULT 1 95 #define ICON_TEXT_DOCUMENT 2 96 #define ICON_TEXT_TEMPLATE 3 97 #define ICON_SPREADSHEET_DOCUMENT 4 98 #define ICON_SPREADSHEET_TEMPLATE 5 99 #define ICON_DRAWING_DOCUMENT 6 100 #define ICON_DRAWING_TEMPLATE 7 101 #define ICON_PRESENTATION_DOCUMENT 8 102 #define ICON_PRESENTATION_TEMPLATE 9 103 #define ICON_PRESENTATION_COMPRESSED 10 104 #define ICON_GLOBAL_DOCUMENT 11 105 #define ICON_HTML_DOCUMENT 12 106 #define ICON_CHART_DOCUMENT 13 107 #define ICON_DATABASE_DOCUMENT 14 108 #define ICON_MATH_DOCUMENT 15 109 #define ICON_TEMPLATE 16 110 #define ICON_MACROLIBRARY 17 111 #define ICON_CONFIGURATION 18 112 #define ICON_OPEN 5 // See index of open folder icon in shell32.dll 113 #define ICON_SETUP 500 114 115 #define SFX_TASKBAR_NOTIFICATION WM_USER+1 116 117 static HWND aListenerWindow = NULL; 118 static HWND aExecuterWindow = NULL; 119 static HMENU popupMenu = NULL; 120 121 static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis); 122 static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis); 123 124 typedef struct tagMYITEM 125 { 126 OUString text; 127 OUString module; 128 UINT iconId; 129 } MYITEM; 130 131 // ------------------------------- 132 133 static bool isNT() 134 { 135 static bool bInitialized = false; 136 static bool bWnt = false; 137 138 if( !bInitialized ) 139 { 140 bInitialized = true; 141 142 OSVERSIONINFO aVerInfo; 143 aVerInfo.dwOSVersionInfoSize = sizeof( aVerInfo ); 144 if ( GetVersionEx( &aVerInfo ) ) 145 { 146 if ( aVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) 147 bWnt = true; 148 } 149 } 150 return bWnt; 151 } 152 153 154 // ------------------------------- 155 156 static void addMenuItem( HMENU hMenu, UINT id, UINT iconId, const OUString& text, int& pos, int bOwnerdraw, const OUString& module ) 157 { 158 MENUITEMINFOW mi; 159 memset( &mi, 0, sizeof( MENUITEMINFOW ) ); 160 161 mi.cbSize = sizeof( MENUITEMINFOW ); 162 if( id == -1 ) 163 { 164 mi.fMask=MIIM_TYPE; 165 mi.fType=MFT_SEPARATOR; 166 } 167 else 168 { 169 if( bOwnerdraw ) 170 { 171 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA; 172 mi.fType=MFT_OWNERDRAW; 173 mi.fState=MFS_ENABLED; 174 mi.wID = id; 175 176 MYITEM *pMyItem = new MYITEM; 177 pMyItem->text = text; 178 pMyItem->iconId = iconId; 179 pMyItem->module = module; 180 mi.dwItemData = (DWORD) pMyItem; 181 } 182 else 183 { 184 mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA; 185 mi.fType=MFT_STRING; 186 mi.fState=MFS_ENABLED; 187 mi.wID = id; 188 mi.dwTypeData = (LPWSTR) text.getStr(); 189 mi.cch = text.getLength(); 190 } 191 192 #if defined(USE_APP_SHORTCUTS) 193 if ( IDM_TEMPLATE == id ) 194 mi.fState |= MFS_DEFAULT; 195 #endif 196 } 197 198 InsertMenuItemW( hMenu, pos++, TRUE, &mi ); 199 } 200 201 // ------------------------------- 202 203 static HMENU createSystrayMenu( ) 204 { 205 SvtModuleOptions aModuleOptions; 206 207 HMENU hMenu = CreatePopupMenu(); 208 int pos=0; 209 210 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance(); 211 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!"); 212 213 if( !pShutdownIcon ) 214 return NULL; 215 216 #if defined(USE_APP_SHORTCUTS) 217 // collect the URLs of the entries in the File/New menu 218 ::std::set< ::rtl::OUString > aFileNewAppsAvailable; 219 SvtDynamicMenuOptions aOpt; 220 Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU ); 221 const ::rtl::OUString sURLKey( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); 222 223 const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray(); 224 const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength(); 225 for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu ) 226 { 227 ::comphelper::SequenceAsHashMap aEntryItems( *pNewMenu ); 228 ::rtl::OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, ::rtl::OUString() ) ); 229 if ( sURL.getLength() ) 230 aFileNewAppsAvailable.insert( sURL ); 231 } 232 233 // describe the menu entries for launching the applications 234 struct MenuEntryDescriptor 235 { 236 SvtModuleOptions::EModule eModuleIdentifier; 237 UINT nMenuItemID; 238 UINT nMenuIconID; 239 const char* pAsciiURLDescription; 240 } aMenuItems[] = 241 { 242 { SvtModuleOptions::E_SWRITER, IDM_WRITER, ICON_TEXT_DOCUMENT, WRITER_URL }, 243 { SvtModuleOptions::E_SCALC, IDM_CALC, ICON_SPREADSHEET_DOCUMENT, CALC_URL }, 244 { SvtModuleOptions::E_SIMPRESS, IDM_IMPRESS,ICON_PRESENTATION_DOCUMENT, IMPRESS_WIZARD_URL }, 245 { SvtModuleOptions::E_SDRAW, IDM_DRAW, ICON_DRAWING_DOCUMENT, DRAW_URL }, 246 { SvtModuleOptions::E_SDATABASE, IDM_BASE, ICON_DATABASE_DOCUMENT, BASE_URL }, 247 { SvtModuleOptions::E_SMATH, IDM_MATH, ICON_MATH_DOCUMENT, MATH_URL }, 248 }; 249 250 OUString aEmpty; 251 252 // insert the menu entries for launching the applications 253 for ( size_t i = 0; i < sizeof( aMenuItems ) / sizeof( aMenuItems[0] ); ++i ) 254 { 255 if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) ) 256 // the complete application is not even installed 257 continue; 258 259 ::rtl::OUString sURL( ::rtl::OUString::createFromAscii( aMenuItems[i].pAsciiURLDescription ) ); 260 261 if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() ) 262 // the application is installed, but the entry has been configured to *not* appear in the File/New 263 // menu => also let not appear it in the quickstarter 264 continue; 265 266 addMenuItem( hMenu, aMenuItems[i].nMenuItemID, aMenuItems[i].nMenuIconID, 267 pShutdownIcon->GetUrlDescription( sURL ), pos, true, aEmpty ); 268 } 269 270 271 272 // insert the remaining menu entries 273 addMenuItem( hMenu, IDM_TEMPLATE, ICON_TEMPLATE, 274 pShutdownIcon->GetResString( STR_QUICKSTART_FROMTEMPLATE ), pos, true, aEmpty); 275 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty ); 276 addMenuItem( hMenu, IDM_OPEN, ICON_OPEN, pShutdownIcon->GetResString( STR_QUICKSTART_FILEOPEN ), pos, true, OUString::createFromAscii( "SHELL32" )); 277 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty ); 278 #endif 279 addMenuItem( hMenu, IDM_INSTALL,0, pShutdownIcon->GetResString( STR_QUICKSTART_PRELAUNCH ), pos, false, aEmpty ); 280 addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty ); 281 addMenuItem( hMenu, IDM_EXIT, 0, pShutdownIcon->GetResString( STR_QUICKSTART_EXIT ), pos, false, aEmpty ); 282 283 // indicate status of autostart folder 284 CheckMenuItem( hMenu, IDM_INSTALL, MF_BYCOMMAND | (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) ); 285 286 return hMenu; 287 } 288 289 // ------------------------------- 290 291 static void deleteSystrayMenu( HMENU hMenu ) 292 { 293 if( !hMenu || !IsMenu( hMenu )) 294 return; 295 296 MENUITEMINFOW mi; 297 MYITEM *pMyItem; 298 int pos=0; 299 memset( &mi, 0, sizeof( mi ) ); 300 mi.cbSize = sizeof( mi ); 301 mi.fMask = MIIM_DATA; 302 303 while( GetMenuItemInfoW( hMenu, pos++, true, &mi ) ) 304 { 305 pMyItem = (MYITEM*) mi.dwItemData; 306 if( pMyItem ) 307 { 308 pMyItem->text = OUString(); 309 delete pMyItem; 310 } 311 mi.fMask = MIIM_DATA; 312 } 313 } 314 315 // ------------------------------- 316 317 static void addTaskbarIcon( HWND hWnd ) 318 { 319 OUString strTip; 320 if( ShutdownIcon::getInstance() ) 321 strTip = ShutdownIcon::getInstance()->GetResString( STR_QUICKSTART_TIP ); 322 323 // add taskbar icon 324 NOTIFYICONDATAA nid; 325 nid.hIcon = (HICON)LoadImageA( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_SO_DEFAULT ), 326 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), 327 LR_DEFAULTCOLOR | LR_SHARED ); 328 329 // better use unicode wrapper here ? 330 strncpy( nid.szTip, ( OUStringToOString(strTip, osl_getThreadTextEncoding()).getStr() ), 64 ); 331 332 nid.cbSize = sizeof(nid); 333 nid.hWnd = hWnd; 334 nid.uID = ID_QUICKSTART; 335 nid.uCallbackMessage = SFX_TASKBAR_NOTIFICATION; 336 nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON; 337 338 Shell_NotifyIconA(NIM_ADD, &nid); 339 } 340 341 // ------------------------------- 342 343 /* 344 static void removeTaskbarIcon() 345 { 346 ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance(); 347 OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!"); 348 349 if( !pShutdownIcon ) 350 return; 351 352 if ( IsWindow( aListenerWindow )) 353 { 354 deleteSystrayMenu( popupMenu ); 355 356 NOTIFYICONDATAA nid; 357 nid.cbSize=sizeof(NOTIFYICONDATA); 358 nid.hWnd = aListenerWindow; 359 nid.uID = ID_QUICKSTART; 360 Shell_NotifyIconA(NIM_DELETE, &nid); 361 } 362 } 363 */ 364 365 // ------------------------------- 366 367 LRESULT CALLBACK listenerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 368 { 369 static UINT s_uTaskbarRestart = 0; 370 static UINT s_uMsgKillTray = 0; 371 372 switch (uMsg) 373 { 374 case WM_NCCREATE: 375 return TRUE; 376 case WM_CREATE: 377 { 378 // request notfication when taskbar is recreated 379 // we then have to add our icon again 380 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); 381 s_uMsgKillTray = RegisterWindowMessage( SHUTDOWN_QUICKSTART_MESSAGE ); 382 383 // create the menu 384 if( !popupMenu ) 385 if( (popupMenu = createSystrayMenu( )) == NULL ) 386 return -1; 387 388 // and the icon 389 addTaskbarIcon( hWnd ); 390 391 // disable shutdown 392 ShutdownIcon::getInstance()->SetVeto( true ); 393 ShutdownIcon::getInstance()->addTerminateListener(); 394 } 395 return 0; 396 397 case WM_MEASUREITEM: 398 OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT) lParam); 399 return TRUE; 400 401 case WM_DRAWITEM: 402 OnDrawItem(hWnd, (LPDRAWITEMSTRUCT) lParam); 403 return TRUE; 404 405 case SFX_TASKBAR_NOTIFICATION: 406 switch( lParam ) 407 { 408 case WM_LBUTTONDBLCLK: 409 #if defined(USE_APP_SHORTCUTS) 410 PostMessage( aExecuterWindow, WM_COMMAND, IDM_TEMPLATE, (LPARAM)hWnd ); 411 #endif 412 break; 413 414 case WM_RBUTTONDOWN: 415 { 416 POINT pt; 417 GetCursorPos(&pt); 418 SetForegroundWindow( hWnd ); 419 420 // update status before showing menu, could have been changed from option page 421 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) ); 422 423 EnableMenuItem( popupMenu, IDM_EXIT, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) ); 424 #if defined(USE_APP_SHORTCUTS) 425 EnableMenuItem( popupMenu, IDM_OPEN, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) ); 426 EnableMenuItem( popupMenu, IDM_TEMPLATE, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) ); 427 #endif 428 int m = TrackPopupMenuEx( popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON, 429 pt.x, pt.y, hWnd, NULL ); 430 // BUGFIX: See Q135788 (PRB: Menus for Notification Icons Don't Work Correctly) 431 PostMessage( hWnd, NULL, 0, 0 ); 432 switch( m ) 433 { 434 #if defined(USE_APP_SHORTCUTS) 435 case IDM_OPEN: 436 case IDM_WRITER: 437 case IDM_CALC: 438 case IDM_IMPRESS: 439 case IDM_DRAW: 440 case IDM_TEMPLATE: 441 case IDM_BASE: 442 case IDM_MATH: 443 break; 444 #endif 445 case IDM_INSTALL: 446 CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) ); 447 break; 448 case IDM_EXIT: 449 // delete taskbar icon 450 NOTIFYICONDATAA nid; 451 nid.cbSize=sizeof(NOTIFYICONDATA); 452 nid.hWnd = hWnd; 453 nid.uID = ID_QUICKSTART; 454 Shell_NotifyIconA(NIM_DELETE, &nid); 455 break; 456 } 457 458 PostMessage( aExecuterWindow, WM_COMMAND, m, (LPARAM)hWnd ); 459 } 460 break; 461 } 462 break; 463 case WM_DESTROY: 464 deleteSystrayMenu( popupMenu ); 465 // We don't need the Systray Thread anymore 466 PostQuitMessage( 0 ); 467 return DefWindowProc(hWnd, uMsg, wParam, lParam); 468 default: 469 if( uMsg == s_uTaskbarRestart ) 470 { 471 // re-create taskbar icon 472 addTaskbarIcon( hWnd ); 473 } 474 else if ( uMsg == s_uMsgKillTray ) 475 { 476 // delete taskbar icon 477 NOTIFYICONDATAA nid; 478 nid.cbSize=sizeof(NOTIFYICONDATA); 479 nid.hWnd = hWnd; 480 nid.uID = ID_QUICKSTART; 481 Shell_NotifyIconA(NIM_DELETE, &nid); 482 483 PostMessage( aExecuterWindow, WM_COMMAND, IDM_EXIT, (LPARAM)hWnd ); 484 } 485 else 486 return DefWindowProc(hWnd, uMsg, wParam, lParam); 487 } 488 return 0; 489 } 490 491 // ------------------------------- 492 493 static sal_Bool checkOEM() { 494 Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory(); 495 Reference<XJob> rOemJob(rFactory->createInstance( 496 OUString::createFromAscii("com.sun.star.office.OEMPreloadJob")), 497 UNO_QUERY ); 498 Sequence<NamedValue> args; 499 sal_Bool bResult = sal_False; 500 if (rOemJob.is()) 501 { 502 Any aResult = rOemJob->execute(args); 503 aResult >>= bResult; 504 } else bResult = sal_True; 505 return bResult; 506 } 507 508 LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 509 { 510 switch (uMsg) 511 { 512 case WM_NCCREATE: 513 return TRUE; 514 case WM_CREATE: 515 return 0; 516 517 case WM_COMMAND: 518 switch( LOWORD(wParam) ) 519 { 520 #if defined(USE_APP_SHORTCUTS) 521 case IDM_OPEN: 522 if ( !ShutdownIcon::bModalMode && checkOEM() ) 523 ShutdownIcon::FileOpen(); 524 break; 525 case IDM_WRITER: 526 if (checkOEM()) 527 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( WRITER_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 528 break; 529 case IDM_CALC: 530 if (checkOEM()) 531 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( CALC_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 532 break; 533 case IDM_IMPRESS: 534 if (checkOEM()) 535 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( IMPRESS_WIZARD_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 536 break; 537 case IDM_DRAW: 538 if (checkOEM()) 539 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( DRAW_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 540 break; 541 case IDM_BASE: 542 if (checkOEM()) 543 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( BASE_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 544 break; 545 case IDM_MATH: 546 if (checkOEM()) 547 ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( MATH_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); 548 break; 549 case IDM_TEMPLATE: 550 if ( !ShutdownIcon::bModalMode && checkOEM()) 551 ShutdownIcon::FromTemplate(); 552 break; 553 #endif 554 case IDM_INSTALL: 555 ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() ); 556 break; 557 case IDM_EXIT: 558 // remove listener and 559 // terminate office if running in background 560 if ( !ShutdownIcon::bModalMode ) 561 ShutdownIcon::terminateDesktop(); 562 break; 563 } 564 break; 565 case WM_DESTROY: 566 default: 567 return DefWindowProc(hWnd, uMsg, wParam, lParam); 568 } 569 return 0; 570 } 571 572 // ------------------------------- 573 574 575 DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ ) 576 { 577 aListenerWindow = CreateWindowExA(0, 578 QUICKSTART_CLASSNAME, // registered class name 579 QUICKSTART_WINDOWNAME, // window name 580 0, // window style 581 CW_USEDEFAULT, // horizontal position of window 582 CW_USEDEFAULT, // vertical position of window 583 CW_USEDEFAULT, // window width 584 CW_USEDEFAULT, // window height 585 (HWND) NULL, // handle to parent or owner window 586 NULL, // menu handle or child identifier 587 (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance 588 NULL // window-creation data 589 ); 590 591 MSG msg; 592 593 while ( GetMessage( &msg, NULL, 0, 0 ) ) 594 { 595 TranslateMessage( &msg ); 596 DispatchMessage( &msg ); 597 } 598 599 return msg.wParam; // Exit code of WM_QUIT 600 } 601 602 // ------------------------------- 603 604 void win32_init_sys_tray() 605 { 606 if ( ShutdownIcon::IsQuickstarterInstalled() ) 607 { 608 WNDCLASSEXA listenerClass; 609 listenerClass.cbSize = sizeof(WNDCLASSEX); 610 listenerClass.style = 0; 611 listenerClass.lpfnWndProc = listenerWndProc; 612 listenerClass.cbClsExtra = 0; 613 listenerClass.cbWndExtra = 0; 614 listenerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL ); 615 listenerClass.hIcon = NULL; 616 listenerClass.hCursor = NULL; 617 listenerClass.hbrBackground = NULL; 618 listenerClass.lpszMenuName = NULL; 619 listenerClass.lpszClassName = QUICKSTART_CLASSNAME; 620 listenerClass.hIconSm = NULL; 621 622 RegisterClassExA(&listenerClass); 623 624 WNDCLASSEXA executerClass; 625 executerClass.cbSize = sizeof(WNDCLASSEX); 626 executerClass.style = 0; 627 executerClass.lpfnWndProc = executerWndProc; 628 executerClass.cbClsExtra = 0; 629 executerClass.cbWndExtra = 0; 630 executerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL ); 631 executerClass.hIcon = NULL; 632 executerClass.hCursor = NULL; 633 executerClass.hbrBackground = NULL; 634 executerClass.lpszMenuName = NULL; 635 executerClass.lpszClassName = EXECUTER_WINDOWCLASS; 636 executerClass.hIconSm = NULL; 637 638 RegisterClassExA( &executerClass ); 639 640 aExecuterWindow = CreateWindowExA(0, 641 EXECUTER_WINDOWCLASS, // registered class name 642 EXECUTER_WINDOWNAME, // window name 643 0, // window style 644 CW_USEDEFAULT, // horizontal position of window 645 CW_USEDEFAULT, // vertical position of window 646 CW_USEDEFAULT, // window width 647 CW_USEDEFAULT, // window height 648 (HWND) NULL, // handle to parent or owner window 649 NULL, // menu handle or child identifier 650 (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance 651 NULL // window-creation data 652 ); 653 654 DWORD dwThreadId; 655 CreateThread( NULL, 0, SystrayThread, NULL, 0, &dwThreadId ); 656 } 657 } 658 659 // ------------------------------- 660 661 void win32_shutdown_sys_tray() 662 { 663 if ( ShutdownIcon::IsQuickstarterInstalled() ) 664 { 665 if( IsWindow( aListenerWindow ) ) 666 { 667 DestroyWindow( aListenerWindow ); 668 aListenerWindow = NULL; 669 DestroyWindow( aExecuterWindow ); 670 aExecuterWindow = NULL; 671 } 672 UnregisterClassA( QUICKSTART_CLASSNAME, GetModuleHandle( NULL ) ); 673 UnregisterClassA( EXECUTER_WINDOWCLASS, GetModuleHandle( NULL ) ); 674 } 675 } 676 677 678 679 // ------------------------------- 680 681 void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis) 682 { 683 MYITEM *pMyItem = (MYITEM *) lpmis->itemData; 684 HDC hdc = GetDC(hwnd); 685 SIZE size; 686 687 NONCLIENTMETRICS ncm; 688 memset(&ncm, 0, sizeof(ncm)); 689 ncm.cbSize = sizeof(ncm); 690 691 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0); 692 693 // Assume every menu item can be default and printed bold 694 ncm.lfMenuFont.lfWeight = FW_BOLD; 695 696 HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont )); 697 698 GetTextExtentPoint32W(hdc, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()), 699 pMyItem->text.getLength(), &size); 700 701 lpmis->itemWidth = size.cx + 4 + GetSystemMetrics( SM_CXSMICON ); 702 lpmis->itemHeight = (size.cy > GetSystemMetrics( SM_CYSMICON )) ? size.cy : GetSystemMetrics( SM_CYSMICON ); 703 lpmis->itemHeight += 4; 704 705 DeleteObject( SelectObject(hdc, hfntOld) ); 706 ReleaseDC(hwnd, hdc); 707 } 708 709 void OnDrawItem(HWND /*hwnd*/, LPDRAWITEMSTRUCT lpdis) 710 { 711 MYITEM *pMyItem = (MYITEM *) lpdis->itemData; 712 COLORREF clrPrevText, clrPrevBkgnd; 713 HFONT hfntOld; 714 HBRUSH hbrOld; 715 int x, y; 716 BOOL fSelected = lpdis->itemState & ODS_SELECTED; 717 BOOL fDisabled = lpdis->itemState & (ODS_DISABLED | ODS_GRAYED); 718 719 // Set the appropriate foreground and background colors. 720 721 RECT aRect = lpdis->rcItem; 722 723 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) ); 724 725 if ( fDisabled ) 726 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) ); 727 else 728 clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) ); 729 730 if ( fSelected ) 731 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) ); 732 else 733 clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) ); 734 735 hbrOld = (HBRUSH)SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) ); 736 737 // Fill background 738 PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY); 739 740 int height = aRect.bottom-aRect.top; 741 742 x = aRect.left; 743 y = aRect.top; 744 745 int cx = GetSystemMetrics( SM_CXSMICON ); 746 int cy = GetSystemMetrics( SM_CYSMICON ); 747 HICON hIcon( 0 ); 748 HMODULE hModule( GetModuleHandle( NULL ) ); 749 750 if ( pMyItem->module.getLength() > 0 ) 751 { 752 LPCWSTR pModuleName = reinterpret_cast<LPCWSTR>( pMyItem->module.getStr() ); 753 hModule = GetModuleHandleW( pModuleName ); 754 if ( hModule == NULL ) 755 { 756 LoadLibraryW( pModuleName ); 757 hModule = GetModuleHandleW( pModuleName ); 758 } 759 } 760 761 hIcon = (HICON) LoadImageA( hModule, MAKEINTRESOURCE( pMyItem->iconId ), 762 IMAGE_ICON, cx, cy, 763 LR_DEFAULTCOLOR | LR_SHARED ); 764 765 // DrawIconEx( lpdis->hDC, x, y+(height-cy)/2, hIcon, cx, cy, 0, NULL, DI_NORMAL ); 766 767 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) ); 768 769 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) ); 770 771 DeleteObject( hbrIcon ); 772 773 x += cx + 4; // space for icon 774 aRect.left = x; 775 776 NONCLIENTMETRICS ncm; 777 memset(&ncm, 0, sizeof(ncm)); 778 ncm.cbSize = sizeof(ncm); 779 780 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0); 781 782 // Print default menu entry with bold font 783 if ( lpdis->itemState & ODS_DEFAULT ) 784 ncm.lfMenuFont.lfWeight = FW_BOLD; 785 786 hfntOld = (HFONT) SelectObject(lpdis->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont )); 787 788 789 SIZE size; 790 GetTextExtentPointW( lpdis->hDC, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()), pMyItem->text.getLength(), &size ); 791 792 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) ); 793 794 // Restore the original font and colors. 795 DeleteObject( SelectObject( lpdis->hDC, hbrOld ) ); 796 DeleteObject( SelectObject( lpdis->hDC, hfntOld) ); 797 SetTextColor(lpdis->hDC, clrPrevText); 798 SetBkColor(lpdis->hDC, clrPrevBkgnd); 799 } 800 801 // ------------------------------- 802 // code from setup2 project 803 // ------------------------------- 804 805 void _SHFree( void *pv ) 806 { 807 IMalloc *pMalloc; 808 if( NOERROR == SHGetMalloc(&pMalloc) ) 809 { 810 pMalloc->Free( pv ); 811 pMalloc->Release(); 812 } 813 } 814 815 #define ALLOC(type, n) ((type *) HeapAlloc(GetProcessHeap(), 0, sizeof(type) * n )) 816 #define FREE(p) HeapFree(GetProcessHeap(), 0, p) 817 818 static OUString _SHGetSpecialFolder( int nFolderID ) 819 { 820 821 LPITEMIDLIST pidl; 822 HRESULT hHdl = SHGetSpecialFolderLocation( NULL, nFolderID, &pidl ); 823 OUString aFolder; 824 825 if( hHdl == NOERROR ) 826 { 827 WCHAR *lpFolderA; 828 lpFolderA = ALLOC( WCHAR, 16000 ); 829 830 SHGetPathFromIDListW( pidl, lpFolderA ); 831 aFolder = OUString( reinterpret_cast<const sal_Unicode*>(lpFolderA) ); 832 833 FREE( lpFolderA ); 834 _SHFree( pidl ); 835 } 836 return aFolder; 837 } 838 839 OUString ShutdownIcon::GetAutostartFolderNameW32() 840 { 841 return _SHGetSpecialFolder(CSIDL_STARTUP); 842 } 843 844 static HRESULT WINAPI SHCoCreateInstance( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv ) 845 { 846 HRESULT hResult = E_NOTIMPL; 847 HMODULE hModShell = GetModuleHandle( "SHELL32" ); 848 849 if ( hModShell != NULL ) 850 { 851 typedef HRESULT (WINAPI *SHCoCreateInstance_PROC)( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknwon, REFIID iid, LPVOID *ppv ); 852 853 SHCoCreateInstance_PROC lpfnSHCoCreateInstance = (SHCoCreateInstance_PROC)GetProcAddress( hModShell, MAKEINTRESOURCE(102) ); 854 855 if ( lpfnSHCoCreateInstance ) 856 hResult = lpfnSHCoCreateInstance( lpszReserved, clsid, pUnkUnknown, iid, ppv ); 857 } 858 return hResult; 859 } 860 861 BOOL CreateShortcut( const OUString& rAbsObject, const OUString& rAbsObjectPath, 862 const OUString& rAbsShortcut, const OUString& rDescription, const OUString& rParameter ) 863 { 864 HRESULT hres; 865 IShellLink* psl; 866 CLSID clsid_ShellLink = CLSID_ShellLink; 867 CLSID clsid_IShellLink = IID_IShellLink; 868 869 hres = CoCreateInstance( clsid_ShellLink, NULL, CLSCTX_INPROC_SERVER, 870 clsid_IShellLink, (void**)&psl ); 871 if( FAILED(hres) ) 872 hres = SHCoCreateInstance( NULL, clsid_ShellLink, NULL, clsid_IShellLink, (void**)&psl ); 873 874 if( SUCCEEDED(hres) ) 875 { 876 IPersistFile* ppf; 877 psl->SetPath( OUStringToOString(rAbsObject, osl_getThreadTextEncoding()).getStr() ); 878 psl->SetWorkingDirectory( OUStringToOString(rAbsObjectPath, osl_getThreadTextEncoding()).getStr() ); 879 psl->SetDescription( OUStringToOString(rDescription, osl_getThreadTextEncoding()).getStr() ); 880 if( rParameter.getLength() ) 881 psl->SetArguments( OUStringToOString(rParameter, osl_getThreadTextEncoding()).getStr() ); 882 883 CLSID clsid_IPersistFile = IID_IPersistFile; 884 hres = psl->QueryInterface( clsid_IPersistFile, (void**)&ppf ); 885 886 if( SUCCEEDED(hres) ) 887 { 888 hres = ppf->Save( reinterpret_cast<LPCOLESTR>(rAbsShortcut.getStr()), TRUE ); 889 ppf->Release(); 890 } else return FALSE; 891 psl->Release(); 892 } else return FALSE; 893 return TRUE; 894 } 895 896 // ------------------ 897 // install/uninstall 898 899 static bool FileExistsW( LPCWSTR lpPath ) 900 { 901 bool bExists = false; 902 WIN32_FIND_DATAW aFindData; 903 904 HANDLE hFind = FindFirstFileW( lpPath, &aFindData ); 905 906 if ( INVALID_HANDLE_VALUE != hFind ) 907 { 908 bExists = true; 909 FindClose( hFind ); 910 } 911 912 return bExists; 913 } 914 915 bool ShutdownIcon::IsQuickstarterInstalled() 916 { 917 wchar_t aPath[_MAX_PATH]; 918 if( isNT() ) 919 { 920 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1); 921 } 922 else 923 { 924 char szPathA[_MAX_PATH]; 925 GetModuleFileNameA( NULL, szPathA, _MAX_PATH-1); 926 927 // calc the string wcstr len 928 int nNeededWStrBuffSize = MultiByteToWideChar( CP_ACP, 0, szPathA, -1, NULL, 0 ); 929 930 // copy the string if necessary 931 if ( nNeededWStrBuffSize > 0 ) 932 MultiByteToWideChar( CP_ACP, 0, szPathA, -1, aPath, nNeededWStrBuffSize ); 933 } 934 935 OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) ); 936 int i = aOfficepath.lastIndexOf((sal_Char) '\\'); 937 if( i != -1 ) 938 aOfficepath = aOfficepath.copy(0, i); 939 940 OUString quickstartExe(aOfficepath); 941 quickstartExe += OUString( RTL_CONSTASCII_USTRINGPARAM( "\\quickstart.exe" ) ); 942 943 return FileExistsW( reinterpret_cast<LPCWSTR>(quickstartExe.getStr()) ); 944 } 945 946 void ShutdownIcon::EnableAutostartW32( const rtl::OUString &aShortcut ) 947 { 948 wchar_t aPath[_MAX_PATH]; 949 if( isNT() ) 950 GetModuleFileNameW( NULL, aPath, _MAX_PATH-1); 951 else 952 { 953 char szPathA[_MAX_PATH]; 954 GetModuleFileNameA( NULL, szPathA, _MAX_PATH-1); 955 956 // calc the string wcstr len 957 int nNeededWStrBuffSize = MultiByteToWideChar( CP_ACP, 0, szPathA, -1, NULL, 0 ); 958 959 // copy the string if necessary 960 if ( nNeededWStrBuffSize > 0 ) 961 MultiByteToWideChar( CP_ACP, 0, szPathA, -1, aPath, nNeededWStrBuffSize ); 962 } 963 964 OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) ); 965 int i = aOfficepath.lastIndexOf((sal_Char) '\\'); 966 if( i != -1 ) 967 aOfficepath = aOfficepath.copy(0, i); 968 969 OUString quickstartExe(aOfficepath); 970 quickstartExe += OUString( RTL_CONSTASCII_USTRINGPARAM( "\\quickstart.exe" ) ); 971 972 CreateShortcut( quickstartExe, aOfficepath, aShortcut, OUString(), OUString() ); 973 } 974 975 #endif // WNT 976 977 978