Данный пример представляет собой небольшую программку, при запуске которой, в строке статуса (там где в Windows показывается время) появляется иконка, которая может обрабатывать различные события, такие как двойное нажатие мышкой, и нажатие правой кнопкой на иконке. Соответственно в зависимости от события, главный модуль программы выполняет определённые действия (открытие всплывающего меню либо открытие различных диалоговых окон и т.д.) Исходный текст был откомпилирован в Visual C++ 4.2. Выбор данного компилятора ни чем не обоснован, просто мне удобно в нём работать, вот и всё. А теперь по-порядку. Сразу представлю исходный код , а в конце подробно его прокомментирую. Листинг 1 (status_ico.cpp) #include <windows.h> #include <windowsx.h>
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct); void WndProc_OnDestroy(HWND hWnd); void AddStatusIcon(HWND hWnd, DWORD dwMessage); void HandlePopupMenu (HWND hwnd, POINT point);
#define WM_NOTIFYICONMSG (WM_USER + 2)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; HWND hWnd; WNDCLASSEX wndclass;
hInst = hInstance;
wndclass.style = 0; wndclass.lpfnWndProc = (WNDPROC)WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInst; wndclass.hIcon = NULL; wndclass.hCursor = NULL; wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "WSCLAS";
if(!RegisterClassEx(&wndclass)) if(!RegisterClass((LPWNDCLASS)&wndclass.style)) return FALSE;
hWnd=CreateWindow("WSCLAS", "", 0, 0, 0, 1, 1, HWND_DESKTOP, NULL, hInst, NULL);
AddStatusIcon(hWnd, NIM_ADD);
while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
return msg.wParam; }
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { POINT pt;
case WM_NOTIFYICONMSG: switch(lParam) { case WM_LBUTTONDBLCLK: MessageBox(NULL, "Двойной щелчок по иконке", "Сообщение от иконки", MB_OK); break;
case WM_RBUTTONDOWN:// нажатие на иконку правой кнопкой мыши GetCursorPos(&pt);//вычисляем текущее положение курсора HandlePopupMenu (hWnd, pt); //рисуем меню от координат курсора break;
default: break; } break;
HANDLE_MSG(hWnd, WM_CREATE, WndProc_OnCreate);//стандартный обработчик создания окна HANDLE_MSG(hWnd, WM_DESTROY, WndProc_OnDestroy);//стандартный обработчик уничтожения окна
default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return 0; }
BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct) { return TRUE; }
void WndProc_OnDestroy(HWND hWnd) { PostQuitMessage(0); }
void AddStatusIcon(HWND hWnd, DWORD dwMessage) { HICON hStatusIcon;// Хэндл иконки в статус-баре LPCSTR pszIDStatusIcon;// Указатель на Иконку в статус-баре NOTIFYICONDATA tnd;
pszIDStatusIcon = MAKEINTRESOURCE(IDI_ICON1);
hStatusIcon = LoadIcon( hInst,pszIDStatusIcon ); tnd.cbSize = sizeof(NOTIFYICONDATA); tnd.hWnd = hWnd; tnd.uID = 1; tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; tnd.uCallbackMessage = WM_NOTIFYICONMSG; tnd.hIcon = hStatusIcon; lstrcpyn(tnd.szTip, "Пример", sizeof(tnd.szTip)); Shell_NotifyIcon( dwMessage, &tnd ); }
void HandlePopupMenu (HWND hWnd, POINT point) { HMENU hMenu; HMENU hMenuTrackPopup; LPCSTR pszIDMenu;
pszIDMenu = MAKEINTRESOURCE(IDM_POPUPMENU1); hMenu = LoadMenu (hInst, pszIDMenu); if (!hMenu) return; hMenuTrackPopup = GetSubMenu (hMenu, 0); TrackPopupMenu (hMenuTrackPopup, 0, point.x, point.y, 0, hWnd, NULL); DestroyMenu (hMenu); }
Комментарии: В самом начале идёт обязательное включение Виндузовых заголовков (как и в любой программе под Windows. Далее я объявляю используемые в программе функции. Обычно такое объявление делается в файле-заголовке (.h) , но когда функций не так много, то я обычно эти описания вставляю в главный файл. Описание главной функции WinMain не нужно добавлять. Далее идёт определение идентификатора сообщения (#define WM_NOTIFYICONMSG (WM_USER + 2)), которое будет поступать от иконки. Впринципе этому идентификатору можно приствоить любое число, но чтобы быть уверенным, что такое число не используется каким-нибудь другим идентификатором, обычно присваивают WM_USER + n , где n - любое число. Далее идёт основная функция, с которой начинает работать данная программа. Вообще-то в разных версиях API данная функция описывается по-разному. Например в API 16 её описание начинается с дескриптора PASCAL, но в API 32 - это WINAPI. Следующим шагом программа создаёт окно, но не простое, а невидимое. То есть запущенная программа не будет видна в панели задач. Вообще процесс создания окна в Windows состоит из двух шагов. Первый ( RegisterClassEx(&wndclass) )- это регистрация класса окна в системе, и второй ( hWnd=CreateWindow(.... )- создание непосредственно окна. Параметр wndclass.lpfnWndProc = (WNDPROC)WndProc; указывает классу окна, что все сообщения, поступающие окну будут обрабатываться функцией WndProc. Все описания данных функций и их входных параметров Вы можете найти во многих книгах по программированию в API 32, поэтому здесь я не буду отвлекаться на эти вопросы. Далее вызывается функция AddStatusIcon(hWnd, NIM_ADD) , задача которой заключается в том, чтобы нарисовать в панели статуса нужную иконку. Параметр hWnd означает, что все сообщения (...нажатия на ней мышкой...) от иконки будут передаваться главному окну нашей программы. Параметр NIM_ADD указывает функции, что иконка будет добавлена в статус-бар. Этот параметр может принимать значение NIM_MODIFY, означающий, что уже существующая иконка будет изменена или будет изменена её информационная надпись, которая появляется при навидении на иконку мышкой. И наконец функция WinMain завершается бесконечным циклом, задача которого обрабатывать сообщения, поступающие главному окну. Естевственно этот цикл не такой уж и бесконечный, при поступлении определённых сообщений (например WM_CLOSE ) цикл может звершиться, и соответственно завершится сама программа. Например, если послать окну сообщение WM_DESTROY , то функция обработки оконных сообщений ( WndProc ) вызовет WndProc_OnDestroy , и наша программа завершит свою работу в системе. Соответственно при создании окна окно получает сообщение WM_CREATE и оконная функция вызывает WndProc_OnCreate(). Ещё можно добавить, что все неопознанные сообщения, или те, для которых Вы не предусмотрите обработчики сообщений напрвляются DefWindowProc(hWnd, msg, wParam, lParam) , вызов каторой находится в конце WndProc. |