source: trunk/testapp/gui/systray/StealthDialog.cpp@ 21593

Last change on this file since 21593 was 21593, checked in by dmik, 15 years ago

testapp/systray: Added a todo.

  • Property svn:eol-style set to native
File size: 7.8 KB
Line 
1// Slightly modified to build out of the original package available at
2// http://www.codeproject.com/KB/shell/StealthDialog.aspx
3
4// Win32 Dialog.cpp : Defines the entry point for the application.
5//
6
7#include "stdafx.h"
8#include "resource.h"
9
10#define TRAYICONID 1// ID number for the Notify Icon
11#define SWM_TRAYMSG WM_APP// the message ID sent to our window
12
13#define SWM_SHOW WM_APP + 1// show the window
14#define SWM_HIDE WM_APP + 2// hide the window
15#define SWM_EXIT WM_APP + 3// close the window
16
17#ifndef _MSC_VER
18
19#include <odinlx.h>
20
21int APIENTRY _tWinMain(HINSTANCE hInstance,
22 HINSTANCE hPrevInstance,
23 LPTSTR lpCmdLine,
24 int nCmdShow);
25
26//Win32 resource table (produced by wrc)
27extern DWORD Resource_PEResTab;
28
29int main(int argc, char **argv)
30{
31 EnableSEH();
32 RegisterLxExe((WINMAIN)_tWinMain, (PVOID)&Resource_PEResTab);
33}
34
35#endif
36
37// Global Variables:
38HINSTANCE hInst; // current instance
39NOTIFYICONDATA niData; // notify icon data
40
41// Forward declarations of functions included in this code module:
42BOOL InitInstance(HINSTANCE, int);
43BOOL OnInitDialog(HWND hWnd);
44void ShowContextMenu(HWND hWnd);
45ULONGLONG GetDllVersion(LPCTSTR lpszDllName);
46
47INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
48LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
49
50int APIENTRY _tWinMain(HINSTANCE hInstance,
51 HINSTANCE hPrevInstance,
52 LPTSTR lpCmdLine,
53 int nCmdShow)
54{
55 MSG msg;
56 HACCEL hAccelTable;
57
58 // Perform application initialization:
59 if (!InitInstance (hInstance, nCmdShow)) return FALSE;
60 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_STEALTHDIALOG);
61
62 // Main message loop:
63 while (GetMessage(&msg, NULL, 0, 0))
64 {
65 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)||
66 !IsDialogMessage(msg.hwnd,&msg) )
67 {
68 TranslateMessage(&msg);
69 DispatchMessage(&msg);
70 }
71 }
72 return (int) msg.wParam;
73}
74
75// Initialize the window and tray icon
76BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
77{
78 // prepare for XP style controls
79 InitCommonControls();
80
81 // store instance handle and create dialog
82 hInst = hInstance;
83 HWND hWnd = CreateDialog( hInstance, MAKEINTRESOURCE(IDD_DLG_DIALOG),
84 NULL, (DLGPROC)DlgProc );
85 if (!hWnd) return FALSE;
86
87 // Fill the NOTIFYICONDATA structure and call Shell_NotifyIcon
88
89 // zero the structure - note: Some Windows funtions require this but
90 // I can't be bothered which ones do and
91 // which ones don't.
92 ZeroMemory(&niData,sizeof(NOTIFYICONDATA));
93
94#ifndef __WIN32OS2__
95 // get Shell32 version number and set the size of the structure
96 // note: the MSDN documentation about this is a little
97 // dubious and I'm not at all sure if the method
98 // bellow is correct
99 ULONGLONG ullVersion = GetDllVersion(_T("Shell32.dll"));
100 if(ullVersion >= MAKEDLLVERULL(5, 0,0,0))
101 niData.cbSize = sizeof(NOTIFYICONDATA);
102 else niData.cbSize = NOTIFYICONDATA_V2_SIZE;
103#else
104 niData.cbSize = sizeof(NOTIFYICONDATA);
105#endif
106
107 // the ID number can be anything you choose
108 niData.uID = TRAYICONID;
109
110 // state which structure members are valid
111 niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
112
113 // @todo: Note that there are two Odin-related bugs in this testcase
114 // presently:
115 //
116 // 1. Requesting an icon of the small size (e.g. 16x16) in LoadImage
117 // corrupts the result. Using LR_DEFAULTSIZE or requesting the
118 // normal size works.
119 // 2. StealthDialog.ico itself is strange. Both PMVIEW and Odin
120 // display some garbage lines in the background (probably, a
121 // transparency issue). The very same icon is shown on Win32 fine.
122 // Changing it to some other icon (e.g. tree.ico from src/shell32/ico)
123 // fixes the problem.
124 //
125 // Both problems need to be addressed one day.
126
127 // load the icon
128 niData.hIcon = (HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_STEALTHDLG),
129 IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),
130 LR_DEFAULTCOLOR);
131
132 // the window to send messages to and the message to send
133 // note: the message value should be in the
134 // range of WM_APP through 0xBFFF
135 niData.hWnd = hWnd;
136 niData.uCallbackMessage = SWM_TRAYMSG;
137
138 // tooltip message
139 lstrcpyn(niData.szTip, _T("Time flies like an arrow but\n fruit flies like a banana!"), sizeof(niData.szTip)/sizeof(TCHAR));
140
141 Shell_NotifyIcon(NIM_ADD,&niData);
142
143 // free icon handle
144 if(niData.hIcon && DestroyIcon(niData.hIcon))
145 niData.hIcon = NULL;
146
147 // call ShowWindow here to make the dialog initially visible
148
149 return TRUE;
150}
151
152BOOL OnInitDialog(HWND hWnd)
153{
154 HMENU hMenu = GetSystemMenu(hWnd,FALSE);
155 if (hMenu)
156 {
157 AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
158 AppendMenu(hMenu, MF_STRING, IDM_ABOUT, _T("About"));
159 }
160 HICON hIcon = (HICON)LoadImage(hInst,
161 MAKEINTRESOURCE(IDI_STEALTHDLG),
162 IMAGE_ICON, 0,0, LR_SHARED|LR_DEFAULTSIZE);
163printf("### hIcon %x\n", hIcon);
164 SendMessage(hWnd,WM_SETICON,ICON_BIG,(LPARAM)hIcon);
165 SendMessage(hWnd,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
166 return TRUE;
167}
168
169// Name says it all
170void ShowContextMenu(HWND hWnd)
171{
172 POINT pt;
173 GetCursorPos(&pt);
174 HMENU hMenu = CreatePopupMenu();
175 if(hMenu)
176 {
177 if( IsWindowVisible(hWnd) )
178 InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION, SWM_HIDE, _T("Hide"));
179 else
180 InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION, SWM_SHOW, _T("Show"));
181 InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION, SWM_EXIT, _T("Exit"));
182
183 // note: must set window to the foreground or the
184 // menu won't disappear when it should
185 SetForegroundWindow(hWnd);
186
187 TrackPopupMenu(hMenu, TPM_BOTTOMALIGN,
188 pt.x, pt.y, 0, hWnd, NULL );
189 DestroyMenu(hMenu);
190 }
191}
192
193#ifndef __WIN32OS2__
194// Get dll version number
195ULONGLONG GetDllVersion(LPCTSTR lpszDllName)
196{
197 ULONGLONG ullVersion = 0;
198 HINSTANCE hinstDll;
199 hinstDll = LoadLibrary(lpszDllName);
200 if(hinstDll)
201 {
202 DLLGETVERSIONPROC pDllGetVersion;
203 pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");
204 if(pDllGetVersion)
205 {
206 DLLVERSIONINFO dvi;
207 HRESULT hr;
208 ZeroMemory(&dvi, sizeof(dvi));
209 dvi.cbSize = sizeof(dvi);
210 hr = (*pDllGetVersion)(&dvi);
211 if(SUCCEEDED(hr))
212 ullVersion = MAKEDLLVERULL(dvi.dwMajorVersion, dvi.dwMinorVersion,0,0);
213 }
214 FreeLibrary(hinstDll);
215 }
216 return ullVersion;
217}
218#endif
219
220// Message handler for the app
221INT_PTR CALLBACK DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
222{
223 int wmId, wmEvent;
224
225 switch (message)
226 {
227 case SWM_TRAYMSG:
228 switch(lParam)
229 {
230 case WM_LBUTTONDBLCLK:
231 ShowWindow(hWnd, SW_RESTORE);
232 break;
233 case WM_RBUTTONDOWN:
234 case WM_CONTEXTMENU:
235 ShowContextMenu(hWnd);
236 }
237 break;
238 case WM_SYSCOMMAND:
239 if((wParam & 0xFFF0) == SC_MINIMIZE)
240 {
241 ShowWindow(hWnd, SW_HIDE);
242 return 1;
243 }
244 else if(wParam == IDM_ABOUT)
245 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
246 break;
247 case WM_COMMAND:
248 wmId = LOWORD(wParam);
249 wmEvent = HIWORD(wParam);
250
251 switch (wmId)
252 {
253 case SWM_SHOW:
254 ShowWindow(hWnd, SW_RESTORE);
255 break;
256 case SWM_HIDE:
257 case IDOK:
258 ShowWindow(hWnd, SW_HIDE);
259 break;
260 case SWM_EXIT:
261 DestroyWindow(hWnd);
262 break;
263 case IDM_ABOUT:
264 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
265 break;
266 }
267 return 1;
268 case WM_INITDIALOG:
269 return OnInitDialog(hWnd);
270 case WM_CLOSE:
271 DestroyWindow(hWnd);
272 break;
273 case WM_DESTROY:
274 niData.uFlags = 0;
275 Shell_NotifyIcon(NIM_DELETE,&niData);
276 PostQuitMessage(0);
277 break;
278 }
279 return 0;
280}
281
282// Message handler for about box.
283LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
284{
285 switch (message)
286 {
287 case WM_INITDIALOG:
288 return TRUE;
289
290 case WM_COMMAND:
291 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
292 {
293 EndDialog(hDlg, LOWORD(wParam));
294 return TRUE;
295 }
296 break;
297 }
298 return FALSE;
299}
Note: See TracBrowser for help on using the repository browser.