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