C++Builder: Кнопка на рабочем столе


В этом примере я покажу, как можно создать кнопку прямо на рабочем столе и обработать событие её нажатия. Не знаю, насколько это будет полезно, но я ставил перед собой цель просто продемонстрировать работу с некоторыми функциями Windows API, и, возможно, кому-нибудь из читателей статьи это пригодится.

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

Код начинается с проверки, которая необходима для предотвращения повторного создания кнопки. Далее мы получаем дескриптор списка с файлами, находящегося на рабочем столе. После этого создаём кнопку, применяя стандартную функцию CreateWindow.

Первый параметр функции - класс окна, именно поэтому здесь указываем "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);

И последнее: в данном примере есть один недостаток: если установить фокус ввода на кнопку и нажать Alt+F4, то вместе с кнопкой исчезнут также все пиктограммы рабочего стола. Не знаю, на всех ли версиях Windows это будет присутствовать (испытывалось в WinME и Win2000).


Hosted by uCoz