Внимание: если этого не сделать, переключение задач будет невозможно даже после завершения работы вашего приложения!
Перейдём к Windows NT/2000. Там трюк со скрин сейвером не работает, но зато есть низкоуровневые хуки для мыши и клавиатуры (обычные хуки не перехватывают системные комбинации клавиш). Установив глобальный низкоуровневый хук на клавиатуру, можно "съесть" все системные нажатия (кроме Ctrl+Alt+Del). Для этого в ответ на приход таких нажатий функция хука должна вернуть единицу.
Как известно, хуки устанавливаются функцией SetWindowsHookEx. В нашем случае требуется глобальный хук, а значит, его код придётся размещать в DLL. DLL может выглядеть примерно так.
#define _WIN32_WINNT 0x0500
#include
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) // Дабы не было проблем с модальными окнами, вызываемыми по нажатию этой кнопки.
Читать дальше