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