I've done a lot of searching around with no real solution (to my own problem) so I thought I'd ask here.
I'm designing a kiosk-like program that prevents the user from using task keys (alt+tab, alt+esc, ctrl+esc, etc) while the program is running. Note I'm a novice programmer thus I'd want to stay away from separate dll handling if I can. Particularly, I have went to this site http://support.microsoft.com/kb/226359/en-us for the code. A simplified part of my code looks like this at the top:
HHOOK mule;
HHOOK g_hKeyboardHook;
BOOL g_bFullscreen;
LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam)
{
// By returning a non-zero value from the hook procedure, the
// message does not get passed to the target window
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
BOOL bControlKeyDown = 0;
switch (nCode)
{
case HC_ACTION:
{
// Check to see if the CTRL key is pressed
bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);
// Disable CTRL+ESC
if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown)
return 1;
// Disable ALT+TAB
if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
// Disable ALT+ESC
if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
break;
}
default:
break;
}
return CallNextHookEx (mule, nCode, wParam, lParam);
}
The my main is
int main(int argc, char **argv)
{
_getch();
g_hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );
cout << "Testing task keys disabling (alt tab, ctrl esc, alt esc) and taskbar..." << endl;
_getch();
UnhookWindowsHookEx( g_hKeyboardHook );
cout << "Re enabled" << endl;
_getch();
return 0;
}
I realize this code is for really old windows OS, but I've looked around and the other solutions resemble this code so I thought it should work.
But for some reason it doesn't seem to be working. Whenever my program gets to that line of code, the program stalls for like 5 seconds and continues to run, but the task keys are still working.
I've heard that I should be implementing that function as a dll instead of putting everything in one file, but I'm not sure if they're absolutely right (also I know nothing of dlls)
In addition, I've also tried code (to disable windows key) here: http://msdn.microsoft.com/en-us/library/windows/desktop/ee416808(v=vs.85).aspx and it does the same thing my own program (stalls and does nothing)
Can anyone spot where I did something wrong? I'm using VC++ 2010 on windows 7 64bit.
Your code is fine, hooks just doesn't work with console application because windows can't callback into a console application, it requires a message loop.
Read this answer by Hans Passant which applies here too.
Related
I am trying to remove windows error sound from my Flutter (Win32) Application. After some research I came up with this fix. I tried this fix but it's not helping in my Flutter application.
Heres the code to handle WM_SYSCHAR message:
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept {
if (message == WM_SYSCHAR) {
std::cout << "SYSCHAR from win32" << std::endl;
return 0;
}
...
}
When I press the Alt+Space, "SYSCHAR from win32" is printed in the console. But whenever I press any other key with Alt, this is not printed and the Windows error sound is played. It seems like SYSCHAR message is handled somewhere else?
This can be used to know the working and initialization of Win32 App in Flutter.
I just want to tell the Application that Alt+Key combinations are handled and it doesn't have to play Windows error sound.
Thanks to #IInspectable for suggesting me to use keyboard accelerators.
The problem is Flutter's main loop doesn't have keyboard accelerators. So I followed how to use keyboard accelerators documentation and modified the main loop as follows:
Created accelerator table by calling CreateAcceleratorTable
LPACCEL accels = GenerateAccels();
HACCEL haccel = CreateAcceleratorTable(accels, 36);
if (haccel==NULL) {
return EXIT_FAILURE;
}
Here's the GenerateAccels function:
LPACCEL GenerateAccels() {
LPACCEL lpAccel = new ACCEL[36];
// Alt + Number combinations:
for (int i = 0; i < 10; i++) {
lpAccel[i].fVirt = FALT;
lpAccel[i].key = (WORD)(0x30 + i);
}
// Alt + Alphabet combinations (NOT WORKING AT THE MOMENT):
for (int i = 0; i < 26; i++) {
lpAccel[i + 10].fVirt = FALT;
lpAccel[i + 10].key = (WORD)(0x41 + i);
}
return lpAccel;
}
Then adding a call to TranslateAccelerator in the main loop
::MSG msg = { };
while (::GetMessage(&msg, nullptr, 0, 0) > 0) {
if (!TranslateAccelerator(msg.hwnd, haccel, &msg)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
I also added this check to prevent error sound from playing when any key is pressed after pressing Alt (Alt is not held down).
flutter_window.cpp
case WM_SYSCOMMAND:
// If the selection is in menu
// handle the key event
// This prevents the error/beep sound
if (wparam == SC_KEYMENU) {
return 0;
}
Note: One thing that isn't working is Alt + Alphabet combinations. When pressed, it is still playing that error sound. In my case it's not important right now, but if someone finds the fix then please share.
I'm barely a week into Win32 GUI programming, so I'm confident/hopeful this is something simple. For your consideration, I've provided a sample of my code below.
As a quick brief, my application watches for another application to be open so that I can modify that application's memory. I've placed this initial check at the top of my UI looper as follows such that it will only run once (in which case the user can only cancel and the app closes, or execution resumes past the if statement with hWndApp having a value assigned):
if (!hWndApp) {
appCheck();
}
If I start my application and the other application isn't running, appCheck(); fires and the waterfall of execution therefrom acts accordingly: a message box appears (and will keep appearing if the user clicks "Retry") until the other application's window is found. If the user clicks "Cancel," the application exits and all is well. If they click "Retry" once the other application is running, then my application will finish painting to the screen and execution is normal.
The funny business starts the next time I call appCheck(); (which happens when one of either two buttons is clicked) if the other application has been opened, then closed.
While debugging (via Visual Studio 2017), the variable I assign the MessageBox() call to equals 0 when the other application has been opened, then closed, then the following:
Push button to call appCheck();
getProcessHandleAndPID(); is then called within the if statement because the window can't be found
AppCheckMessageBox(); is then called within the while loop because the window can't be found
The debugger then points to the first line inside of AppCheckMessageBox();, which is the entire int msgboxID = MessageBox(); bit
Pressing F11 (Step Into), no window shows and the application exists after the default choice in the switch statement is triggered since the value of msgboxID is 0 (indicating the MessageBox() call failed, so I tried calling GetLastError() before exit(EXIT_FAILURE), but to no avail).
I'm not sure where my error lies, but I've sought many solutions--none of which have panned out. Finally, if you see any variables below that look misnamed or undeclared, it's solely due to my modification of the code for this post to try to generalize/ shorten it. I may have left out some global variable declarations, etc.
Thank you for any help/guidance you can provide! I'm at my wit's end with this right now...lol.
//--------------------------------------------------
// Function to get process handle and PID of app /
//------------------------------------------------
void getProcessHandleAndPID()
{
hWndApp = FindWindow(NULL, _T("NameOfApplication"));
while (!hWndApp) {
AppCheckMessageBox();
}
//Much more code here
}
//---------------------------------
// Function to show message box /
//-------------------------------
int AppCheckMessageBox()
{
int msgboxID = MessageBox(
NULL, //I tried making this hWndApp as well, but no difference
(LPCWSTR)L"Cancel to exit or start the app and click Retry.",
(LPCWSTR)L"Application Not Found!",
MB_ICONSTOP | MB_RETRYCANCEL | MB_SYSTEMMODAL | MB_SETFOREGROUND
);
switch (msgboxID)
{
case IDCANCEL:
exit(EXIT_FAILURE);
case IDRETRY:
getProcessHandleAndPID();
break;
default:
//GetLastError();
exit(EXIT_FAILURE);
}
return msgboxID;
}
//------------------------------------------------
// Function to check if application is running /
//----------------------------------------------
void appCheck() {
if (!FindWindow(NULL, _T("NameOfApplication"))) {
getProcessHandleAndPID();
}
}
//--------------------------------------------------
// Function to get process handle and PID of app /
//------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (!hWndApp) {
appCheck();
}
switch (message)
{
case WM_PAINT:
//Code here
break;
case WM_CREATE:
//Code here
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
if (LOWORD(wParam) == BTN_ENABLE) {
appCheck();
//Do stuff with button press
}
if (LOWORD(wParam) == BTN_DISABLE) {
appCheck();
//Do stuff with button press
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
Not really an answer, but too long for comments:
This isn't your real code. Many things are missing, there are mismatched braces which would prevent compilation, etc. Always show your real code if you want help.
As David says, calling appCheck() every time you receive a message is the wrong approach. If you want to call it once after your window opens, do that before entering your message loop.
Your code is needlessly recursive (getProcessHandleAndPID() calls AppCheckMessageBox() which calls getProcessHandleAndPID() which calls...) and will potentially lead to a stack overflow.
I want to detect keypress in C++ and i need to use Windows System Call. So, i did some research and this is what i got using Hooks and Message:
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>
using namespace std;
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
switch (wParam) {
case WM_KEYDOWN:
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
char c = char(MapVirtualKey(p->vkCode, MAPVK_VK_TO_CHAR));
cout << c << endl;
}
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
int main() {
HHOOK HKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) > 0) {
cout << "bRet = " << bRet << endl; // I want to do something here, but the program doesn't seem to go in here
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(HKeyboard);
return 0;
}
My question is why my program doesn't go inside the loop(and instead stuck on GetMessage function)? I need it to set conditions to terminate after some seconds, so where should i put the conditions? I know the GetMessage function reads Message, but when i press keys on my keyboard it still not going in and the callback function works just fine.
The events are posted to the active window. Console windows are owned by the console subsystem, csrss.exe, and it receives the events, then translates them to characters and puts them in the console object which is your application's stdin.
If you want to process events the Win32 GUI way, you should use a Win32 window (e.g. RegisterClass and CreateWindow), not a console window.
If you just want the callbacks to work for a certain period of time, you can use an alertable wait such as SleepEx or MsgWaitForMultipleObjects, which accept a timeout.
That's not surprising, there aren't really any messages on your thread queue and you have no window so there's no window queue either.
If you want to play with values returned from your hook, put the code in the hook callback function.
I should warn you that hooks like these won't work in console applications since the console window resides in another process. Also, if you look at the MSDN page for SetWindowsHookEx, you'll see that WH_KEYBOARD_LL is a global hook only, ie you have to put your hook handler in a DLL library and inject the hook in the other applications. Then you have to handle the 32/64 bit issue yourself.
And as a last note, when you say cout << c; in your handler, that would be printing in the process's output file handle, not your own.
I made a little DLL in C++ that I inject into the GTA San Andreas game. Now I want to create hotkeys that work in-game. Like when I press F10 it sets the player's health to maximum. I already know how to set the health and all but I don't know how to make hotkeys.
Here is some code I found but it isn't for DLL usage I suppose:
bool customKeyHook(HWND hWnd, UINT uMsg ,WPARAM wParam, LPARAM lParam)
{
switch(wParam)
{
case VK_F10:
*playerHP = 200;
return true;
}
}
Create a Thread with CreateThread an then create an infinite loop and wait for the keypress:
if (GetAsyncKeyState(VK_F10) & 1)
{
}
I want to put inside a software the necessary codes for it to disable Windows (Xp, Vista, specially 7 and sucessors) hotkeys that could allow the user to get away from the software.
Details:
The commands must be valid only while the software is running; when its not running, Windows hotkeys must be enabled (so: if the user starts the software, the hotkeys are disable; if he closes it, must be re-enabled).
I don't want to disable all windows hotkeys (some key hotkeys such as ctrl+alt+del must still be operational), so solutions such as some sort of windows configuration that disable all hotkeys are useless for me. I must be capable of specifically select which hotkeys I want to continue working and which I don't.
The "hotkey" nickname includes the Windows button.
The code must be either using C++ or Windows functions.
Preferetially without requiering to terminate explorer.exe.
I did look at a post here in stackoverflow that had a very similiar case as mine (Prevent users from quitting a windows application via system hotkeys), but as far as I understood nether of the solutions presented were applicable to my specific situation, and I didn't find anything in the web as well.
Ok, I got how to do it. The code is able to create a sistem-wide hook without DLL using a low level keyboard hook. Here is the code (better that explaining)(using Qt):
//Installing the hook
SWH_return = SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,GetModuleHandle(NULL),0);
if (SWH_return != NULL)
qDebug() << "Hook true";
else
qDebug() << "Hook false";
//Uninstalling the hook
bool teste = false;
teste = UnhookWindowsHookEx(SWH_return);
if (teste)
qDebug() << "Unhook: true";
else
qDebug() << "Unhook: false";
//The function responsible for detecting the keystrokes
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0)
return CallNextHookEx(NULL, nCode, wParam, lParam);
tagKBDLLHOOKSTRUCT *str = (tagKBDLLHOOKSTRUCT *)lParam;
switch(str->flags)
{
case (LLKHF_ALTDOWN):
qDebug() << "ALT";
delete str;
return 1;
}
if (wParam == WM_KEYDOWN)
{
switch (str->vkCode)
{
case VK_RWIN:
case VK_LWIN:
case VK_LCONTROL:
case VK_RCONTROL:
case VK_APPS:
case VK_SLEEP:
case VK_MENU:
qDebug() << "SPECIAL PRESS";
delete str;
return 1;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
This last function don't need any declaration in the .h or in the .cpp file. It blocks inputs of Ctrl, Windows Key and Alt. The other two must be placed respectively in the functions where the user wants to begin the key disabling and when he want it to stop.
Thanks,
Momergil.
RegisterHotKey is also globally disable hotkey for all applications except where RegisterHotKey function call is made.
RegisterHotKey(GetSafeHwnd(), 100, 0,VK_F5); //F5 works only in our application