home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2003 November
/
Chip_2003-11_cd1.bin
/
software
/
dave
/
dqsd.exe
/
src
/
DQSDTools
/
KeyboardHook.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2003-01-05
|
10KB
|
386 lines
// KeyboardHook.cpp : Single-thread Keyboard hook implementation
//
#include "stdafx.h"
#include "DQSDTools.h"
#include "KeyboardHook.h"
#include "Launcher.h"
#include "Utilities.h"
#define HOTKEY_WINDOW_CLASS_NAME _T("DQSDHotKeyWindowClass")
#define HOTKEY_WINDOW_NAME _T("DQSDHotKeyWindow")
std::map< long, long > g_mapKeyCodeToCharCode;
// The handle of our hook
static HHOOK hHook;
static HWND hHookedWindow;
static LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if(code == HC_ACTION)
{
HWND hFocusWnd = GetFocus();
if(hFocusWnd != hHookedWindow)
{
// This is not us - don't do anything
ATLTRACE("Hooked message arrived with wrong focus (DQSD 0x%x, focus 0x%x)\n", hHookedWindow, hFocusWnd);
return CallNextHookEx(hHook, code, wParam, lParam);
}
//-----VVVVV-----NOTE: You need to link with IMM32.LIB---
// check if the IME is up
{
HIMC himc = ImmGetContext(hFocusWnd);
bool bImmOn = (ImmGetOpenStatus (himc) != 0);
ImmReleaseContext (hFocusWnd, himc);
if (bImmOn)
{
// This is not us - don't do anything
ATLTRACE("IMM is on\n");
return CallNextHookEx(hHook, code, wParam, lParam);
}
}
//-----^^^^^^------
bool bKeyDown = !(lParam & 0x80000000);
if(wParam == VK_INSERT)
{
if(GetAsyncKeyState(VK_SHIFT) & 0x80000000)
{
ATLTRACE(_T("Shift-INS: %c\n"), bKeyDown ? 'P' : 'R');
if(bKeyDown)
{
// Shift-INS is paste - send a CTRL-V
SendMessage(hFocusWnd, WM_CHAR, 'V'-'@', 0);
return 0;
}
}
else if(GetAsyncKeyState(VK_CONTROL) & 0x80000000)
{
ATLTRACE(_T("Ctrl-INS: %c\n"), bKeyDown ? 'P' : 'R');
if(bKeyDown)
{
// Ctrl-INS is copy - send a CTRL-C
SendMessage(hFocusWnd, WM_CHAR, 'C'-'@', 0);
return 0;
}
}
}
else if(wParam == VK_DELETE)
{
ATLTRACE(_T("DEL: %c\n"), bKeyDown ? 'P' : 'R');
if(GetAsyncKeyState(VK_SHIFT) & 0x80000000)
{
ATLTRACE(_T("Shift-DEL: %c\n"), bKeyDown ? 'P' : 'R');
if(bKeyDown)
{
// Shift-DEL is cut - send a CTRL-X
SendMessage(hFocusWnd, WM_CHAR, 'X'-'@', 0);
return 0;
}
}
else
{
// It's a DEL
if(bKeyDown)
{
// Send a CTRL-D - special handler for this in search.htm
SendMessage(hFocusWnd, WM_CHAR, 'D'-'@', 0);
return 0;
}
}
}
else if(wParam == VK_UP)
{
if ( bKeyDown )
{
// Send a CTRL-P
SendMessage(hFocusWnd, WM_CHAR, 'P'-'@', 0);
return 0;
}
}
else if(wParam == VK_DOWN)
{
if ( bKeyDown )
{
// Send a CTRL-N
SendMessage(hFocusWnd, WM_CHAR, 'N'-'@', 0);
return 0;
}
}
else if(g_mapKeyCodeToCharCode.find( wParam ) != g_mapKeyCodeToCharCode.end() )
{
if ( bKeyDown )
{
SendMessage(hFocusWnd, WM_CHAR, g_mapKeyCodeToCharCode[ wParam ], 0);
return 0;
}
}
else
{
ATLTRACE(_T("Hook: %d (focus 0x%x)\n"), wParam, GetFocus());
}
}
return CallNextHookEx(hHook, code, wParam, lParam);
}
/*
static BOOL CALLBACK EnumProc(
HWND hwnd, // handle to child window
LPARAM lParam // Pointer to discovered taskbar window
)
{
TCHAR className[100];
className[0] = '\0'; // In case the call fails
// Look for the window which corresponds to our deskbar
GetClassName(hwnd, className, sizeof(className));
if(StrCmpI(className, "Internet Explorer_Server") == 0)
{
_RPT1(_CRT_WARN, "Found bar - hWnd 0x%x\n", hwnd);
*(HWND*)lParam = hwnd;
return FALSE;
}
return TRUE;
}
*/
//HWND hBarWnd = NULL;
LRESULT CALLBACK NotificationWndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
static int nAttempts;
if(uMsg == WM_HOTKEY || (uMsg == WM_TIMER && wParam == 0x5744))
{
// _RPT0(_CRT_WARN, "HotKey\n");
// OutputDebugString("HotKey\n");
if(uMsg == WM_HOTKEY)
{
nAttempts = 0;
}
else
{
nAttempts++;
if(nAttempts > 20)
{
// We've failed in some way - kill the timer
KillTimer(hwnd, 0x5744);
}
}
HWND hBarWnd = g_hDQSDWindow; // UtilitiesFindDQSDWindow();
if(hBarWnd == NULL)
{
return 0;
}
// Save the mouse position before these games...
POINT mousePoint;
GetCursorPos(&mousePoint);
// Find our window
RECT taskBarRect;
GetWindowRect(hBarWnd, &taskBarRect);
// We do all this larking about with the mouse because
// SetForegroundWindow is crippled nowadays, and because the DQSD edit control
// doesn't actually seem to get a proper caret if you SFW to it anyway.
ATLTRACE("TaskBarRect: %d,%d,%d,%d\n", taskBarRect.left, taskBarRect.top, taskBarRect.right, taskBarRect.bottom);
if(taskBarRect.top >= GetSystemMetrics(SM_CYSCREEN)
|| taskBarRect.bottom < 0
|| taskBarRect.left >= GetSystemMetrics(SM_CXSCREEN)
|| taskBarRect.right < 0)
{
// The taskbar is auto-hidden - we need to send more than one click - one to unhide the tool bar,
// and one to set the focus
SetTimer(hwnd, 0x5744, 50, NULL);
}
else
{
// The taskbar is not autohidden - don't send any timer messages
KillTimer(hwnd, 0x5744);
// Test if our window is visible (rather than overlayed by something else)
// This only happens if you have a taskbar without always-on-top set
POINT topLeft;
topLeft.x = taskBarRect.left;
topLeft.y = taskBarRect.top;
HWND hTestWindow = WindowFromPoint(topLeft);
ATLTRACE("HotKey: Test window 0x%x, DQSD Window 0x%x\n", hTestWindow, hBarWnd);
if(hBarWnd != hTestWindow)
{
SetForegroundWindow(hBarWnd);
// Take the focus off the bar wnd, so that we get the normal
// 'highlight everything' behaviour when simulating a click into the bar
SetFocus(GetParent(hBarWnd));
}
}
// Calculate the position of a simultated mouse click
// The SendInput structure takes a position scaled 0-65536 across the primary monitor
// Hence the muldivs
INPUT mouseClick;
ZeroMemory(&mouseClick, sizeof(mouseClick));
mouseClick.type = INPUT_MOUSE;
mouseClick.mi.dx = (taskBarRect.left + taskBarRect.right) / 2;
mouseClick.mi.dx = MulDiv(mouseClick.mi.dx, 65536, GetSystemMetrics(SM_CXSCREEN));
mouseClick.mi.dy = (taskBarRect.top + taskBarRect.bottom) / 2;
mouseClick.mi.dy = MulDiv(mouseClick.mi.dy, 65536, GetSystemMetrics(SM_CYSCREEN));
mouseClick.mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
SendInput(1, &mouseClick, sizeof(mouseClick));
mouseClick.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &mouseClick, sizeof(mouseClick));
// Put the mouse back where we found it, because we're nice like that
SetCursorPos(mousePoint.x, mousePoint.y);
}
else if(uMsg == WM_DESTROY)
{
// OutputDebugString("HotKey Destroy\n");
UnregisterHotKey(hwnd, GetWindowLong(hwnd, GWL_USERDATA));
}
return DefWindowProc(hwnd, uMsg,wParam,lParam);
}
//
// Install a keyboard hook on the search deskbars message handler thread
//
//
HRESULT KeyboardHookInstall(HWND hBarWnd, HHOOK& hInstalledHook)
{
// Did we find the window?
if(hBarWnd == NULL)
{
return CLauncher::Error(IDS_ERR_CANT_INSTALL_KEYBOARD_HOOK, IID_ILauncher);
}
// Get a handle to the thread which owns the message queue for this window
DWORD threadId = GetWindowThreadProcessId(hBarWnd, NULL);
ATLTRACE("Thread ID 0x%x\n", threadId);
if(hHook != NULL)
{
ATLTRACE("DQSD: Keyboard Hook already installed\n");
return CLauncher::Error(IDS_ERR_CANT_INSTALL_KEYBOARD_HOOK, IID_ILauncher);
}
hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, _Module.GetModuleInstance(), threadId);
hInstalledHook = hHook;
hHookedWindow = hBarWnd;
ATLTRACE("hHook 0x%x\n", hHook);
return S_OK;
}
void
KeyboardHookRemove(HHOOK hInstalledHook)
{
if(hInstalledHook != NULL)
{
UnhookWindowsHookEx(hInstalledHook);
hHook = NULL;
}
}
//
// Install a hotkey
//
// Return:
// HRESULT
//
HRESULT
KeyboardInstallHotkey(int vkCode, LPCTSTR pModifierNames, HWND* phwndNotification, LPDISPATCH pDispDocument)
{
HWND hBarWnd = UtilitiesFindDQSDWindow(pDispDocument);
if(hBarWnd == NULL)
{
return CLauncher::Error(IDS_ERR_HOTKEY_NO_BAR_WINDOW, IID_ILauncher, E_FAIL);
}
// Create a window which we use to receive notifications
WNDCLASS wc;
ZeroMemory(&wc, sizeof(wc));
wc.lpfnWndProc = NotificationWndProc;
wc.lpszClassName = HOTKEY_WINDOW_CLASS_NAME;
HWND hExistingWindow = FindWindow(wc.lpszClassName, HOTKEY_WINDOW_NAME);
if(hExistingWindow != NULL)
{
// THere's already hotkey window
ATLTRACE("HotKey - window exists\n");
DestroyWindow(hExistingWindow);
}
RegisterClass(&wc);
*phwndNotification = CreateWindow(wc.lpszClassName, HOTKEY_WINDOW_NAME, 0, 0, 0, 0, 0, hBarWnd, NULL, NULL, NULL);
if(*phwndNotification == NULL)
{
ATLTRACE("Failed to create a window for hotkeys (err %d)\n", GetLastError());
return CLauncher::Error(IDS_ERR_HOTKEY_WINDOW_FAILED, IID_ILauncher, E_FAIL);
}
// Make an ID for the window and store it in the windows userdata slot
// so that it can be used to unregister the hotkey
ATOM hotKeyId = GlobalAddAtom(_T("DQSDHotKeyAtom"));
SetWindowLong(*phwndNotification, GWL_USERDATA, hotKeyId);
// Try and work out the modifier - default to the Windows key
UINT keyModifier = 0;
if(StrStrI(pModifierNames, _T("WIN")) != NULL)
{
keyModifier |= MOD_WIN;
}
if(StrStrI(pModifierNames, _T("ALT")) != NULL)
{
keyModifier |= MOD_ALT;
}
if(StrStrI(pModifierNames, _T("SHIFT")) != NULL)
{
keyModifier |= MOD_SHIFT;
}
if(StrStrI(pModifierNames, _T("CONTROL"))!= NULL)
{
keyModifier |= MOD_CONTROL;
}
if(keyModifier == 0)
{
// Blank or invalid modifier string - use WIN
keyModifier = MOD_WIN;
}
if(!RegisterHotKey(*phwndNotification, hotKeyId, keyModifier, vkCode))
{
ATLTRACE("Failed to register hotkey (err %d)\n", GetLastError());
return CLauncher::Error(IDS_ERR_HOTKEY_REG_FAILED, IID_ILauncher, E_FAIL);
}
return S_OK;
}