| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sfx2.hxx" |
| |
| #ifdef WNT |
| |
| // necessary to include system headers without warnings |
| #ifdef _MSC_VER |
| #pragma warning(disable:4668 4917) |
| #endif |
| |
| // Support Windows 95 too |
| #undef WINVER |
| #define WINVER 0x0400 |
| #define USE_APP_SHORTCUTS |
| // |
| // the systray icon is only available on windows |
| // |
| |
| #include <unotools/moduleoptions.hxx> |
| #include <unotools/dynamicmenuoptions.hxx> |
| |
| #include "shutdownicon.hxx" |
| #include "app.hrc" |
| #include <shlobj.h> |
| #include <objidl.h> |
| #include <stdio.h> |
| #include <io.h> |
| #include <osl/thread.h> |
| #include <setup_native/qswin32.h> |
| #include <comphelper/sequenceashashmap.hxx> |
| #include <comphelper/processfactory.hxx> |
| #include <com/sun/star/uno/Reference.h> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/task/XJob.hpp> |
| #include <com/sun/star/beans/NamedValue.hpp> |
| |
| #include <set> |
| |
| using namespace ::rtl; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::task; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::beans; |
| using namespace ::osl; |
| |
| |
| #define EXECUTER_WINDOWCLASS "SO Executer Class" |
| #define EXECUTER_WINDOWNAME "SO Executer Window" |
| |
| |
| #define ID_QUICKSTART 1 |
| #define IDM_EXIT 2 |
| #if defined(USE_APP_SHORTCUTS) |
| # define IDM_OPEN 3 |
| # define IDM_WRITER 4 |
| # define IDM_CALC 5 |
| # define IDM_IMPRESS 6 |
| # define IDM_DRAW 7 |
| # define IDM_BASE 8 |
| # define IDM_TEMPLATE 9 |
| # define IDM_MATH 12 |
| #endif |
| #define IDM_INSTALL 10 |
| #define IDM_UNINSTALL 11 |
| |
| |
| #define ICON_SO_DEFAULT 1 |
| #define ICON_TEXT_DOCUMENT 2 |
| #define ICON_TEXT_TEMPLATE 3 |
| #define ICON_SPREADSHEET_DOCUMENT 4 |
| #define ICON_SPREADSHEET_TEMPLATE 5 |
| #define ICON_DRAWING_DOCUMENT 6 |
| #define ICON_DRAWING_TEMPLATE 7 |
| #define ICON_PRESENTATION_DOCUMENT 8 |
| #define ICON_PRESENTATION_TEMPLATE 9 |
| #define ICON_PRESENTATION_COMPRESSED 10 |
| #define ICON_GLOBAL_DOCUMENT 11 |
| #define ICON_HTML_DOCUMENT 12 |
| #define ICON_CHART_DOCUMENT 13 |
| #define ICON_DATABASE_DOCUMENT 14 |
| #define ICON_MATH_DOCUMENT 15 |
| #define ICON_TEMPLATE 16 |
| #define ICON_MACROLIBRARY 17 |
| #define ICON_CONFIGURATION 18 |
| #define ICON_OPEN 5 // See index of open folder icon in shell32.dll |
| #define ICON_SETUP 500 |
| |
| #define SFX_TASKBAR_NOTIFICATION WM_USER+1 |
| |
| static HWND aListenerWindow = NULL; |
| static HWND aExecuterWindow = NULL; |
| static HMENU popupMenu = NULL; |
| |
| static void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis); |
| static void OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis); |
| |
| typedef struct tagMYITEM |
| { |
| OUString text; |
| OUString module; |
| UINT iconId; |
| } MYITEM; |
| |
| // ------------------------------- |
| |
| static bool isNT() |
| { |
| static bool bInitialized = false; |
| static bool bWnt = false; |
| |
| if( !bInitialized ) |
| { |
| bInitialized = true; |
| |
| OSVERSIONINFO aVerInfo; |
| aVerInfo.dwOSVersionInfoSize = sizeof( aVerInfo ); |
| if ( GetVersionEx( &aVerInfo ) ) |
| { |
| if ( aVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) |
| bWnt = true; |
| } |
| } |
| return bWnt; |
| } |
| |
| |
| // ------------------------------- |
| |
| static void addMenuItem( HMENU hMenu, UINT id, UINT iconId, const OUString& text, int& pos, int bOwnerdraw, const OUString& module ) |
| { |
| MENUITEMINFOW mi; |
| memset( &mi, 0, sizeof( MENUITEMINFOW ) ); |
| |
| mi.cbSize = sizeof( MENUITEMINFOW ); |
| if( id == -1 ) |
| { |
| mi.fMask=MIIM_TYPE; |
| mi.fType=MFT_SEPARATOR; |
| } |
| else |
| { |
| if( bOwnerdraw ) |
| { |
| mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA; |
| mi.fType=MFT_OWNERDRAW; |
| mi.fState=MFS_ENABLED; |
| mi.wID = id; |
| |
| MYITEM *pMyItem = new MYITEM; |
| pMyItem->text = text; |
| pMyItem->iconId = iconId; |
| pMyItem->module = module; |
| mi.dwItemData = (DWORD) pMyItem; |
| } |
| else |
| { |
| mi.fMask=MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_DATA; |
| mi.fType=MFT_STRING; |
| mi.fState=MFS_ENABLED; |
| mi.wID = id; |
| mi.dwTypeData = (LPWSTR) text.getStr(); |
| mi.cch = text.getLength(); |
| } |
| |
| #if defined(USE_APP_SHORTCUTS) |
| if ( IDM_TEMPLATE == id ) |
| mi.fState |= MFS_DEFAULT; |
| #endif |
| } |
| |
| InsertMenuItemW( hMenu, pos++, TRUE, &mi ); |
| } |
| |
| // ------------------------------- |
| |
| static HMENU createSystrayMenu( ) |
| { |
| SvtModuleOptions aModuleOptions; |
| |
| HMENU hMenu = CreatePopupMenu(); |
| int pos=0; |
| |
| ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance(); |
| OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!"); |
| |
| if( !pShutdownIcon ) |
| return NULL; |
| |
| #if defined(USE_APP_SHORTCUTS) |
| // collect the URLs of the entries in the File/New menu |
| ::std::set< ::rtl::OUString > aFileNewAppsAvailable; |
| SvtDynamicMenuOptions aOpt; |
| Sequence < Sequence < PropertyValue > > aNewMenu = aOpt.GetMenu( E_NEWMENU ); |
| const ::rtl::OUString sURLKey( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); |
| |
| const Sequence< PropertyValue >* pNewMenu = aNewMenu.getConstArray(); |
| const Sequence< PropertyValue >* pNewMenuEnd = aNewMenu.getConstArray() + aNewMenu.getLength(); |
| for ( ; pNewMenu != pNewMenuEnd; ++pNewMenu ) |
| { |
| ::comphelper::SequenceAsHashMap aEntryItems( *pNewMenu ); |
| ::rtl::OUString sURL( aEntryItems.getUnpackedValueOrDefault( sURLKey, ::rtl::OUString() ) ); |
| if ( sURL.getLength() ) |
| aFileNewAppsAvailable.insert( sURL ); |
| } |
| |
| // describe the menu entries for launching the applications |
| struct MenuEntryDescriptor |
| { |
| SvtModuleOptions::EModule eModuleIdentifier; |
| UINT nMenuItemID; |
| UINT nMenuIconID; |
| const char* pAsciiURLDescription; |
| } aMenuItems[] = |
| { |
| { SvtModuleOptions::E_SWRITER, IDM_WRITER, ICON_TEXT_DOCUMENT, WRITER_URL }, |
| { SvtModuleOptions::E_SCALC, IDM_CALC, ICON_SPREADSHEET_DOCUMENT, CALC_URL }, |
| { SvtModuleOptions::E_SIMPRESS, IDM_IMPRESS,ICON_PRESENTATION_DOCUMENT, IMPRESS_WIZARD_URL }, |
| { SvtModuleOptions::E_SDRAW, IDM_DRAW, ICON_DRAWING_DOCUMENT, DRAW_URL }, |
| { SvtModuleOptions::E_SDATABASE, IDM_BASE, ICON_DATABASE_DOCUMENT, BASE_URL }, |
| { SvtModuleOptions::E_SMATH, IDM_MATH, ICON_MATH_DOCUMENT, MATH_URL }, |
| }; |
| |
| OUString aEmpty; |
| |
| // insert the menu entries for launching the applications |
| for ( size_t i = 0; i < sizeof( aMenuItems ) / sizeof( aMenuItems[0] ); ++i ) |
| { |
| if ( !aModuleOptions.IsModuleInstalled( aMenuItems[i].eModuleIdentifier ) ) |
| // the complete application is not even installed |
| continue; |
| |
| ::rtl::OUString sURL( ::rtl::OUString::createFromAscii( aMenuItems[i].pAsciiURLDescription ) ); |
| |
| if ( aFileNewAppsAvailable.find( sURL ) == aFileNewAppsAvailable.end() ) |
| // the application is installed, but the entry has been configured to *not* appear in the File/New |
| // menu => also let not appear it in the quickstarter |
| continue; |
| |
| addMenuItem( hMenu, aMenuItems[i].nMenuItemID, aMenuItems[i].nMenuIconID, |
| pShutdownIcon->GetUrlDescription( sURL ), pos, true, aEmpty ); |
| } |
| |
| |
| |
| // insert the remaining menu entries |
| addMenuItem( hMenu, IDM_TEMPLATE, ICON_TEMPLATE, |
| pShutdownIcon->GetResString( STR_QUICKSTART_FROMTEMPLATE ), pos, true, aEmpty); |
| addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty ); |
| addMenuItem( hMenu, IDM_OPEN, ICON_OPEN, pShutdownIcon->GetResString( STR_QUICKSTART_FILEOPEN ), pos, true, OUString::createFromAscii( "SHELL32" )); |
| addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty ); |
| #endif |
| addMenuItem( hMenu, IDM_INSTALL,0, pShutdownIcon->GetResString( STR_QUICKSTART_PRELAUNCH ), pos, false, aEmpty ); |
| addMenuItem( hMenu, static_cast< UINT >( -1 ), 0, OUString(), pos, false, aEmpty ); |
| addMenuItem( hMenu, IDM_EXIT, 0, pShutdownIcon->GetResString( STR_QUICKSTART_EXIT ), pos, false, aEmpty ); |
| |
| // indicate status of autostart folder |
| CheckMenuItem( hMenu, IDM_INSTALL, MF_BYCOMMAND | (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) ); |
| |
| return hMenu; |
| } |
| |
| // ------------------------------- |
| |
| static void deleteSystrayMenu( HMENU hMenu ) |
| { |
| if( !hMenu || !IsMenu( hMenu )) |
| return; |
| |
| MENUITEMINFOW mi; |
| MYITEM *pMyItem; |
| int pos=0; |
| memset( &mi, 0, sizeof( mi ) ); |
| mi.cbSize = sizeof( mi ); |
| mi.fMask = MIIM_DATA; |
| |
| while( GetMenuItemInfoW( hMenu, pos++, true, &mi ) ) |
| { |
| pMyItem = (MYITEM*) mi.dwItemData; |
| if( pMyItem ) |
| { |
| pMyItem->text = OUString(); |
| delete pMyItem; |
| } |
| mi.fMask = MIIM_DATA; |
| } |
| } |
| |
| // ------------------------------- |
| |
| static void addTaskbarIcon( HWND hWnd ) |
| { |
| OUString strTip; |
| if( ShutdownIcon::getInstance() ) |
| strTip = ShutdownIcon::getInstance()->GetResString( STR_QUICKSTART_TIP ); |
| |
| // add taskbar icon |
| NOTIFYICONDATAA nid; |
| nid.hIcon = (HICON)LoadImageA( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_SO_DEFAULT ), |
| IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), |
| LR_DEFAULTCOLOR | LR_SHARED ); |
| |
| // better use unicode wrapper here ? |
| strncpy( nid.szTip, ( OUStringToOString(strTip, osl_getThreadTextEncoding()).getStr() ), 64 ); |
| |
| nid.cbSize = sizeof(nid); |
| nid.hWnd = hWnd; |
| nid.uID = ID_QUICKSTART; |
| nid.uCallbackMessage = SFX_TASKBAR_NOTIFICATION; |
| nid.uFlags = NIF_MESSAGE|NIF_TIP|NIF_ICON; |
| |
| Shell_NotifyIconA(NIM_ADD, &nid); |
| } |
| |
| // ------------------------------- |
| |
| /* |
| static void removeTaskbarIcon() |
| { |
| ShutdownIcon *pShutdownIcon = ShutdownIcon::getInstance(); |
| OSL_ENSURE( pShutdownIcon, "ShutdownIcon instance empty!"); |
| |
| if( !pShutdownIcon ) |
| return; |
| |
| if ( IsWindow( aListenerWindow )) |
| { |
| deleteSystrayMenu( popupMenu ); |
| |
| NOTIFYICONDATAA nid; |
| nid.cbSize=sizeof(NOTIFYICONDATA); |
| nid.hWnd = aListenerWindow; |
| nid.uID = ID_QUICKSTART; |
| Shell_NotifyIconA(NIM_DELETE, &nid); |
| } |
| } |
| */ |
| |
| // ------------------------------- |
| |
| LRESULT CALLBACK listenerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
| { |
| static UINT s_uTaskbarRestart = 0; |
| static UINT s_uMsgKillTray = 0; |
| |
| switch (uMsg) |
| { |
| case WM_NCCREATE: |
| return TRUE; |
| case WM_CREATE: |
| { |
| // request notfication when taskbar is recreated |
| // we then have to add our icon again |
| s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); |
| s_uMsgKillTray = RegisterWindowMessage( SHUTDOWN_QUICKSTART_MESSAGE ); |
| |
| // create the menu |
| if( !popupMenu ) |
| if( (popupMenu = createSystrayMenu( )) == NULL ) |
| return -1; |
| |
| // and the icon |
| addTaskbarIcon( hWnd ); |
| |
| // disable shutdown |
| ShutdownIcon::getInstance()->SetVeto( true ); |
| ShutdownIcon::getInstance()->addTerminateListener(); |
| } |
| return 0; |
| |
| case WM_MEASUREITEM: |
| OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT) lParam); |
| return TRUE; |
| |
| case WM_DRAWITEM: |
| OnDrawItem(hWnd, (LPDRAWITEMSTRUCT) lParam); |
| return TRUE; |
| |
| case SFX_TASKBAR_NOTIFICATION: |
| switch( lParam ) |
| { |
| case WM_LBUTTONDBLCLK: |
| #if defined(USE_APP_SHORTCUTS) |
| PostMessage( aExecuterWindow, WM_COMMAND, IDM_TEMPLATE, (LPARAM)hWnd ); |
| #endif |
| break; |
| |
| case WM_RBUTTONDOWN: |
| { |
| POINT pt; |
| GetCursorPos(&pt); |
| SetForegroundWindow( hWnd ); |
| |
| // update status before showing menu, could have been changed from option page |
| CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) ); |
| |
| EnableMenuItem( popupMenu, IDM_EXIT, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) ); |
| #if defined(USE_APP_SHORTCUTS) |
| EnableMenuItem( popupMenu, IDM_OPEN, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) ); |
| EnableMenuItem( popupMenu, IDM_TEMPLATE, MF_BYCOMMAND | (ShutdownIcon::bModalMode ? MF_GRAYED : MF_ENABLED) ); |
| #endif |
| int m = TrackPopupMenuEx( popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON, |
| pt.x, pt.y, hWnd, NULL ); |
| // BUGFIX: See Q135788 (PRB: Menus for Notification Icons Don't Work Correctly) |
| PostMessage( hWnd, NULL, 0, 0 ); |
| switch( m ) |
| { |
| #if defined(USE_APP_SHORTCUTS) |
| case IDM_OPEN: |
| case IDM_WRITER: |
| case IDM_CALC: |
| case IDM_IMPRESS: |
| case IDM_DRAW: |
| case IDM_TEMPLATE: |
| case IDM_BASE: |
| case IDM_MATH: |
| break; |
| #endif |
| case IDM_INSTALL: |
| CheckMenuItem( popupMenu, IDM_INSTALL, MF_BYCOMMAND| (ShutdownIcon::GetAutostart() ? MF_CHECKED : MF_UNCHECKED) ); |
| break; |
| case IDM_EXIT: |
| // delete taskbar icon |
| NOTIFYICONDATAA nid; |
| nid.cbSize=sizeof(NOTIFYICONDATA); |
| nid.hWnd = hWnd; |
| nid.uID = ID_QUICKSTART; |
| Shell_NotifyIconA(NIM_DELETE, &nid); |
| break; |
| } |
| |
| PostMessage( aExecuterWindow, WM_COMMAND, m, (LPARAM)hWnd ); |
| } |
| break; |
| } |
| break; |
| case WM_DESTROY: |
| deleteSystrayMenu( popupMenu ); |
| // We don't need the Systray Thread anymore |
| PostQuitMessage( 0 ); |
| return DefWindowProc(hWnd, uMsg, wParam, lParam); |
| default: |
| if( uMsg == s_uTaskbarRestart ) |
| { |
| // re-create taskbar icon |
| addTaskbarIcon( hWnd ); |
| } |
| else if ( uMsg == s_uMsgKillTray ) |
| { |
| // delete taskbar icon |
| NOTIFYICONDATAA nid; |
| nid.cbSize=sizeof(NOTIFYICONDATA); |
| nid.hWnd = hWnd; |
| nid.uID = ID_QUICKSTART; |
| Shell_NotifyIconA(NIM_DELETE, &nid); |
| |
| PostMessage( aExecuterWindow, WM_COMMAND, IDM_EXIT, (LPARAM)hWnd ); |
| } |
| else |
| return DefWindowProc(hWnd, uMsg, wParam, lParam); |
| } |
| return 0; |
| } |
| |
| // ------------------------------- |
| |
| static sal_Bool checkOEM() { |
| Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory(); |
| Reference<XJob> rOemJob(rFactory->createInstance( |
| OUString::createFromAscii("com.sun.star.office.OEMPreloadJob")), |
| UNO_QUERY ); |
| Sequence<NamedValue> args; |
| sal_Bool bResult = sal_False; |
| if (rOemJob.is()) |
| { |
| Any aResult = rOemJob->execute(args); |
| aResult >>= bResult; |
| } else bResult = sal_True; |
| return bResult; |
| } |
| |
| LRESULT CALLBACK executerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
| { |
| switch (uMsg) |
| { |
| case WM_NCCREATE: |
| return TRUE; |
| case WM_CREATE: |
| return 0; |
| |
| case WM_COMMAND: |
| switch( LOWORD(wParam) ) |
| { |
| #if defined(USE_APP_SHORTCUTS) |
| case IDM_OPEN: |
| if ( !ShutdownIcon::bModalMode && checkOEM() ) |
| ShutdownIcon::FileOpen(); |
| break; |
| case IDM_WRITER: |
| if (checkOEM()) |
| ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( WRITER_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); |
| break; |
| case IDM_CALC: |
| if (checkOEM()) |
| ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( CALC_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); |
| break; |
| case IDM_IMPRESS: |
| if (checkOEM()) |
| ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( IMPRESS_WIZARD_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); |
| break; |
| case IDM_DRAW: |
| if (checkOEM()) |
| ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( DRAW_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); |
| break; |
| case IDM_BASE: |
| if (checkOEM()) |
| ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( BASE_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); |
| break; |
| case IDM_MATH: |
| if (checkOEM()) |
| ShutdownIcon::OpenURL( OUString( RTL_CONSTASCII_USTRINGPARAM( MATH_URL ) ), OUString( RTL_CONSTASCII_USTRINGPARAM( "_default" ) ) ); |
| break; |
| case IDM_TEMPLATE: |
| if ( !ShutdownIcon::bModalMode && checkOEM()) |
| ShutdownIcon::FromTemplate(); |
| break; |
| #endif |
| case IDM_INSTALL: |
| ShutdownIcon::SetAutostart( !ShutdownIcon::GetAutostart() ); |
| break; |
| case IDM_EXIT: |
| // remove listener and |
| // terminate office if running in background |
| if ( !ShutdownIcon::bModalMode ) |
| ShutdownIcon::terminateDesktop(); |
| break; |
| } |
| break; |
| case WM_DESTROY: |
| default: |
| return DefWindowProc(hWnd, uMsg, wParam, lParam); |
| } |
| return 0; |
| } |
| |
| // ------------------------------- |
| |
| |
| DWORD WINAPI SystrayThread( LPVOID /*lpParam*/ ) |
| { |
| aListenerWindow = CreateWindowExA(0, |
| QUICKSTART_CLASSNAME, // registered class name |
| QUICKSTART_WINDOWNAME, // window name |
| 0, // window style |
| CW_USEDEFAULT, // horizontal position of window |
| CW_USEDEFAULT, // vertical position of window |
| CW_USEDEFAULT, // window width |
| CW_USEDEFAULT, // window height |
| (HWND) NULL, // handle to parent or owner window |
| NULL, // menu handle or child identifier |
| (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance |
| NULL // window-creation data |
| ); |
| |
| MSG msg; |
| |
| while ( GetMessage( &msg, NULL, 0, 0 ) ) |
| { |
| TranslateMessage( &msg ); |
| DispatchMessage( &msg ); |
| } |
| |
| return msg.wParam; // Exit code of WM_QUIT |
| } |
| |
| // ------------------------------- |
| |
| void win32_init_sys_tray() |
| { |
| if ( ShutdownIcon::IsQuickstarterInstalled() ) |
| { |
| WNDCLASSEXA listenerClass; |
| listenerClass.cbSize = sizeof(WNDCLASSEX); |
| listenerClass.style = 0; |
| listenerClass.lpfnWndProc = listenerWndProc; |
| listenerClass.cbClsExtra = 0; |
| listenerClass.cbWndExtra = 0; |
| listenerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL ); |
| listenerClass.hIcon = NULL; |
| listenerClass.hCursor = NULL; |
| listenerClass.hbrBackground = NULL; |
| listenerClass.lpszMenuName = NULL; |
| listenerClass.lpszClassName = QUICKSTART_CLASSNAME; |
| listenerClass.hIconSm = NULL; |
| |
| RegisterClassExA(&listenerClass); |
| |
| WNDCLASSEXA executerClass; |
| executerClass.cbSize = sizeof(WNDCLASSEX); |
| executerClass.style = 0; |
| executerClass.lpfnWndProc = executerWndProc; |
| executerClass.cbClsExtra = 0; |
| executerClass.cbWndExtra = 0; |
| executerClass.hInstance = (HINSTANCE) GetModuleHandle( NULL ); |
| executerClass.hIcon = NULL; |
| executerClass.hCursor = NULL; |
| executerClass.hbrBackground = NULL; |
| executerClass.lpszMenuName = NULL; |
| executerClass.lpszClassName = EXECUTER_WINDOWCLASS; |
| executerClass.hIconSm = NULL; |
| |
| RegisterClassExA( &executerClass ); |
| |
| aExecuterWindow = CreateWindowExA(0, |
| EXECUTER_WINDOWCLASS, // registered class name |
| EXECUTER_WINDOWNAME, // window name |
| 0, // window style |
| CW_USEDEFAULT, // horizontal position of window |
| CW_USEDEFAULT, // vertical position of window |
| CW_USEDEFAULT, // window width |
| CW_USEDEFAULT, // window height |
| (HWND) NULL, // handle to parent or owner window |
| NULL, // menu handle or child identifier |
| (HINSTANCE) GetModuleHandle( NULL ), // handle to application instance |
| NULL // window-creation data |
| ); |
| |
| DWORD dwThreadId; |
| CreateThread( NULL, 0, SystrayThread, NULL, 0, &dwThreadId ); |
| } |
| } |
| |
| // ------------------------------- |
| |
| void win32_shutdown_sys_tray() |
| { |
| if ( ShutdownIcon::IsQuickstarterInstalled() ) |
| { |
| if( IsWindow( aListenerWindow ) ) |
| { |
| DestroyWindow( aListenerWindow ); |
| aListenerWindow = NULL; |
| DestroyWindow( aExecuterWindow ); |
| aExecuterWindow = NULL; |
| } |
| UnregisterClassA( QUICKSTART_CLASSNAME, GetModuleHandle( NULL ) ); |
| UnregisterClassA( EXECUTER_WINDOWCLASS, GetModuleHandle( NULL ) ); |
| } |
| } |
| |
| |
| |
| // ------------------------------- |
| |
| void OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis) |
| { |
| MYITEM *pMyItem = (MYITEM *) lpmis->itemData; |
| HDC hdc = GetDC(hwnd); |
| SIZE size; |
| |
| NONCLIENTMETRICS ncm; |
| memset(&ncm, 0, sizeof(ncm)); |
| ncm.cbSize = sizeof(ncm); |
| |
| SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0); |
| |
| // Assume every menu item can be default and printed bold |
| ncm.lfMenuFont.lfWeight = FW_BOLD; |
| |
| HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont )); |
| |
| GetTextExtentPoint32W(hdc, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()), |
| pMyItem->text.getLength(), &size); |
| |
| lpmis->itemWidth = size.cx + 4 + GetSystemMetrics( SM_CXSMICON ); |
| lpmis->itemHeight = (size.cy > GetSystemMetrics( SM_CYSMICON )) ? size.cy : GetSystemMetrics( SM_CYSMICON ); |
| lpmis->itemHeight += 4; |
| |
| DeleteObject( SelectObject(hdc, hfntOld) ); |
| ReleaseDC(hwnd, hdc); |
| } |
| |
| void OnDrawItem(HWND /*hwnd*/, LPDRAWITEMSTRUCT lpdis) |
| { |
| MYITEM *pMyItem = (MYITEM *) lpdis->itemData; |
| COLORREF clrPrevText, clrPrevBkgnd; |
| HFONT hfntOld; |
| HBRUSH hbrOld; |
| int x, y; |
| BOOL fSelected = lpdis->itemState & ODS_SELECTED; |
| BOOL fDisabled = lpdis->itemState & (ODS_DISABLED | ODS_GRAYED); |
| |
| // Set the appropriate foreground and background colors. |
| |
| RECT aRect = lpdis->rcItem; |
| |
| clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) ); |
| |
| if ( fDisabled ) |
| clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( COLOR_GRAYTEXT ) ); |
| else |
| clrPrevText = SetTextColor( lpdis->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) ); |
| |
| if ( fSelected ) |
| clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT) ); |
| else |
| clrPrevBkgnd = SetBkColor( lpdis->hDC, GetSysColor(COLOR_MENU) ); |
| |
| hbrOld = (HBRUSH)SelectObject( lpdis->hDC, CreateSolidBrush( GetBkColor( lpdis->hDC ) ) ); |
| |
| // Fill background |
| PatBlt(lpdis->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY); |
| |
| int height = aRect.bottom-aRect.top; |
| |
| x = aRect.left; |
| y = aRect.top; |
| |
| int cx = GetSystemMetrics( SM_CXSMICON ); |
| int cy = GetSystemMetrics( SM_CYSMICON ); |
| HICON hIcon( 0 ); |
| HMODULE hModule( GetModuleHandle( NULL ) ); |
| |
| if ( pMyItem->module.getLength() > 0 ) |
| { |
| LPCWSTR pModuleName = reinterpret_cast<LPCWSTR>( pMyItem->module.getStr() ); |
| hModule = GetModuleHandleW( pModuleName ); |
| if ( hModule == NULL ) |
| { |
| LoadLibraryW( pModuleName ); |
| hModule = GetModuleHandleW( pModuleName ); |
| } |
| } |
| |
| hIcon = (HICON) LoadImageA( hModule, MAKEINTRESOURCE( pMyItem->iconId ), |
| IMAGE_ICON, cx, cy, |
| LR_DEFAULTCOLOR | LR_SHARED ); |
| |
| // DrawIconEx( lpdis->hDC, x, y+(height-cy)/2, hIcon, cx, cy, 0, NULL, DI_NORMAL ); |
| |
| HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) ); |
| |
| 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) ); |
| |
| DeleteObject( hbrIcon ); |
| |
| x += cx + 4; // space for icon |
| aRect.left = x; |
| |
| NONCLIENTMETRICS ncm; |
| memset(&ncm, 0, sizeof(ncm)); |
| ncm.cbSize = sizeof(ncm); |
| |
| SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0); |
| |
| // Print default menu entry with bold font |
| if ( lpdis->itemState & ODS_DEFAULT ) |
| ncm.lfMenuFont.lfWeight = FW_BOLD; |
| |
| hfntOld = (HFONT) SelectObject(lpdis->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont )); |
| |
| |
| SIZE size; |
| GetTextExtentPointW( lpdis->hDC, reinterpret_cast<LPCWSTR>(pMyItem->text.getStr()), pMyItem->text.getLength(), &size ); |
| |
| 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) ); |
| |
| // Restore the original font and colors. |
| DeleteObject( SelectObject( lpdis->hDC, hbrOld ) ); |
| DeleteObject( SelectObject( lpdis->hDC, hfntOld) ); |
| SetTextColor(lpdis->hDC, clrPrevText); |
| SetBkColor(lpdis->hDC, clrPrevBkgnd); |
| } |
| |
| // ------------------------------- |
| // code from setup2 project |
| // ------------------------------- |
| |
| void _SHFree( void *pv ) |
| { |
| IMalloc *pMalloc; |
| if( NOERROR == SHGetMalloc(&pMalloc) ) |
| { |
| pMalloc->Free( pv ); |
| pMalloc->Release(); |
| } |
| } |
| |
| #define ALLOC(type, n) ((type *) HeapAlloc(GetProcessHeap(), 0, sizeof(type) * n )) |
| #define FREE(p) HeapFree(GetProcessHeap(), 0, p) |
| |
| static OUString _SHGetSpecialFolder( int nFolderID ) |
| { |
| |
| LPITEMIDLIST pidl; |
| HRESULT hHdl = SHGetSpecialFolderLocation( NULL, nFolderID, &pidl ); |
| OUString aFolder; |
| |
| if( hHdl == NOERROR ) |
| { |
| WCHAR *lpFolderA; |
| lpFolderA = ALLOC( WCHAR, 16000 ); |
| |
| SHGetPathFromIDListW( pidl, lpFolderA ); |
| aFolder = OUString( reinterpret_cast<const sal_Unicode*>(lpFolderA) ); |
| |
| FREE( lpFolderA ); |
| _SHFree( pidl ); |
| } |
| return aFolder; |
| } |
| |
| OUString ShutdownIcon::GetAutostartFolderNameW32() |
| { |
| return _SHGetSpecialFolder(CSIDL_STARTUP); |
| } |
| |
| static HRESULT WINAPI SHCoCreateInstance( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknown, REFIID iid, LPVOID *ppv ) |
| { |
| HRESULT hResult = E_NOTIMPL; |
| HMODULE hModShell = GetModuleHandle( "SHELL32" ); |
| |
| if ( hModShell != NULL ) |
| { |
| typedef HRESULT (WINAPI *SHCoCreateInstance_PROC)( LPVOID lpszReserved, REFCLSID clsid, LPUNKNOWN pUnkUnknwon, REFIID iid, LPVOID *ppv ); |
| |
| SHCoCreateInstance_PROC lpfnSHCoCreateInstance = (SHCoCreateInstance_PROC)GetProcAddress( hModShell, MAKEINTRESOURCE(102) ); |
| |
| if ( lpfnSHCoCreateInstance ) |
| hResult = lpfnSHCoCreateInstance( lpszReserved, clsid, pUnkUnknown, iid, ppv ); |
| } |
| return hResult; |
| } |
| |
| BOOL CreateShortcut( const OUString& rAbsObject, const OUString& rAbsObjectPath, |
| const OUString& rAbsShortcut, const OUString& rDescription, const OUString& rParameter ) |
| { |
| HRESULT hres; |
| IShellLink* psl; |
| CLSID clsid_ShellLink = CLSID_ShellLink; |
| CLSID clsid_IShellLink = IID_IShellLink; |
| |
| hres = CoCreateInstance( clsid_ShellLink, NULL, CLSCTX_INPROC_SERVER, |
| clsid_IShellLink, (void**)&psl ); |
| if( FAILED(hres) ) |
| hres = SHCoCreateInstance( NULL, clsid_ShellLink, NULL, clsid_IShellLink, (void**)&psl ); |
| |
| if( SUCCEEDED(hres) ) |
| { |
| IPersistFile* ppf; |
| psl->SetPath( OUStringToOString(rAbsObject, osl_getThreadTextEncoding()).getStr() ); |
| psl->SetWorkingDirectory( OUStringToOString(rAbsObjectPath, osl_getThreadTextEncoding()).getStr() ); |
| psl->SetDescription( OUStringToOString(rDescription, osl_getThreadTextEncoding()).getStr() ); |
| if( rParameter.getLength() ) |
| psl->SetArguments( OUStringToOString(rParameter, osl_getThreadTextEncoding()).getStr() ); |
| |
| CLSID clsid_IPersistFile = IID_IPersistFile; |
| hres = psl->QueryInterface( clsid_IPersistFile, (void**)&ppf ); |
| |
| if( SUCCEEDED(hres) ) |
| { |
| hres = ppf->Save( reinterpret_cast<LPCOLESTR>(rAbsShortcut.getStr()), TRUE ); |
| ppf->Release(); |
| } else return FALSE; |
| psl->Release(); |
| } else return FALSE; |
| return TRUE; |
| } |
| |
| // ------------------ |
| // install/uninstall |
| |
| static bool FileExistsW( LPCWSTR lpPath ) |
| { |
| bool bExists = false; |
| WIN32_FIND_DATAW aFindData; |
| |
| HANDLE hFind = FindFirstFileW( lpPath, &aFindData ); |
| |
| if ( INVALID_HANDLE_VALUE != hFind ) |
| { |
| bExists = true; |
| FindClose( hFind ); |
| } |
| |
| return bExists; |
| } |
| |
| bool ShutdownIcon::IsQuickstarterInstalled() |
| { |
| wchar_t aPath[_MAX_PATH]; |
| if( isNT() ) |
| { |
| GetModuleFileNameW( NULL, aPath, _MAX_PATH-1); |
| } |
| else |
| { |
| char szPathA[_MAX_PATH]; |
| GetModuleFileNameA( NULL, szPathA, _MAX_PATH-1); |
| |
| // calc the string wcstr len |
| int nNeededWStrBuffSize = MultiByteToWideChar( CP_ACP, 0, szPathA, -1, NULL, 0 ); |
| |
| // copy the string if necessary |
| if ( nNeededWStrBuffSize > 0 ) |
| MultiByteToWideChar( CP_ACP, 0, szPathA, -1, aPath, nNeededWStrBuffSize ); |
| } |
| |
| OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) ); |
| int i = aOfficepath.lastIndexOf((sal_Char) '\\'); |
| if( i != -1 ) |
| aOfficepath = aOfficepath.copy(0, i); |
| |
| OUString quickstartExe(aOfficepath); |
| quickstartExe += OUString( RTL_CONSTASCII_USTRINGPARAM( "\\quickstart.exe" ) ); |
| |
| return FileExistsW( reinterpret_cast<LPCWSTR>(quickstartExe.getStr()) ); |
| } |
| |
| void ShutdownIcon::EnableAutostartW32( const rtl::OUString &aShortcut ) |
| { |
| wchar_t aPath[_MAX_PATH]; |
| if( isNT() ) |
| GetModuleFileNameW( NULL, aPath, _MAX_PATH-1); |
| else |
| { |
| char szPathA[_MAX_PATH]; |
| GetModuleFileNameA( NULL, szPathA, _MAX_PATH-1); |
| |
| // calc the string wcstr len |
| int nNeededWStrBuffSize = MultiByteToWideChar( CP_ACP, 0, szPathA, -1, NULL, 0 ); |
| |
| // copy the string if necessary |
| if ( nNeededWStrBuffSize > 0 ) |
| MultiByteToWideChar( CP_ACP, 0, szPathA, -1, aPath, nNeededWStrBuffSize ); |
| } |
| |
| OUString aOfficepath( reinterpret_cast<const sal_Unicode*>(aPath) ); |
| int i = aOfficepath.lastIndexOf((sal_Char) '\\'); |
| if( i != -1 ) |
| aOfficepath = aOfficepath.copy(0, i); |
| |
| OUString quickstartExe(aOfficepath); |
| quickstartExe += OUString( RTL_CONSTASCII_USTRINGPARAM( "\\quickstart.exe" ) ); |
| |
| CreateShortcut( quickstartExe, aOfficepath, aShortcut, OUString(), OUString() ); |
| } |
| |
| #endif // WNT |
| |
| |