I work with the keyboard so (_kbhit ()
, _Getch ()
):
while (true) // Cycle driving hard processor
{// ^.
if (_kbhit ()) // this call is not blocking
{
char ch = tolower (_Getch ());
Switch (CH)
{
Case 'R':
// ...
Break;
Default:
// ...
Break;
}
}
}
or so (getkeystate ()
):
void keyanaliz ()
{
enum
{
e_firstindex = 0,
E_SIZE = 255,
E_LASTINDEX = E_FIRSTIDEX + E_SIZE,
};
BOOL PREVCHECKEDKEYS [E_SIZE];
Memset (PrevCheckedKeys, True, E_SIZE);
BOOL CHECKEDKEYS [E_SIZE];
Memset (CheckedKeys, False, E_SIZE);
While (ISPlay)
{
for (int i = 0; i & lt; e_size; ++ i)
{
int b = i + e_firstindex;
Char CH = CHAR (B);
Const Short Keystate = GetKeyState (B);
BOOL ISCECKED = KEYSTATE & AMP; 0001;
CheckedKEYS [i] = ischecked;
IF (PrevCheckedKeys [i]! = CheckedKeys [i])
{
COUT & LT; & LT; ch;
PrevCheckedKEYS [i] = CheckedKeys [i];
}
}
}
}
But both ways do not suit me, as the processor is strongly loaded. I would like to process interrupts from the keyboard and call the Callback function.
On MSDN there is a huge section “Keyboard input , I just started studying it.
Which way to dig and where to look? Maybe someone hello examples of ready-made solutions.
Solution Options found using setWindowshooKEX ()
:
# define _win32_winnt 0x500
#Include & lt; Windows.h & gt;
#Include & lt; Tchar.h & gt;
Hhook g_hhook;
Handle G_HEVENT;
UINT G_UKEY = VK_CAPITAL;
Uint g_udisablekey = vk_lmenu;
Lresult Callback Keyboardhook (Int Ncode, WParam Wparam, LPARAM LPARAM)
{
if (ncode == HC_ACTION)
{
Kbdllhookstruct * ks = (kbdllhookstruct *) lparam;
If (ks- & gt; vkcode == g_ukey & amp; & amp;! (GetKeyState (G_udisableKey) & amp; 0x8000))
{
If (WParam == WM_KEYDOWN)
{
HWND HWND = GetForeGroundWindow ();
AttachThreadInPut (getCurrentThreadid (), GetWindowthReadProcessID (HWND, NULL), TRUE);
HWND HWND_THREAD = getFocus ();
if (hwnd_thread)
HWND = HWND_THREAD;
if (hwnd)
PostMessage (HWND, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM) HKL_NEXT);
}
Return 1;
}
}
RETURN CallNEXTHOOKEX (G_HHHOK, NCODE, WPARAM, LPARAM);
}
Void Failed (Const Tchar * MSG)
{
MessageBox (NULL, MSG, _T ("Error"), MB_OK | MB_ICONERROR);
Exitprocess (1);
}
Void Callback Timercallback (HWND HWND, UINT UMSG, UINT_PTR IDEVENT, DWORD DWTIME)
{
If (WaitForSingleObject (G_HEVENT, 0) == WAIT_OBJECT_0)
PostQuitmessage (0);
}
Void CMDLineParse (Int Argc, WCHAR_T ** ARGV)
{
argv = commandlinetoargvw (getcommandlinew (), & amp; argc);
if (argv! = null & amp; & amp; argc & gt; = 2)
{
UINT UCMDKEY = _WTOI (ARGV [1]);
if (UcmdKey & GT; = 0x01 & amp; & amp; ucmdkey & lt; = 0xfe)
g_ukey = ucmdkey;
if (argc & gt; = 3)
{
UINT UDISABLEKEY = _WTOI (ARGV [2]);
if (udisableKey & gt; = 0x01 & amp; & amp; udisablekey & lt; = 0xfe)
g_udisablekey = udisablekey;
}
}
LocalFree (ARGV);
}
Void ApplicationisalreadYRunning ()
{
g_hevent = CreateEvent (NULL, TRUE, FALSE, _T ("haalilswitch"));
if (g_hevent == null)
Failed (_T ("CreateEvent ()"));
if (getLastterror () == error_already_exists)
{
failed (_T ("LSwitch is already running!"));
}
}
void resolve (int argc, wchar_t ** argv)
{
MSG msg;
cmdLineParse (argc, argv);
applicationIsAlreadyRunning ();
if (SetTimer (NULL, 0, 500, TimerCallback) == 0) // Don't understand why this is needed?
failed (_T ("SetTimer ()"));
g_hHook = SetWindowsHookEx (WH_KEYBOARD_LL, KeyboardHook, GetModuleHandle (0), 0);
if (! g_hHook)
failed (_T ("SetWindowsHookEx ()"));
while (GetMessage (& amp; msg, 0, 0, 0))
{
TranslateMessage (& amp; msg);
DispatchMessage (& amp; msg);
}
UnhookWindowsHookEx (g_hHook);
CloseHandle (g_hEvent);
ExitProcess (0);
}
Few questions left:
- Why call the
TimerCallback ()
function on a timer and what happens in it? The solution works fine without it. - I don’t quite understand why using a bunch
GetMessage ()
,TranslateMessage ()
, andDispatchMessage ()
. Can you recommend a good book on WinApi to figure it out?
Answer 1, authority 100%
Use SetWindowHookEx.
An example is here: https://github.com/MikalaiR/LSwitch/blob/master/ lswitch.c
Answer 2
- https://referencesource.microsoft.com/#mscorlib/system /console.cs,f2f74e891abe6be3
- https://github.com/dotnet/corefx/issues/1153 # issuecomment-139896374
- https: // msdn.microsoft.com/ru-ru/library/windows/desktop/ms684961(v=vs.85).aspx
# include & lt; cstdio & gt;
#include & lt; Windows.h & gt;
char getch ()
{
static INPUT_RECORD cachedInputRecord;
INPUT_RECORD r;
if (cachedInputRecord.EventType == 1)
{
r = cachedInputRecord;
if (cachedInputRecord.Event.KeyEvent.wRepeatCount == 0)
cachedInputRecord.EventType = -1;
else
cachedInputRecord.Event.KeyEvent.wRepeatCount--;
}
else
{
DWORD n;
while (true)
{
ReadConsoleInput (GetStdHandle (-10), & amp; r, 1, & amp; n);
short keyCode = r.Event.KeyEvent.wVirtualKeyCode;
if (! (r.EventType == 1 & amp; & amp; r.Event.KeyEvent.bKeyDown) & amp; & amp; keyCode! = 0x12) continue;
char ch = r.Event.KeyEvent.uChar.AsciiChar;
if (ch == 0 & amp; & amp; ((keyCode & gt; = 0x10 & amp; & amp; keyCode & lt; = 0x12) || keyCode == 0x14 || keyCode == 0x90 || keyCode == 0x91)) continue;
if (r.Event.KeyEvent.wRepeatCount & gt; 1)
{
r.Event.KeyEvent.wRepeatCount--;
cachedInputRecord = r;
}
break;
}
}
return r.Event.KeyEvent.uChar.AsciiChar;
}
int main ()
{
char ch = '';
for (int q = 10; q; --q)
{
printf ("Press% d keys (previous was% c) \ n", q, ch);
ch = getch ();
}
return 0;
}