Создайте новое приложение и поместите на форму одну единственную кнопку. Объявите следующие глобальные переменные: hBtn типа HWND и hHook типа HHOOK (обе инициализируйте значением NULL). В обработчике OnClick кнопки напишите следующий код:
if(hBtn)
{
MessageBox(Handle,"Button already created.",NULL,MB_OK|MB_ICONSTOP);
return;
}
HWND hListView=FindWindow("ProgMan",NULL);
hListView=GetWindow(hListView,GW_CHILD);
hListView=GetWindow(hListView,GW_CHILD);
hBtn=CreateWindow("BUTTON","My Button",WS_CHILD,0,0,200,30,hListView,NULL,NULL,NULL);
if(hBtn==NULL)
{
MessageBox(Handle,"Can't create button.",NULL,MB_OK|MB_ICONSTOP);
return;
}
ShowWindow(hBtn,SW_SHOW);
hHook=SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)CallWndProc,NULL, GetCurrentThreadId());
|
Первый параметр функции - класс окна, именно поэтому здесь указываем "BUTTON". Второй параметр - надпись на кнопке. Стиль кнопки обязательно устанавливаем в WS_CHILD, т. к. будущая кнопка должна стать дочерним окном для списка hListView. Следующие четыре параметра - координаты кнопки (x, y) и её размер (ширина, высота). То, что hListView будет являться родительским окном для кнопки, указываем в следующем параметре. Остальные параметры можно установить в NULL.
После вызова функции проверяем успешность создания кнопки. С помощью ShowWindow мы отображаем кнопку (по умолчанию она будет скрыта). Последний шаг - установка hook'а типа WH_CALLWNDPROC, который будет отлавливать сообщения, посланные с помощью функции SendMessage. В последнем параметре нужно передать именно полученный идентификатор текущего потока, а не ноль (с виду может показаться, что можно передать и ноль, т. к. всё равно для всех потоков ловушка не установится, но в Windows 2000, в отличие от Windows ME, hook при этом не работает). Осталось написать саму hook-процедуру, что сейчас и делаем.
Обратите внимание: код процедуры необходимо расположить выше OnClick-обработчика, или же нужно объявить прототип hook-процедуры, и тогда её код можно будет размеcтить в любом допустимом месте.
Hook-процедура:
LRESULT CALLBACK CallWndProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if(nCode==HC_ACTION)
{
LPCWPSTRUCT pStruct=((LPCWPSTRUCT)lParam);
if(pStruct->hwnd==hBtn && pStruct->message==BM_SETSTATE && !pStruct->wParam)
MessageBeep(MB_ICONWARNING);
}
return 0;
}
|
Параметр lParam содержит указатель на структуру типа CWPSTRUCT, содержащую нужные нам данные. Мы сравниваем дескриптор окна с дескриптором нашей кнопки, проверяем равенство сообщения константе BM_SETSTATE и равенство FALSE параметра wParam структуры. Если условие является верным, это означает, что именно нашей кнопке послано сообщение, после обработки которого она окажется в отжатом состоянии.
В таком случае воспроизводим один из стандартных звуков (при условии, что у вас есть звуковая плата и настроена звуковая схема Windows), который информирует о нажатии кнопки. Если же условие равно FALSE, то просто возвращаем 0, ничего более не делая.
В событии OnDestroy формы необходимо снять ловушку, если она была установлена.
Код:
if(hHook)UnhookWindowsHookEx(hHook); |