Рейтинговые книги
Читем онлайн Программирование на Visual C++. Архив рассылки - Алекс Jenter

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 35 36 37 38 39 40 41 42 43 ... 156

Q. Как в Win9x и WinNT заблокировать клавиши WIN, Alt+Tab, Ctrl+Esc etc.?

Mike Krasnik 

A1 Например так – в конструкторе главного окна приложения зарегистрировать HotKey:

m_HK = GlobalAddAtom("alttab"); // DWORD m_HK;

RegisterHotKey(GetSafeHwnd(), m_HK, MOD_ALT, VK_TAB); 

а в деструкторе не забыть его разрегистрировать: 

UnregisterHotKey(GetSafeHwnd(), m_HK); 

так как никакого обработчика для этого HotKey мы не делаем, то соответственно и происходить по нажатию Alt-Tab ничего не будет.

Алексей Кирюшкин 

A2 По материалам http://msdn.microsoft.com/msdnmag/issues/0700/Win32/Win320700.asp

В WinNT (начиная с Windows NTR 4.0 Service Pack 3) существует возможность использовать "low-level" hook на клавиатуру WH_ KEYBOARD_LL для отключения комбинаций Ctrl+Esc, Alt+Tab, Alt+Esc.

Для данной данной функии установлен лимит времени: Система возвращается в нормальное состояние через промежуток времени определяемый параметром LowLevelHooksTimeout в HKEY_CURRENT_USERControl PanelDesktop время указывается в милисекундах.

Владимир Згурский 

A3 Это делается очень по-разному в различных системах от Microsoft.

В Windows 9x можно использовать трюк, опсанный в MSDN – вызвать функцию SystemParametersInfo с недокументированным параметром. В данном случае им можно пользоваться смело: Микрософт больше не будет вносить изменений в архитектуру Win9x. Чтобы отключить Alt+Tab, Ctrl+Alt+Del и т. д., нужно написать: 

int prev;

SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, &prev, 0); 

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

int prev;

SystemParametersInfo(SPI_SCREENSAVERRUNNING, FALSE, &prev, 0); 

Внимание: если этого не сделать, переключение задач будет невозможно даже после завершения работы вашего приложения! 

Перейдём к Windows NT/2000. Там трюк со скрин сейвером не работает, но зато есть низкоуровневые хуки для мыши и клавиатуры (обычные хуки не перехватывают системные комбинации клавиш). Установив глобальный низкоуровневый хук на клавиатуру, можно "съесть" все системные нажатия (кроме Ctrl+Alt+Del). Для этого в ответ на приход таких нажатий функция хука должна вернуть единицу. 

Как известно, хуки устанавливаются функцией SetWindowsHookEx. В нашем случае требуется глобальный хук, а значит, его код придётся размещать в DLL. DLL может выглядеть примерно так. 

#define _WIN32_WINNT 0x0500

#include <windows.h>

static HINSTANCE hInstance;

static HHOOK     hHook;

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {

 hInstance = (HINSTANCE)hModule;

 return TRUE;

}

LRESULT CALLBACK KeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam);

extern "C" __declspec(dllexport) void HookKeyboard() {

 hHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardProc, hInstance, 0);

}

extern "C" __declspec(dllexport) void UnhookKeyboard() {

 UnhookWindowsHookEx(hHook);

}

LRESULT CALLBACK KeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam) {

 KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT*)lParam;

 BOOL bControlKeyDown = 0;

 if (nCode == HC_ACTION) {

  bControlKeyDown = GetAsyncKeyState(VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);

  // Проверяем CTRL+ESC

  if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown) return 1;

  // Проверяем ALT+TAB

  if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN) return 1;

  // Проверяем ALT+ESC

  if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN) return 1;

 }

 return CallNextHookEx(hHook, nCode, wParam, lParam);

}

Чтобы воспользоваться этой DLL, загрузите её любым способом, а затем вызывайте HookKeyboard, чтобы перехватывать комбинации клавиш, и UnhookKeyboard, чтобы прекратить перехват. 

В ранних версиях NT низкоуровневых хуков не было. В MSDN утверждается, что там от Alt+Tab там можно избавиться с помощью перерегистрации глобального акселератора на ту же комбинацию (посредством RegisterHotKey), но испытать это средство мне не удалось (нет под рукой NT3.51 или NT4.0 с SP 2 и ниже). Ctrl+Esc там не блокируется. 

Для полноты картины упомяну ещё одно непровереное средство, с помощью которого можно обезвредить Ctrl+Alt+Del под Windows NT/2000. Для этого нужно написать собственную GINA DLL. Если кого-нибудь интересуют подробности, сделайте в MSDN поиск по строке "GINA".

Александр Шаргин  ОБРАТНАЯ СВЯЗЬ 

Уважаемый Алекс.

Читая Вашу статью о DCOM я прочел:

"Строго говоря, COM не является спецификацией, привязанной к Win32. Теоретически, можно портировать ваши COM-объекты в Unix или любые другие ОС. Однако, я никогда не видел, чтобы COM применялась где-то за пределами сферы влияния Microsoft."

Могу подсказать ОС использующую COM/DCOM не из семейства Windows. Как ни странно это VxWorks, где COM/DCOM существует в виде одного из компонент ядра и обеспечивает все, что может быть положено на концепцию этой ОС.

Например из-за ограничений ОС (там по сути только один процесс с общей памятью, но со многими потоками-задачами) серверы могут быть только INPROC. Не поддержан (пока что) IDispatch, массивы в VARIANT. Зато теперь можно использовать DCOM-распределенные системы на основе смеси Windows и VxWorks, что очень удобно для управления realtime системами.

С уважением

Алексей Трошин 

На вопрос из выпуска №27 о пунктирной рамке вокруг кнопки: 

Предложенный Александром Шаргиным вариант с тулбаром врядли можно признать удовлетворительным. Диалог не получит сообщение от тулбара да и программное создание кнопки… Можно, конечно, но… :-( . Наиболее приемлемый выход – использование самопрорисовывающихся элементов управления. Достоинство этого метода – нарисовать можно всё, что угодно! :-))). А в вопросе Максима Чучуйко есть ещё подвопрос: А должна ли кнопка вообще получать фокус?.

В общем, плоскую кнопку, не получающую фокус совсем сделать достаточно просто:

1) Создаём класс

CFlatButton: public CButton;

2) Добавляем переменные:

protected:

 BOOL bMouseCaptured;

 CWnd* pOldFocus;

В конструкторе инициализируем:

 bMouseCaptured = FALSE;

 pOldFocus = NULL;

3) Добавляем методы:

protected:

 void CFlatButton::SetOldFocus() {

  // Закомментировать тело метода, если кнопка может получать фокус.

  if (pOldFocus) pOldFocus->SetFocus();

  pOldFocus =NULL;

}

Добавляем обработчики сообщений:

 void CFlatButton::OnSetFocus(CWnd* pOldWnd) {

  CButton::OnSetFocus(pOldWnd);

  if (!pOldFocus) // Дабы не было проблем с модальными окнами, вызываемыми по нажатию этой кнопки.

   pOldFocus = pOldWnd;

 }

 void CFlatButton::OnLButtonUp(UINT nFlags, CPoint point) {

  CButton::OnLButtonUp(nFlags, point);

  CRect rectBtn;

  GetClientRect(rectBtn);

  if (rectBtn.PtInRect(point) && GetCapture() != this) {

   bMouseCaptured = TRUE;

   SetCapture();

   Invalidate(FALSE);

  }

  SetOldFocus();

 }

 void CFlatButton::OnMouseMove(UINT nFlags, CPoint point) {

  CRect rectBtn;

  GetClientRect(rectBtn);

  if (rectBtn.PtInRect(point)) {

   BOOL bNeedUpdate =FALSE;

   if (!bMouseCaptured) bNeedUpdate = TRUE;

   bMouseCaptured = TRUE;

   SetCapture();

   if (bNeedUpdate) Invalidate(FALSE);

  } else {

   bMouseCaptured = FALSE;

   ReleaseCapture();

   SetOldFocus();

   Invalidate(FALSE);

  }

  CButton::OnMouseMove(nFlags, point);

 }

И, самое интересное… :-))) Перекрываем виртуальный метод:

void CFlatButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) {

 // Test WS_TABSTOP

 ASSERT(!(GetStyle() & WS_TABSTOP)); 

 CDC* pDC = CDC::FromHandle(lpDIS->hDC);

 CRect rectAll;

 GetClientRect(rectAll);

 CString text;

 GetWindowText(text);

 int save = pDC->SaveDC();

 CRect rectText(rectAll);

 rectText.DeflateRect(2,2);

 CBrush bkBr(GetSysColor(COLOR_3DFACE));

 pDC->FillRect(rectAll,&bkBr);

 UINT state = lpDIS->itemState;

 if (state & ODS_SELECTED) {

  // Нажатое состояние

  rectText.OffsetRect(1,1);

  pDC->DrawEdge(rectAll, BDR_SUNKENOUTER, BF_RECT);

 } else {

  if (bMouseCaptured) {

   pDC->DrawEdge(rectAll, BDR_RAISEDINNER, BF_RECT);

  }

 }

 pDC->DrawText(text, rectText, DT_SINGLELINE|DT_VCENTER|DT_CENTER|DT_TOP);

 pDC->RestoreDC(save);

}

Использование: очень просто. Ставим на шаблоне диалога кнопку, убираем стиль WS_TABSTOP, ставим стиль WS_OWNERDRAW. В ClassWizard'е сопоставляем ей переменную типа CButton, затем тип переменной вручную меняем на CFlatButton. И всё. Далее – как с обычной кнопкой. У меня (VC++ 5.0) – работает.

Дмитрий Сулима В ПОИСКАХ ИСТИНЫ

Q. Как включать в проект незарегистрированный компонент ActiveX? Вернее он на моей машине зарегистрирован, а на другой нет, и в результате этого программа на той машине вообще не запускается.

1 ... 35 36 37 38 39 40 41 42 43 ... 156
На этой странице вы можете бесплатно читать книгу Программирование на Visual C++. Архив рассылки - Алекс Jenter бесплатно.
Похожие на Программирование на Visual C++. Архив рассылки - Алекс Jenter книги

Оставить комментарий