1 // QuickStart.cpp : Defines the entry point for the application. 2 // 3 4 #include "stdafx.h" 5 #include "resource.h" 6 #include <systools/win32/uwinapi.h> 7 #include <stdio.h> 8 9 #define MY_TASKBAR_NOTIFICATION WM_USER+1 10 11 #define MAX_LOADSTRING 100 12 13 // message used to communicate with soffice 14 #define TERMINATIONVETO_MESSAGE "SO TerminationVeto" 15 #define TERMINATE_MESSAGE "SO Terminate" 16 #define LISTENER_WINDOWCLASS "SO Listener Class" 17 #define KILLTRAY_MESSAGE "SO KillTray" 18 19 static UINT aTerminationVetoMessage = 0x7FFF; 20 static UINT aTerminateMessage = 0x7FFF; 21 static HMENU popupMenu = NULL; 22 static bool bTerminateVeto = true; 23 24 #define UPDATE_TIMER 1 25 26 // Global Variables: 27 HINSTANCE hInst; // current instance 28 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text 29 TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text 30 31 TCHAR szExitString[MAX_LOADSTRING]; 32 TCHAR szTooltipString[MAX_LOADSTRING]; 33 34 // Foward declarations of functions included in this code module: 35 ATOM MyRegisterClass(HINSTANCE hInstance); 36 BOOL InitInstance(HINSTANCE, int); 37 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 38 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); 39 40 bool SofficeRuns() 41 { 42 // check for soffice by searching the communication window 43 return ( FindWindowEx( NULL, NULL, LISTENER_WINDOWCLASS, NULL ) == NULL ) ? false : true; 44 } 45 46 bool launchSoffice( ) 47 { 48 if ( !SofficeRuns() ) 49 { 50 // UINT ret = WinExec( "h:\\office60.630b\\program\\swriter.exe -bean", SW_SHOW ); 51 char filename[_MAX_PATH + 1]; 52 53 filename[_MAX_PATH] = 0; 54 GetModuleFileName( NULL, filename, _MAX_PATH ); // soffice resides in the same dir 55 char *p = strrchr( filename, '\\' ); 56 if ( !p ) 57 return false; 58 59 strncpy( p+1, "soffice.exe", _MAX_PATH - (p+1 - filename) ); 60 61 char imagename[_MAX_PATH + 1]; 62 63 imagename[_MAX_PATH] = 0; 64 _snprintf(imagename, _MAX_PATH, "\"%s\" -quickstart", filename ); 65 66 UINT ret = WinExec( imagename, SW_SHOW ); 67 if ( ret < 32 ) 68 return false; 69 /* 70 // wait until we can communicate 71 int retry = 30; 72 while (retry-- && !SofficeRuns() ) 73 Sleep(1000); 74 75 return SofficeRuns(); 76 */ 77 return true; 78 } 79 else 80 return true; 81 } 82 83 void NotifyListener( HWND hWnd ) 84 { 85 static HICON hIconActive=NULL; 86 //static HICON hIconInActive=NULL; 87 88 if( !hIconActive ) 89 { 90 hIconActive = (HICON)LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_ACTIVE ), 91 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), 92 LR_DEFAULTCOLOR | LR_SHARED ); 93 94 /* hIconInActive = (HICON)LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_INACTIVE ), 95 IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), 96 LR_DEFAULTCOLOR | LR_SHARED ); 97 */ 98 } 99 100 NOTIFYICONDATA nid; 101 nid.cbSize = sizeof(NOTIFYICONDATA); 102 nid.hWnd = hWnd; 103 nid.uID = IDM_QUICKSTART; 104 nid.szTip[elementsof(nid.szTip) - 1] = 0; 105 // nid.hIcon = bTerminateVeto ? hIconActive : hIconInActive; 106 // strncpy(nid.szTip, bTerminateVeto ? STRING_QUICKSTARTACTIVE : STRING_QUICKSTARTINACTIVE, elementsof(nid.szTip) - 1 ); 107 nid.hIcon = hIconActive; 108 strncpy(nid.szTip, szTooltipString, elementsof(nid.szTip) - 1); 109 nid.uFlags = NIF_TIP|NIF_ICON; 110 111 // update systray 112 Shell_NotifyIcon( NIM_MODIFY, &nid ); 113 //CheckMenuItem( popupMenu, IDM_QUICKSTART, bTerminateVeto ? MF_CHECKED : MF_UNCHECKED ); 114 115 // notify listener 116 SendMessage( HWND_BROADCAST, aTerminationVetoMessage, (WORD) bTerminateVeto, 0L ); 117 } 118 119 120 121 int APIENTRY WinMain(HINSTANCE hInstance, 122 HINSTANCE /*hPrevInstance*/, 123 LPSTR /*lpCmdLine*/, 124 int nCmdShow) 125 { 126 // Look for -killtray argument 127 128 for ( int i = 1; i < __argc; i++ ) 129 { 130 if ( 0 == strcmp( __argv[i], "-killtray" ) ) 131 { 132 HWND hwndTray = FindWindow( LISTENER_WINDOWCLASS, NULL ); 133 134 if ( hwndTray ) 135 { 136 UINT uMsgKillTray = RegisterWindowMessage( KILLTRAY_MESSAGE ); 137 SendMessage( hwndTray, uMsgKillTray, 0, 0 ); 138 } 139 140 return 0; 141 } 142 } 143 144 launchSoffice(); 145 return 0; 146 147 // TODO: Place code here. 148 MSG msg; 149 HACCEL hAccelTable; 150 aTerminationVetoMessage = RegisterWindowMessage( TERMINATIONVETO_MESSAGE ); 151 aTerminateMessage = RegisterWindowMessage( TERMINATE_MESSAGE ); 152 153 // Initialize global strings 154 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 155 LoadString(hInstance, IDC_QUICKSTART, szWindowClass, MAX_LOADSTRING); 156 157 LoadString(hInstance, IDS_EXIT, szExitString, MAX_LOADSTRING); 158 LoadString(hInstance, IDS_TOOLTIP, szTooltipString, MAX_LOADSTRING); 159 160 MyRegisterClass(hInstance); 161 162 // Perform application initialization: 163 if (!InitInstance (hInstance, nCmdShow)) 164 { 165 return FALSE; 166 } 167 168 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_QUICKSTART); 169 170 // Main message loop: 171 while (GetMessage(&msg, NULL, 0, 0)) 172 { 173 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 174 { 175 TranslateMessage(&msg); 176 DispatchMessage(&msg); 177 } 178 } 179 180 return msg.wParam; 181 } 182 183 184 185 // 186 // FUNCTION: MyRegisterClass() 187 // 188 // PURPOSE: Registers the window class. 189 // 190 // COMMENTS: 191 // 192 // This function and its usage is only necessary if you want this code 193 // to be compatible with Win32 systems prior to the 'RegisterClassEx' 194 // function that was added to Windows 95. It is important to call this function 195 // so that the application will get 'well formed' small icons associated 196 // with it. 197 // 198 ATOM MyRegisterClass(HINSTANCE hInstance) 199 { 200 WNDCLASSEX wcex; 201 202 wcex.cbSize = sizeof(WNDCLASSEX); 203 204 wcex.style = CS_HREDRAW | CS_VREDRAW; 205 wcex.lpfnWndProc = (WNDPROC)WndProc; 206 wcex.cbClsExtra = 0; 207 wcex.cbWndExtra = 0; 208 wcex.hInstance = hInstance; 209 wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_QUICKSTART); 210 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 211 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 212 wcex.lpszMenuName = NULL; 213 wcex.lpszClassName = szWindowClass; 214 wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); 215 216 return RegisterClassEx(&wcex); 217 } 218 219 // 220 // FUNCTION: InitInstance(HANDLE, int) 221 // 222 // PURPOSE: Saves instance handle and creates main window 223 // 224 // COMMENTS: 225 // 226 // In this function, we save the instance handle in a global variable and 227 // create and display the main program window. 228 // 229 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 230 { 231 HWND hWnd; 232 233 hInst = hInstance; // Store instance handle in our global variable 234 235 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 236 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 237 238 if (!hWnd) 239 { 240 return FALSE; 241 } 242 243 nCmdShow = SW_HIDE; // hide main window, we only need the taskbar icon 244 ShowWindow(hWnd, nCmdShow); 245 UpdateWindow(hWnd); 246 247 return TRUE; 248 } 249 250 // 251 // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) 252 // 253 // PURPOSE: Processes messages for the main window. 254 // 255 // WM_COMMAND - process the application menu 256 // WM_PAINT - Paint the main window 257 // WM_DESTROY - post a quit message and return 258 // 259 // 260 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 261 { 262 switch (message) 263 { 264 case WM_CREATE: 265 { 266 // make sure soffice runs 267 if( !launchSoffice() ) 268 return -1; 269 270 // create popup menu 271 popupMenu = CreatePopupMenu(); 272 static int count=0; 273 274 // Add my items 275 MENUITEMINFO mi; 276 mi.cbSize = sizeof(MENUITEMINFO); 277 mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; 278 mi.fType=MFT_STRING; 279 mi.fState=MFS_ENABLED|MFS_DEFAULT; 280 mi.wID = IDM_QUICKSTART; 281 mi.hSubMenu=NULL; 282 mi.hbmpChecked=NULL; 283 mi.hbmpUnchecked=NULL; 284 mi.dwItemData=NULL; 285 mi.dwTypeData = "QuickStart"; 286 mi.cch = strlen(mi.dwTypeData); 287 // InsertMenuItem(popupMenu, count++, TRUE, &mi); 288 289 mi.cbSize = sizeof(MENUITEMINFO); 290 mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; 291 mi.fType=MFT_STRING; 292 mi.fState=MFS_ENABLED; 293 mi.wID = IDM_ABOUT; 294 mi.hSubMenu=NULL; 295 mi.hbmpChecked=NULL; 296 mi.hbmpUnchecked=NULL; 297 mi.dwItemData=NULL; 298 mi.dwTypeData = "Info..."; 299 mi.cch = strlen(mi.dwTypeData); 300 // InsertMenuItem(popupMenu, count++, TRUE, &mi); 301 302 mi.cbSize = sizeof(MENUITEMINFO); 303 mi.fMask=MIIM_TYPE; 304 mi.fType=MFT_SEPARATOR; 305 mi.hSubMenu=NULL; 306 mi.hbmpChecked=NULL; 307 mi.hbmpUnchecked=NULL; 308 mi.dwItemData=NULL; 309 // InsertMenuItem(popupMenu, count++, TRUE, &mi); 310 311 mi.cbSize = sizeof(MENUITEMINFO); 312 mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; 313 mi.fType=MFT_STRING; 314 mi.fState=MFS_ENABLED; 315 mi.wID = IDM_EXIT; 316 mi.hSubMenu=NULL; 317 mi.hbmpChecked=NULL; 318 mi.hbmpUnchecked=NULL; 319 mi.dwItemData=NULL; 320 mi.dwTypeData = szExitString; 321 mi.cch = strlen(mi.dwTypeData); 322 InsertMenuItem(popupMenu, count++, TRUE, &mi); 323 324 // add taskbar icon 325 NOTIFYICONDATA nid; 326 nid.cbSize = sizeof(NOTIFYICONDATA); 327 nid.hWnd = hWnd; 328 nid.uID = IDM_QUICKSTART; 329 nid.uFlags = NIF_MESSAGE; 330 nid.uCallbackMessage=MY_TASKBAR_NOTIFICATION; 331 Shell_NotifyIcon(NIM_ADD, &nid); 332 333 // and update state 334 NotifyListener( hWnd ); 335 336 // check for soffice 337 SetTimer(hWnd, UPDATE_TIMER, 3000, NULL); 338 } 339 break; 340 341 case MY_TASKBAR_NOTIFICATION: // message from taskbar 342 switch(lParam) 343 { 344 /* 345 case WM_LBUTTONDBLCLK: 346 bTerminateVeto = bTerminateVeto ? false : true; 347 NotifyListener( hWnd ); 348 break; 349 */ 350 351 case WM_LBUTTONDOWN: 352 case WM_RBUTTONDOWN: 353 { 354 POINT pt; 355 GetCursorPos(&pt); 356 SetForegroundWindow( hWnd ); 357 int m = TrackPopupMenuEx(popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON, 358 pt.x, pt.y, hWnd, NULL); 359 // BUGFIX: See Q135788 (PRB: Menus for Notification Icons Don't Work Correctly) 360 PostMessage(hWnd, NULL, 0, 0); 361 switch(m) 362 { 363 case IDM_QUICKSTART: 364 bTerminateVeto = bTerminateVeto ? false : true; 365 NotifyListener( hWnd ); 366 break; 367 case IDM_ABOUT: 368 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); 369 break; 370 case IDM_EXIT: 371 DestroyWindow(hWnd); 372 break; 373 } 374 } 375 break; 376 } 377 break; 378 379 case WM_TIMER: 380 if( wParam == UPDATE_TIMER ) 381 { 382 // update state 383 NotifyListener( hWnd ); 384 } 385 break; 386 387 case WM_DESTROY: 388 // try to terminate office 389 SendMessage( HWND_BROADCAST, aTerminateMessage, 0, 0L ); 390 391 // delete taskbar icon 392 NOTIFYICONDATA nid; 393 nid.cbSize=sizeof(NOTIFYICONDATA); 394 nid.hWnd = hWnd; 395 nid.uID = IDM_QUICKSTART; 396 Shell_NotifyIcon(NIM_DELETE, &nid); 397 398 PostQuitMessage(0); 399 break; 400 default: 401 return DefWindowProc(hWnd, message, wParam, lParam); 402 } 403 return 0; 404 } 405 406 // Mesage handler for about box. 407 LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM) 408 { 409 switch (message) 410 { 411 case WM_INITDIALOG: 412 return TRUE; 413 414 case WM_COMMAND: 415 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 416 { 417 EndDialog(hDlg, LOWORD(wParam)); 418 return TRUE; 419 } 420 break; 421 } 422 return FALSE; 423 } 424