// QuickStart.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #include #include #define MY_TASKBAR_NOTIFICATION WM_USER+1 #define MAX_LOADSTRING 100 // message used to communicate with soffice #define TERMINATIONVETO_MESSAGE "SO TerminationVeto" #define TERMINATE_MESSAGE "SO Terminate" #define LISTENER_WINDOWCLASS "SO Listener Class" #define KILLTRAY_MESSAGE "SO KillTray" static UINT aTerminationVetoMessage = 0x7FFF; static UINT aTerminateMessage = 0x7FFF; static HMENU popupMenu = NULL; static bool bTerminateVeto = true; #define UPDATE_TIMER 1 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text TCHAR szExitString[MAX_LOADSTRING]; TCHAR szTooltipString[MAX_LOADSTRING]; // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); bool SofficeRuns() { // check for soffice by searching the communication window return ( FindWindowEx( NULL, NULL, LISTENER_WINDOWCLASS, NULL ) == NULL ) ? false : true; } bool launchSoffice( ) { if ( !SofficeRuns() ) { // UINT ret = WinExec( "h:\\office60.630b\\program\\swriter.exe -bean", SW_SHOW ); char filename[_MAX_PATH + 1]; filename[_MAX_PATH] = 0; GetModuleFileName( NULL, filename, _MAX_PATH ); // soffice resides in the same dir char *p = strrchr( filename, '\\' ); if ( !p ) return false; strncpy( p+1, "soffice.exe", _MAX_PATH - (p+1 - filename) ); char imagename[_MAX_PATH + 1]; imagename[_MAX_PATH] = 0; _snprintf(imagename, _MAX_PATH, "\"%s\" -quickstart", filename ); UINT ret = WinExec( imagename, SW_SHOW ); if ( ret < 32 ) return false; /* // wait until we can communicate int retry = 30; while (retry-- && !SofficeRuns() ) Sleep(1000); return SofficeRuns(); */ return true; } else return true; } void NotifyListener( HWND hWnd ) { static HICON hIconActive=NULL; //static HICON hIconInActive=NULL; if( !hIconActive ) { hIconActive = (HICON)LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_ACTIVE ), IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), LR_DEFAULTCOLOR | LR_SHARED ); /* hIconInActive = (HICON)LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_INACTIVE ), IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), LR_DEFAULTCOLOR | LR_SHARED ); */ } NOTIFYICONDATA nid; nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = hWnd; nid.uID = IDM_QUICKSTART; nid.szTip[elementsof(nid.szTip) - 1] = 0; // nid.hIcon = bTerminateVeto ? hIconActive : hIconInActive; // strncpy(nid.szTip, bTerminateVeto ? STRING_QUICKSTARTACTIVE : STRING_QUICKSTARTINACTIVE, elementsof(nid.szTip) - 1 ); nid.hIcon = hIconActive; strncpy(nid.szTip, szTooltipString, elementsof(nid.szTip) - 1); nid.uFlags = NIF_TIP|NIF_ICON; // update systray Shell_NotifyIcon( NIM_MODIFY, &nid ); //CheckMenuItem( popupMenu, IDM_QUICKSTART, bTerminateVeto ? MF_CHECKED : MF_UNCHECKED ); // notify listener SendMessage( HWND_BROADCAST, aTerminationVetoMessage, (WORD) bTerminateVeto, 0L ); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow) { // Look for -killtray argument for ( int i = 1; i < __argc; i++ ) { if ( 0 == strcmp( __argv[i], "-killtray" ) ) { HWND hwndTray = FindWindow( LISTENER_WINDOWCLASS, NULL ); if ( hwndTray ) { UINT uMsgKillTray = RegisterWindowMessage( KILLTRAY_MESSAGE ); SendMessage( hwndTray, uMsgKillTray, 0, 0 ); } return 0; } } launchSoffice(); return 0; // TODO: Place code here. MSG msg; HACCEL hAccelTable; aTerminationVetoMessage = RegisterWindowMessage( TERMINATIONVETO_MESSAGE ); aTerminateMessage = RegisterWindowMessage( TERMINATE_MESSAGE ); // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_QUICKSTART, szWindowClass, MAX_LOADSTRING); LoadString(hInstance, IDS_EXIT, szExitString, MAX_LOADSTRING); LoadString(hInstance, IDS_TOOLTIP, szTooltipString, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_QUICKSTART); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage is only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_QUICKSTART); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } nCmdShow = SW_HIDE; // hide main window, we only need the taskbar icon ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: { // make sure soffice runs if( !launchSoffice() ) return -1; // create popup menu popupMenu = CreatePopupMenu(); static int count=0; // Add my items MENUITEMINFO mi; mi.cbSize = sizeof(MENUITEMINFO); mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; mi.fType=MFT_STRING; mi.fState=MFS_ENABLED|MFS_DEFAULT; mi.wID = IDM_QUICKSTART; mi.hSubMenu=NULL; mi.hbmpChecked=NULL; mi.hbmpUnchecked=NULL; mi.dwItemData=NULL; mi.dwTypeData = "QuickStart"; mi.cch = strlen(mi.dwTypeData); // InsertMenuItem(popupMenu, count++, TRUE, &mi); mi.cbSize = sizeof(MENUITEMINFO); mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; mi.fType=MFT_STRING; mi.fState=MFS_ENABLED; mi.wID = IDM_ABOUT; mi.hSubMenu=NULL; mi.hbmpChecked=NULL; mi.hbmpUnchecked=NULL; mi.dwItemData=NULL; mi.dwTypeData = "Info..."; mi.cch = strlen(mi.dwTypeData); // InsertMenuItem(popupMenu, count++, TRUE, &mi); mi.cbSize = sizeof(MENUITEMINFO); mi.fMask=MIIM_TYPE; mi.fType=MFT_SEPARATOR; mi.hSubMenu=NULL; mi.hbmpChecked=NULL; mi.hbmpUnchecked=NULL; mi.dwItemData=NULL; // InsertMenuItem(popupMenu, count++, TRUE, &mi); mi.cbSize = sizeof(MENUITEMINFO); mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; mi.fType=MFT_STRING; mi.fState=MFS_ENABLED; mi.wID = IDM_EXIT; mi.hSubMenu=NULL; mi.hbmpChecked=NULL; mi.hbmpUnchecked=NULL; mi.dwItemData=NULL; mi.dwTypeData = szExitString; mi.cch = strlen(mi.dwTypeData); InsertMenuItem(popupMenu, count++, TRUE, &mi); // add taskbar icon NOTIFYICONDATA nid; nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = hWnd; nid.uID = IDM_QUICKSTART; nid.uFlags = NIF_MESSAGE; nid.uCallbackMessage=MY_TASKBAR_NOTIFICATION; Shell_NotifyIcon(NIM_ADD, &nid); // and update state NotifyListener( hWnd ); // check for soffice SetTimer(hWnd, UPDATE_TIMER, 3000, NULL); } break; case MY_TASKBAR_NOTIFICATION: // message from taskbar switch(lParam) { /* case WM_LBUTTONDBLCLK: bTerminateVeto = bTerminateVeto ? false : true; NotifyListener( hWnd ); break; */ case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: { POINT pt; GetCursorPos(&pt); SetForegroundWindow( hWnd ); 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) { case IDM_QUICKSTART: bTerminateVeto = bTerminateVeto ? false : true; NotifyListener( hWnd ); break; case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; } } break; } break; case WM_TIMER: if( wParam == UPDATE_TIMER ) { // update state NotifyListener( hWnd ); } break; case WM_DESTROY: // try to terminate office SendMessage( HWND_BROADCAST, aTerminateMessage, 0, 0L ); // delete taskbar icon NOTIFYICONDATA nid; nid.cbSize=sizeof(NOTIFYICONDATA); nid.hWnd = hWnd; nid.uID = IDM_QUICKSTART; Shell_NotifyIcon(NIM_DELETE, &nid); PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Mesage handler for about box. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; }