Создайте новое приложение и поместите на форму одну единственную кнопку. Объявите следующие глобальные переменные: 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); |