diff options
Diffstat (limited to 'sfx2/source/appl/shutdowniconw32.cxx')
-rw-r--r-- | sfx2/source/appl/shutdowniconw32.cxx | 977 |
1 files changed, 977 insertions, 0 deletions
diff --git a/sfx2/source/appl/shutdowniconw32.cxx b/sfx2/source/appl/shutdowniconw32.cxx new file mode 100644 index 000000000000..26fd35272a51 --- /dev/null +++ b/sfx2/source/appl/shutdowniconw32.cxx @@ -0,0 +1,977 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 + + |