Создание системных ловушек Windows на Borland C++ Builder - Написание приложения, устанавливающего ловушку

ОГЛАВЛЕНИЕ

 

Написание приложения, устанавливающего ловушку.

Создание пустого приложения.

Для создания пустого приложения воспользоваться встроенным мастером. Для этого надо использовать пункт меню File->New: В появившемся окне необходимо выбрать "Console Wizard" и нажать кнопку "Ok". В новом диалоге в разделе "Source Type" следует оставить значение по умолчанию - "C++". Во втором разделе надо снять все флажки. По нажатию "Ок" приложение создаётся.

Создание главного окна.

Следующий этап - это создание главного окна приложения. Сначала надо зарегистрировать класс окна. После этого создать окно (подробности можно найти в "Win32 Programmer's Reference" в подразделах "RegisterClass" и "CreateWindow"). Всё это делает следующий код (описатель окна MainWnd определён глобально):

BOOL InitApplication(HINSTANCE hinstance,int nCmdShow)
{ // Создание главного окна
WNDCLASS wcx; // Класс окна
wcx.style=NULL;
wcx.lpfnWndProc=MainWndProc;
wcx.cbClsExtra=0;
wcx.cbWndExtra=0;
wcx.hInstance=hinstance;
wcx.hIcon=LoadIcon(hinstance,"MAINICON");
wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
wcx.hbrBackground=(HBRUSH)(COLOR_APPWORKSPACE);
wcx.lpszMenuName=NULL;
wcx.lpszClassName="HookWndClass";

if(RegisterClass(&wcx)) // Регистрируем класс
{
MainWnd=CreateWindow("HookWndClass","SSHook", /* Создаём окно */
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hinstance,NULL);
if(!MainWnd)
return FALSE;

return TRUE;
}
return false;
}

Обратите внимание на то, каким образом был получен значок класса: wcx.hIcon=LoadIcon(hinstance,"MAINICON"); Для того, чтобы это получилось надо включить в проект файл ресурсов (*.res), в котором должен находиться значок с именем "MAINICON".

Это окно никогда не появится на экране, поэтому оно имеет размеры и координаты, устанавливаемые по умолчанию. Оконная процедура такого окна необычайно проста:

  LRESULT CALLBACK MainWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,
LPARAM lParam)
{// Оконная процедура
switch (uMsg)
{
case WM_DESTROY:{PostQuitMessage(0); break;}
//------------
case MYWM_NOTIFY:
{
if(lParam==WM_RBUTTONUP)
PostQuitMessage(0);
break; // Правый щелчок на значке - завершаем
}
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;

Размещение значка в системной области.

Возникает естественный вопрос: если окно приложения никогда не появится на экране, то каким образом пользователь может управлять им (например, закрыть)? Для индикации работы приложения и для управления его работой поместим значок в системную область панели задач. Делается это следующей функцией:

void vfSetTrayIcon(HINSTANCE hInst)
{ // Значок в Tray
char* pszTip="Хранитель экрана и раскладка";// Это просто Hint
NotIconD.cbSize=sizeof(NOTIFYICONDATA);
NotIconD.hWnd=MainWnd;
NotIconD.uID=IDC_MYICON;
NotIconD.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
NotIconD.uCallbackMessage=MYWM_NOTIFY;
NotIconD.hIcon=LoadIcon(hInst,"MAINICON");
lstrcpyn(NotIconD.szTip,pszTip,sizeof(NotIconD.szTip));
Shell_NotifyIcon(NIM_ADD,&NotIconD);
}

Для корректной работы функции предварительно нужно определить уникальный номер значка (параметр NotIconD.uID) и его сообщение (параметр NotIconD.uCallbackMessage). Делаем это в области определения глобальных переменных:

#define MYWM_NOTIFY (WM_APP+100)
#define IDC_MYICON 1006
Сообщение значка будет обрабатываться в оконной процедуре главного окна (NotIconD.hWnd=MainWnd):
case MYWM_NOTIFY:
{
if(lParam==WM_RBUTTONUP)
PostQuitMessage(0);
break; // Правый щелчок на значке - завершаем
}

Этот код просто завершает работу приложения по щелчку правой кнопкой мыши на значке.

При завершении работы значок надо удалить:

void vfResetTrayIcon()
{// Удаляем значок
Shell_NotifyIcon(NIM_DELETE,&NotIconD);
}