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