// Slightly modified to build out of the original package available at // http://www.codeproject.com/KB/shell/StealthDialog.aspx // Win32 Dialog.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #define TRAYICONID 1// ID number for the Notify Icon #define SWM_TRAYMSG WM_APP// the message ID sent to our window #define SWM_SHOW WM_APP + 1// show the window #define SWM_HIDE WM_APP + 2// hide the window #define SWM_EXIT WM_APP + 3// close the window #ifndef _MSC_VER #include int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow); //Win32 resource table (produced by wrc) extern DWORD Resource_PEResTab; int main(int argc, char **argv) { #ifdef ODIN_FORCE_WIN32_TIB ForceWin32TIB(); #endif RegisterLxExe((WINMAIN)_tWinMain, (PVOID)&Resource_PEResTab); } #endif // Global Variables: HINSTANCE hInst; // current instance NOTIFYICONDATA niData; // notify icon data // Forward declarations of functions included in this code module: BOOL InitInstance(HINSTANCE, int); BOOL OnInitDialog(HWND hWnd); void ShowContextMenu(HWND hWnd); ULONGLONG GetDllVersion(LPCTSTR lpszDllName); INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; HACCEL hAccelTable; // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) return FALSE; hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_STEALTHDIALOG); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)|| !IsDialogMessage(msg.hwnd,&msg) ) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // Add tray icon VOID AddTrayIcon(HWND hWnd) { // Fill the NOTIFYICONDATA structure and call Shell_NotifyIcon // zero the structure - note: Some Windows funtions require this but // I can't be bothered which ones do and // which ones don't. ZeroMemory(&niData,sizeof(NOTIFYICONDATA)); #ifndef __WIN32OS2__ // get Shell32 version number and set the size of the structure // note: the MSDN documentation about this is a little // dubious and I'm not at all sure if the method // bellow is correct ULONGLONG ullVersion = GetDllVersion(_T("Shell32.dll")); if(ullVersion >= MAKEDLLVERULL(5, 0,0,0)) niData.cbSize = sizeof(NOTIFYICONDATA); else niData.cbSize = NOTIFYICONDATA_V2_SIZE; #else niData.cbSize = sizeof(NOTIFYICONDATA); #endif // the ID number can be anything you choose niData.uID = TRAYICONID; // state which structure members are valid niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; // @todo: Note that there are two Odin-related bugs in this testcase // presently: // // 1. Requesting an icon of the small size (e.g. 16x16) in LoadImage // corrupts the result. Using LR_DEFAULTSIZE or requesting the // normal size works. // 2. StealthDialog.ico itself is strange. Both PMVIEW and Odin // display some garbage lines in the background (probably, a // transparency issue). The very same icon is shown on Win32 fine. // Changing it to some other icon (e.g. tree.ico from src/shell32/ico) // fixes the problem. // // Both problems need to be addressed one day. // load the icon niData.hIcon = (HICON)LoadImage(hInst,MAKEINTRESOURCE(IDI_STEALTHDLG), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); // the window to send messages to and the message to send // note: the message value should be in the // range of WM_APP through 0xBFFF niData.hWnd = hWnd; niData.uCallbackMessage = SWM_TRAYMSG; // tooltip message lstrcpyn(niData.szTip, _T("Time flies like an arrow but\n fruit flies like a banana!"), sizeof(niData.szTip)/sizeof(TCHAR)); Shell_NotifyIcon(NIM_ADD,&niData); // free icon handle if(niData.hIcon && DestroyIcon(niData.hIcon)) niData.hIcon = NULL; } // Initialize the window BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { // prepare for XP style controls InitCommonControls(); // store instance handle and create dialog hInst = hInstance; HWND hWnd = CreateDialog( hInstance, MAKEINTRESOURCE(IDD_DLG_DIALOG), NULL, (DLGPROC)DlgProc ); if (!hWnd) return FALSE; AddTrayIcon(hWnd); // call ShowWindow here to make the dialog initially visible return TRUE; } BOOL OnInitDialog(HWND hWnd) { HMENU hMenu = GetSystemMenu(hWnd,FALSE); if (hMenu) { AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); AppendMenu(hMenu, MF_STRING, IDM_ABOUT, _T("About")); } HICON hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_STEALTHDLG), IMAGE_ICON, 0,0, LR_SHARED|LR_DEFAULTSIZE); SendMessage(hWnd,WM_SETICON,ICON_BIG,(LPARAM)hIcon); SendMessage(hWnd,WM_SETICON,ICON_SMALL,(LPARAM)hIcon); return TRUE; } // Name says it all void ShowContextMenu(HWND hWnd) { POINT pt; GetCursorPos(&pt); HMENU hMenu = CreatePopupMenu(); if(hMenu) { if( IsWindowVisible(hWnd) ) InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION, SWM_HIDE, _T("Hide")); else InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION, SWM_SHOW, _T("Show")); InsertMenu(hMenu, (UINT)-1, MF_BYPOSITION, SWM_EXIT, _T("Exit")); // note: must set window to the foreground or the // menu won't disappear when it should SetForegroundWindow(hWnd); TrackPopupMenu(hMenu, TPM_BOTTOMALIGN, pt.x, pt.y, 0, hWnd, NULL ); DestroyMenu(hMenu); } } #ifndef __WIN32OS2__ // Get dll version number ULONGLONG GetDllVersion(LPCTSTR lpszDllName) { ULONGLONG ullVersion = 0; HINSTANCE hinstDll; hinstDll = LoadLibrary(lpszDllName); if(hinstDll) { DLLGETVERSIONPROC pDllGetVersion; pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); if(pDllGetVersion) { DLLVERSIONINFO dvi; HRESULT hr; ZeroMemory(&dvi, sizeof(dvi)); dvi.cbSize = sizeof(dvi); hr = (*pDllGetVersion)(&dvi); if(SUCCEEDED(hr)) ullVersion = MAKEDLLVERULL(dvi.dwMajorVersion, dvi.dwMinorVersion,0,0); } FreeLibrary(hinstDll); } return ullVersion; } #endif // Message handler for the app INT_PTR CALLBACK DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static UINT wmTaskbarCreated; int wmId, wmEvent; switch (message) { case SWM_TRAYMSG: switch(lParam) { case WM_LBUTTONDBLCLK: ShowWindow(hWnd, SW_RESTORE); break; case WM_RBUTTONDOWN: case WM_CONTEXTMENU: ShowContextMenu(hWnd); } break; case WM_SYSCOMMAND: if((wParam & 0xFFF0) == SC_MINIMIZE) { ShowWindow(hWnd, SW_HIDE); return 1; } else if(wParam == IDM_ABOUT) DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch (wmId) { case SWM_SHOW: ShowWindow(hWnd, SW_RESTORE); break; case SWM_HIDE: case IDOK: ShowWindow(hWnd, SW_HIDE); break; case SWM_EXIT: DestroyWindow(hWnd); break; case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; } return 1; case WM_INITDIALOG: wmTaskbarCreated = RegisterWindowMessage(TEXT("TaskbarCreated")); return OnInitDialog(hWnd); case WM_CLOSE: DestroyWindow(hWnd); break; case WM_DESTROY: niData.uFlags = 0; Shell_NotifyIcon(NIM_DELETE,&niData); PostQuitMessage(0); break; default: if (message == wmTaskbarCreated) AddTrayIcon(hWnd); break; } return 0; } // Message handler for about box. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; }