I like to know if its possible to use win32 keyboard hook function (SetWindowsHookEx , SetWindowsHookEx ) in a Qt application.
If possible pls provide a sample code on using SetWindowsHookEx , SetWindowsHookEx functions in Qt.
//Update as of 18 Feb 2010 //
I havent figured out how to do that in QT yet.
But as a workaround I have created a win32 dll using vc++ express edition and placed my hook commands inside the dll functions.
And I call that dll functions from Qt using QLibrary class
/* hearder file code*/
QLibrary *myLib;
typedef HHOOK (*MyPrototype)(HINSTANCE);
/* source file code */
myLib = new QLibrary( "ekhook.dll" );
MyPrototype myFunction;
myFunction = (MyPrototype) myLib->resolve( "Init" );
init() is the function in ekhook.dll thats being called
I was wondering the same thing and found this finally.. Credit goes to Voidrealms.
The video explains enough to make a working application with the following code below.
//Copied Code from YouTube Video
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QTime>
#include <QChar>
#include <iostream>
#include <windows.h>
#pragma comment(lib, "user32.lib")
HHOOK hHook = NULL;
using namespace std;
void UpdateKeyState(BYTE *keystate, int keycode)
{
keystate[keycode] = GetKeyState(keycode);
}
LRESULT CALLBACK MyLowLevelKeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//WPARAM is WM_KEYDOWn, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP
//LPARAM is the key information
qDebug() << "Key Pressed!";
if (wParam == WM_KEYDOWN)
{
//Get the key information
KBDLLHOOKSTRUCT cKey = *((KBDLLHOOKSTRUCT*)lParam);
wchar_t buffer[5];
//get the keyboard state
BYTE keyboard_state[256];
GetKeyboardState(keyboard_state);
UpdateKeyState(keyboard_state, VK_SHIFT);
UpdateKeyState(keyboard_state, VK_CAPITAL);
UpdateKeyState(keyboard_state, VK_CONTROL);
UpdateKeyState(keyboard_state, VK_MENU);
//Get keyboard layout
HKL keyboard_layout = GetKeyboardLayout(0);
//Get the name
char lpszName[0X100] = {0};
DWORD dwMsg = 1;
dwMsg += cKey.scanCode << 16;
dwMsg += cKey.flags << 24;
int i = GetKeyNameText(dwMsg, (LPTSTR)lpszName, 255);
//Try to convert the key information
int result = ToUnicodeEx(cKey.vkCode, cKey.scanCode, keyboard_state, buffer, 4, 0, keyboard_layout);
buffer[4] = L'\0';
//Print the output
qDebug() << "Key: " << cKey.vkCode << " " << QString::fromUtf16((ushort*)buffer) << " " << QString::fromUtf16((ushort*)lpszName);
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, MyLowLevelKeyBoardProc, NULL, 0);
if (hHook == NULL)
{
qDebug() << "Hook Failed" << endl;
}
return a.exec();
}
You don't need to do anything with Qt. Just follow the windows examples:
http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
I believe it is possible, yes. Use QWidget::winId.
Related
I have the following problem with retrieving the window handle from a specific window (title and class name are known):
There are two identical windows with different handles under two different processes, but FindWindow() can find the handle only from the newest window spawned, never from the first one.
What can be used instead? Can EnumWindows() be used to retrieve a list of windows with the same characteristics?
Use the Win32 API EnumWindows , and then check which process each window belongs to by using the Win32 API GetWindowThreadProcessId.
Here is a sample:
#include <iostream>
#include <Windows.h>
using namespace std;
BOOL CALLBACK enumProc(HWND hwnd, LPARAM) {
TCHAR buf[1024]{};
GetClassName(hwnd, buf, 100);
if (!lstrcmp(buf, L"Notepad"))
{
GetWindowText(hwnd, buf, 100);
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
wcout << buf << " " << pid << endl;
}
return TRUE;
}
int main() {
EnumWindows(&enumProc, 0);
}
If you need to check the window of each process, you can refer to this answer.
typedef struct
{
const char *name;
const char *class;
HWND handles[10];
int handlesFound;
} SearchWindowInfo;
SearchWindowInfo wi;
wi.handlesFound = 0;
wi.title = "WindowName";
wi.class = "ClassName";
BOOL CALLBACK searchWindowCallback(HWND hwnd, LPARAM lParam)
{
SearchWindoInfo *wi = (SearchWindoInfo *)lParam;
char buffer[256];
if (wi->handlesFound == 10)
return FALSE;
buffer[255] = 0;
if (wi->name)
{
int rc = GetWindowText(hwnd, buffer, sizeof(buffer)-1);
if(rc)
{
if (strcmp(wi->name, buffer) == 0)
{
wi->handles[wi->handlesFound++] = hwnd;
return TRUE;
}
}
}
if (wi->class)
{
int rc = GetClassName (hwnd, buffer, sizeof(buffer)-1);
if(rc)
{
if (strcmp(wi->class, buffer) == 0)
{
wi->handles[wi->handlesFound++] = hwnd;
return TRUE;
}
}
}
return TRUE;
}
EnumWindows(searchWindowCallback, (LPARAM)&wi);
for(int i = 0; i < wi.handlesFound; i++)
{
// yeah...
}
i have an HID usb rfid reader that act like a keyboard,
i don't want to put a textbox on my form (WPF) to recieve the text from it because i have other requirements .
instead i am trying to capture the key pressed events and process them . for that i have tried three differents methods :
Windows Hook (c++)
this is the most simple testcase example that illustrate the issue
#include <iostream>
#include <fstream>
#include <Windows.h>
#pragma comment(lib, "user32.lib")
HHOOK keyboardHook{ NULL };
DWORD lastkey = 0;
LRESULT CALLBACK MyLowLevelKeyBoardProc(const int nCode, const WPARAM wParam, const LPARAM lParam)
{
KBDLLHOOKSTRUCT *kb = (KBDLLHOOKSTRUCT *)lParam;
switch (wParam)
{
case WM_KEYUP:
if (lastkey == 13)
system("cls");
std::cout << "KeyUp event : " << kb->vkCode << std::endl;
lastkey = kb->vkCode;
break;
}
return CallNextHookEx(keyboardHook, nCode, wParam, lParam);
}
int main(int argc, char* argv[])
{
keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, MyLowLevelKeyBoardProc, NULL, 0);
if (keyboardHook == NULL) {
std::cout << "Keyboard hook failed!" << std::endl;
}
while (GetMessage(NULL, NULL, 0, 0));
return 0;
}
Raw input API
by handling the WM_INPUT message (too many code to show)
oblita interception library
the most interesting solution that i will use if i fix the problem
#include "stdafx.h"
#include "C:\Dev\WPF\Interception\library\interception.h"
#include "C:\Dev\WPF\Interception\Interception-1.0.0\samples\utils.h"
#include <string>
#include <iostream>
enum ScanCode
{
SCANCODE_X = 0x2D,
SCANCODE_Y = 0x15,
SCANCODE_ESC = 0x01
};
int main()
{
using namespace std;
InterceptionContext context;
InterceptionDevice device;
InterceptionStroke stroke;
wchar_t hardware_id[500];
string buffer = "";
//raise_process_priority();
context = interception_create_context();
interception_set_filter(context, interception_is_keyboard, INTERCEPTION_FILTER_KEY_UP | INTERCEPTION_FILTER_KEY_UP);
while (interception_receive(context, device = interception_wait(context), &stroke, 1) > 0)
{
if (interception_is_keyboard(device))
{
InterceptionKeyStroke &keystroke = *(InterceptionKeyStroke *)&stroke;
if (keystroke.code == SCANCODE_ESC) break;
size_t length = interception_get_hardware_id(context, device, hardware_id, sizeof(hardware_id));
if (wcsstr(hardware_id, L"04F3&PID_0009") == 0)
interception_send(context, device, &stroke, 1); // Real Keyboard
else
{
// RFID reader
if (keystroke.code == 28)
{
std::cout << buffer << endl;
buffer = "";
}
else
buffer = buffer + std::to_string(keystroke.code);
}
}
}
interception_destroy_context(context);
return 0;
}
all the three methods gave me the same problem :
some keys are randomly lost during the read, instead of having the 10 characters i my have 8/9 only .
if i use the rfid reader on blocnote no character is lost so there is no problem with the reader .
so my question is : how to ensure that no message/key is lost by windows on the hooks , even if the read operation may take 10 seconds .
thanks and good day .
I'm having a problem when trying to run the following code:
#include "header.h"
int main()
{
id = GetCurrentProcessId();
EnumWindows(hEnumWindows, NULL);
Sleep(5000);
//MoveWindow(hThis, 450, 450, 100, 100, TRUE);
system("pause");
return 0;
}
//header.h
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <Windows.h>
using namespace std;
DWORD id = 0;
HWND hThis = NULL;
BOOL CALLBACK hEnumWindows(HWND hwnd, LPARAM lParam)
{
DWORD pid = 0;
pid = GetWindowThreadProcessId(hwnd, NULL);
if (pid == id)
{
hThis = GetWindow(hwnd, GW_OWNER);
if (!hThis)
{
cout << "Error getting window!" << endl;
}
else
{
char *buffer = nullptr;
int size = GetWindowTextLength(hThis);
buffer = (char*)malloc(size+1);
if (buffer != nullptr)
{
GetWindowText(hThis, buffer, size);
cout << pid << ":" << buffer << endl;
free(buffer);
}
}
}
return TRUE;
}
When I run this code nothing is output to the screen almost as if the program is not attached. I tried running it under a console and windows subsystem in VS2013.
According to the GetCurrentProcessId docs, the API
Retrieves the process identifier of the calling process.
GetWindowThreadProcessId, on the other hand,
Retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the process that created the window.
The return value is the identifier of the thread that created the window.
So looking at your call:
pid = GetWindowThreadProcessId(hwnd, NULL);
You're actually getting back a thread ID, not a process ID. So when you compare pid to id, you're comparing a process ID and a thread ID, and that's just not going to work. Try this instead:
GetWindowThreadProcessId(hwnd, &pid);
(Note: I can't actually test whether this works, since EnumWindows requires a top-level window to enumerate and I ran this as a console app. Let me know if this answer doesn't work for you and I'll delete it.)
(As a second note, you don't need to use NULL anymore, even for WinAPI stuff like HWND. nullptr will work perfectly fine.)
I assume you're trying to find the "Main" window from the ProcessID.. In that case, this MAY help:
#include "stdafx.h"
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <Windows.h>
struct WindowHandleStructure
{
unsigned long PID;
HWND WindowHandle;
};
BOOL CALLBACK EnumWindowsProc(HWND WindowHandle, LPARAM lParam)
{
unsigned long PID = 0;
WindowHandleStructure* data = reinterpret_cast<WindowHandleStructure*>(lParam);
GetWindowThreadProcessId(WindowHandle, &PID);
if (data->PID != PID || (GetWindow(WindowHandle, GW_OWNER) && !IsWindowVisible(WindowHandle)))
{
return TRUE;
}
data->WindowHandle = WindowHandle;
return FALSE;
}
HWND FindMainWindow(unsigned long PID)
{
WindowHandleStructure data = { PID, nullptr };
EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&data));
return data.WindowHandle;
}
int main()
{
HWND Window = FindMainWindow(GetCurrentProcessId());
std::wstring Buffer(GetWindowTextLength(Window) + 1, L'\0');
GetWindowText(Window, &Buffer[0], Buffer.size());
std::wcout << Buffer.c_str() << L"\n";
system("pause");
return 0;
}
I try to use the Windows API in c++ and SetWindowsHookEx WH_KEYBOARD_LL does not seem to get events from the right Shift key (the Shift key at the right side of a qwerty keyboard, below the Enter key). It does work with the left Shift key. How do I troubleshoot this problem???
#include "stdafx.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <windows.h>
#include <string>
#include <shlobj.h>
#include <Shlwapi.h>
#include <stdio.h>
#include <aclapi.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <future>
#include <stdlib.h>
#include <random>
#include <ctime>
#include <time.h>
#include <Lmcons.h>
HHOOK kbdhook; /* Keyboard hook handle */
bool running; /* Used in main loop */
__declspec(dllexport) LRESULT CALLBACK handlekeys(int code, WPARAM wp, LPARAM lp)
{
static bool capslock = false;
static bool shift = false;
char tmp[0xFF] = {0};
std::string str;
DWORD msg = 1;
KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);
msg += (st_hook.scanCode << 16);
msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
GetKeyNameText(msg, tmp, 0xFF);
str = std::string(tmp);
if (code == HC_ACTION && (wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN )) {
MessageBox(NULL,str.c_str(),NULL,MB_OK);
}
return CallNextHookEx(kbdhook, code, wp, lp);
}
LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_CLOSE: case WM_DESTROY:
running = false;
break;
default:
/* Call default message handler */
return DefWindowProc(hwnd, msg, wp, lp);
}
return 0;
}
int WINAPI WinMain(HINSTANCE thisinstance, HINSTANCE previnstance,
LPSTR cmdline, int ncmdshow)
{
HWND hwnd;
HWND fgwindow = GetForegroundWindow();
MSG msg;
WNDCLASSEX windowclass;
HINSTANCE modulehandle;
modulehandle = GetModuleHandle(NULL);
kbdhook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)handlekeys, modulehandle, NULL);
running = true;
while (running) {
if (!GetMessage(&msg, NULL, 0, 0))
running = false;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Right shift shows a blanco string in the alert. Left shift however shows a "SHIFT" string in the alert. Anyone a clue???
PS:
If I remove the line with " msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);" -> "RIGHT SHIFT" does show up now, but undefined shows up, when pressing the "Windows key"
Left vs. right shift shows up in the vkCode field of KBDLLHOOKSTRUCT. You're using the key name of the scancode; the right shift key is named 'Shift', just like it says on the keyboard.
Apparently, right shift ends up with the extended flag set, which causes GetKeyNameText to look in the wrong table. Removing the extended flag ends up with a key name of "right shift".
msg += (st_hook.scanCode << 16);
if (st_hook.scanCode != 0x3a)
{
msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
}
GetKeyNameText(msg, tmp, 0xFF);
This solution does not rely on a specific code
if (st_hook.vkCode != VK_RSHIFT)
msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
I'm assuming, what I'm asking should actually be the default, but I'm experiencing some behavior I don't understand.
#include "stdafx.h"
using namespace std;
BOOL CALLBACK enumWindowsProc(
__in HWND hWnd,
__in LPARAM lParam
) {
if( !::IsIconic( hWnd ) ) {
return TRUE;
}
int length = ::GetWindowTextLength( hWnd );
if( 0 == length ) return TRUE;
TCHAR* buffer;
buffer = new TCHAR[ length + 1 ];
memset( buffer, 0, ( length + 1 ) * sizeof( TCHAR ) );
GetWindowText( hWnd, buffer, length + 1 );
tstring windowTitle = tstring( buffer );
delete[] buffer;
wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;
return TRUE;
}
int _tmain( int argc, _TCHAR* argv[] ) {
wcout << TEXT( "Enumerating Windows..." ) << endl;
BOOL enumeratingWindowsSucceeded = ::EnumWindows( enumWindowsProc, NULL );
cin.get();
return 0;
}
If I invoke that code, it will list all minimized windows:
Now, I'm no longer interested in only the minimized windows, now I want all of them. So I remove the IsIconic check:
BOOL CALLBACK enumWindowsProc(
__in HWND hWnd,
__in LPARAM lParam
) {
/*
if( !::IsIconic( hWnd ) ) {
return TRUE;
}
*/
int length = ::GetWindowTextLength( hWnd );
if( 0 == length ) return TRUE;
TCHAR* buffer;
buffer = new TCHAR[ length + 1 ];
memset( buffer, 0, ( length + 1 ) * sizeof( TCHAR ) );
GetWindowText( hWnd, buffer, length + 1 );
tstring windowTitle = tstring( buffer );
delete[] buffer;
wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;
return TRUE;
}
Now I get all windows except the minimized ones (none of the previously listed window handles are listed this time):
For completeness, this is the stdafx.h:
#pragma once
#include "targetver.h"
#include <iostream>
#include <map>
#include <string>
namespace std {
#if defined _UNICODE || defined UNICODE
typedef wstring tstring;
#else
typedef string tstring;
#endif
}
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <psapi.h>
What am I doing wrong?
Here is a callback function that lists all open windows:
#include <string>
#include <iostream>
#include <Windows.h>
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
std::string windowTitle(buffer);
delete[] buffer;
// List visible windows with a non-empty title
if (IsWindowVisible(hWnd) && length != 0) {
std::cout << hWnd << ": " << windowTitle << std::endl;
}
return TRUE;
}
int main() {
std::cout << "Enmumerating windows..." << std::endl;
EnumWindows(enumWindowCallback, NULL);
std::cin.ignore();
return 0;
}
If you want to check if the window is minimized, you can use IsIconic().
See Also:
Microsoft: EnumWindows function
Stack Overflow: Getting a list of all open windows in c++ and storing them
Well, wcout.flush() never works, however wcout.clear() fixes your code, at least for me.
wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;
wcout.clear();
return TRUE;
And I know that this question is already one year old, however it's never too late to answer.
It's (as I assumed) not a problem with EnumWindows at all. The problem is with the output stream.
While debugging, I noticed that enumWindowsProc is called just fine for every window, but that some iterations are simply not generating output.
For the time being, I switched to using _tprintf, but I don't understand what the problem with the original code is. Calling wcout.flush() had no desirable effect either.
Documentation of Windows (dunno its accuracy) says that EnumWindows only enumerates top level windows. If you wish to enumerate child windows, you need to use EnumChildWindows function where you have to pass handle of parent window