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 // Forward 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 
SofficeRuns()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 
launchSoffice()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 
NotifyListener(HWND hWnd)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 
WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int nCmdShow)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 //
MyRegisterClass(HINSTANCE hInstance)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 //
InitInstance(HINSTANCE hInstance,int nCmdShow)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 //
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)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.
About(HWND hDlg,UINT message,WPARAM wParam,LPARAM)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