Catch Ctrl+Alt keys in wndproc - c++

I have successfully caught Alt+F4 inside my overridden wndproc function using:
LRESULT CALLBACK NewWndProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
if (uMsg == WM_SYSKEYDOWN)
{
switch (wParam)
{
case VK_F4:
{
qDebug() << "Alt+F4 pressed";
break;
}
};
}
else
return CallWindowProc(OldWinProc,hwnd,uMsg,wParam,lParam);
}
I now need to catch Ctrl+Alt+Tab and Ctrl+Alt+←
But I can't seem to find them.
I know in C# one of the parameters in the function is:
Keys keyData
And I can use the following:
case Keys.Control | Keys.Alt | Keys.Q:
How do I get those key combinations in C++?

Use GetKeyState WinAPI function to get state of modifier keys like Ctrl. For example:
case VK_LEFT:
{
if (GetKeyState(VK_CONTROL) & 0x8000)
{
qDebug() << "Alt+Ctrl+Left Arrow pressed";
break;
}
}
But please take in account that some videocard drivers under Windows can rotate screen on Ctrl+Alt+← combination and intercept this combination before your code gets it. And it will be a bit hard to implement getting this keyboard event before driver. However you can disable this feature

Related

Hook with setwindowhookex

Hi I need help with this hook I am learning about hooks and I am doing one easy example to learn more about setwindowshookex of microsoft.
The first thing I am trying to include different control keys like ctrl, enter, etc I have tried this code:
if( wParam == WM_SYSKEYDOWN ){
switch (wParam)
{
case VK_SHIFT:
qDebug() << "prueba";
break;
default:
break;
}
}
Obviously didnt work. So i can do comparing but i prefer to include some type to check control key separated. At the same i am trying to include something to separate when i using different applications like notepad for learning.
The normal way you check for modifier keys in a keyboard hook function is using GetKeyState, e.g.
LRESULT DLL_CALL KeyboardFunc (int nCode, WPARAM wParam, LPARAM lParam)
{
...
if (nCode < 0)
return (CallNextHookEx (hKeyHook, nCode, wParam, lParam));
if (nCode == HC_NOREMOVE)
return (CallNextHookEx (hKeyHook, nCode, wParam, lParam));
switch (wParam)
{
case VK_F12 :
// Check for modifier keys:
if ((GetKeyState (VK_CONTROL) & iHiOrder) && // ctrl key
(GetKeyState (VK_SHIFT) & iHiOrder) && // shift key
(GetKeyState (VK_MENU) & iHiOrder) // Alt key
{
}
where HiOrder is a const SHORT value with the high-order bit set.

LuaRef Call crash in WNDPROC CALLBACK

Hi guys.
I have some overlay with lua support.
I need to create some WndProc callbacks, so I hooked WndProc of target window using SetWindowLong and saving old one
LRESULT CALLBACK nProc(HWND hWnd, UINT _Msg, WPARAM wP, LPARAM lP) // its new wndProc
{
switch (_Msg)
{
case WM_CUT: case WM_COPY: case WM_PASTE: case WM_CLEAR:
return 1;
case WM_DESTROY: case WM_NCDESTROY:
UnhookWndP(); // switching back to original wndProc
return 1;
case WM_KEYDOWN: case WM_KEYUP: case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MOUSEWHEEL:
try
{
if (_Msg == WM_KEYUP && wP == 120) // restart LuaState
{
if (LuaInit)
DelLua();
else
CreLua();
}
for (luabridge::LuaRef f : wndCall) // call all our WndProc Lua callbacks
{
if (Msg != NULL && wP != NULL && f.isFunction() && f.isFunction() && lua_gettop(L) == 0)
{
f((int)_Msg, wP); // always in callstack when error occurs
}
}
}
catch (luabridge::LuaException ex) { Msg(ex.what()); }
default:
return CallWindowProc(OriWndP, hWnd, _Msg, wP, lP);
}
}
Created global function for adding callback, which is saving func to wndCall Vector(LuaRef)
Lua part is working fine. It shows messages of WM_KEY... events successfully.
The only problem is: When i hold some button or spamming commands I got Crash with Random error :(
I think its because CALLBACK got hit multiple times at one tick and something got broken in LuaState or idk.
Please help me find a solution or some extra checks for WndProc func.

WM_MBUTTONDOWN doesn't work

I use WM_MBUTTONDOWN to keep track of middle mouse button when it's pressed. So, when I click the middle mouse button at the mouse wheel, it will display the message on the console. I wonder why it doesn't work. Is WM_MBUTTONDOWN for another usage?
LRESULT CALLBACK UI::WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
// The message is post when we destroy the window.
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_MBUTTONDOWN:
cout << "Middle button clicked" << endl;
break;
// Default handling for other messages.
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Output:
Mouse used: Logitech
This looks like a driver issue. On some mice WM_MBUTTONDOWN message is not received. Make sure you use a mouse driver that supports middle button.
Check if the middle button works in other applications - if not, it is a driver issue.

How to know how many time your computer has been in screen saver or monitor/screen off?

I'm using Windows 7 and VC++. The business is to know how many seconds my system has been set into screen saver mode or monitor screen off. To achieve this, I'm trying to catch the events WM_SYSCOMMAND and SC_SCREENSAVE, SC_MONITORPOWER. So I have created a Win32 project in Visual Studio 2008 and I'm receiving the events in WndProc function:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_SYSCOMMAND:
{
switch (LOWORD(wParam))
{
case SC_SCREENSAVE:
{
FILE *fl = fopen("this_is_a_event_test.txt","a");
fputs("SC_SCREENSAVE\n",fl);
fclose(fl);
}
break;
case SC_MONITORPOWER:
{
FILE *fl = fopen("this_is_a_event_test.txt","a");
fputs("SC_MONITORPOWER\n",fl);
fclose(fl);
}
break;
default:
{
}
}
}
break;
}
}
It works fine when dialog is in foreground, but in background (or if I comment ShowWindow function) it only works if I manually send the events:
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_SCREENSAVE, (LPARAM)2);
or
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);
So, it is not working when system power configuration sets the screen saver after 2 minutes of inactivity, and the same thing with automatic monitor screen off. Thats the real thing I want, know when the system is turning off the screen or setting the screen saver, with a background monitoring program.
I have also tried to use hook events with extern dll. I have followed this example http://www.codeproject.com/Articles/1037/Hooks-and-DLLs adding in the CALLBACK msghook() function the same switch code above in WndProc. It doesn't work even using the SendMessage.
After several days stuck with this issue, searching in the Internet, forums... I don't know what else I can do. Can anyone help me?
I were not using hooks properly, but it has been rare. Firstly, about setWindowsHookEx function, I have read WH_CALLWNDPROC or WH_SYSMSGFILTER must be used to get WM_SYSCOMMAND sent messages, and then get SC_SCREENSAVE wParam. In this case, I don't know why and maybe I'm wrong, but thats seems not to be true.
After use every possible message to SetWindowsHookEx, I realised WH_GETMESSAGE is the only one who sends SC_SCREENSAVE wParam, at least in this hook example in Windows 7.
HHOOK hook;
HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE,
(HOOKPROC)msghook,
hInst,
0);
Secondly, listening for every message catched in hook function, WM_SYSCOMMAND were appeared with LPMSG. I have read also that wParam must to be combined to 0xFFF0 to be compared. But wParam & 0xFFF0 == SC_SCREENSAVE didn't work and wParam == SC_SCREENSAVE neither. In this case the only way is using LPMSG for both WM_SYSCOMMAND and SC_SCREENSAVE.
static LRESULT CALLBACK msghook(UINT code, WPARAM wParam, LPARAM lParam)
{
if(code > 0)
{
CallNextHookEx(hook, code, wParam, lParam);
return 0;
}
LPMSG msg = (LPMSG)lParam;
if(msg->message == WM_SYSCOMMAND)
{
if (msg->wParam == SC_SCREENSAVE)
{
MessageBoxA(NULL,L"SC_SCREENSAVE",L"SC_SCREENSAVE",MB_OK);
}
if (msg->wParam == SC_MONITORPOWER)
{
MessageBoxA(NULL,L"SC_MONITORPOWER",L"SC_MONITORPOWER",MB_OK);
}
}
return CallNextHookEx(hook, nCode, wParam, lParam);
}
And using FILE to test the events was a very bad idea, I think using MessageBox is not much better but I don't know how to test ir correctly.

How to turn off beeping when pressing ENTER on a single-line EDIT control under Windows CE?

I'm developing an application targeted to a POCKET PC 2003 (Windows CE 4.2) device using C++ and native WINAPI (i.e. no MFC or the like). In it I have a single-line edit control which part of the main window (not a dialog); hence the normal behaviour of Windows when pressing ENTER is to do nothing but beep.
I've subclassed the window procedure for the edit control to override the default behaviour using the following code:
LRESULT CALLBACK Gui::ItemIdInputProc( HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam ) {
switch ( message ) {
case WM_KEYDOWN :
switch ( wParam ) {
case VK_RETURN :
addNewItem();
return 0;
}
}
return CallWindowProc( oldItemIdInputProc_, hwnd, message, wParam, lParam );
}
This causes the equivalent behaviour as pressing the 'OK' button.
Now to the problem at hand: this window procedure does not override the default behaviour of making a beep. I suspect that there must be some other message or messages which are triggered as ENTER is pressed that I fail to capture; I just can't figure out which. I really want to stop the device from beeping as it messes up other sounds that are played in certain circumstances when an item collision occurs, and it is crucial that the user is alerted about that.
Thanks in advance.
After spewing all messages to a log file, I finally managed to figure out which message was causing the beeping - WM_CHAR with wParam set to VK_RETURN. Stopping that message from being forwarded to the edit control stopped the beeping. ^^
The final code now reads:
LRESULT CALLBACK Gui::ItemIdInputProc( HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam ) {
switch ( message ) {
case WM_CHAR :
switch ( wParam ) {
case VK_RETURN :
addNewItem();
return 0;
}
}
return CallWindowProc( oldItemIdInputProc_, hwnd, message, wParam, lParam );
}
Had the same issue but thanks to you, I finally managed to turn the beep off.
// Run the message loop. It will run until GetMessage() returns 0
while(GetMessage (&messages, NULL, 0, 0)) {
if(messages.message == WM_KEYDOWN && messages.wParam == VK_RETURN) {
sendChatMessage("sample text");
continue;
}
// Translate virtual-key messages into character messages
TranslateMessage(&messages);
// Send message to WindowProcedure
DispatchMessage(&messages);
}
I guess the trick was to not let execute those two statements
I had the same problem but with my Rich Edit (using also subclassed callback). This side helped me lot but sadly the solution from gablin didn't work for me. Somehow I couldn't get the VK_RETURN from the WM_CHAR. But from the WM_KEYDOWN message I can:). I also found out that in my case the beep comes only if the rich edit use not the ES_MULTILINE style.
So finaly this is my working solution in the Callback to dissable the beep if return key is pressed. Maybe it can still help someone who has the same problem :)
switch (message){
case (WM_KEYDOWN) : {
switch (wParam) {
case VK_RETURN:
if ((GetWindowLong(this_editbox->getHandle(), GWL_STYLE) & ~ES_MULTILINE)){ //Only dissable return key if the rich edit is a single line rich edit
//Do something you want to do here if return key was pressed for ex. delete text with SetWindowTextA(hRichEdit, ""); after reading
return 0;// stop beep by blocking message
}
}
break;
}
default: break;
}
Try also handling the WM_KEYUP and return 0 for VK_RETURN there as well - Windows non-CE also beeps if you don't handle the key event in both down and up.
In a Windows desktop app, I was also getting annoying beeps when hitting the left arrow key when the insertion point was to the left of the first character, or hitting the right arrow key when the insertion point was positioned after the last character. This code handles the return key as well as the left and right arrow keys to stop the beep.
This is in a Windows desktop app, so I'm not hearing a beep for WM_CHAR + VK_RETURN; you'll have to try this code yourself on CE to see if it works well for you.
bool processKeystroke = true;
if (message == WM_CHAR || message == WM_KEYDOWN || message == WM_KEYUP) {
DWORD start = 0;
DWORD end = 0;
switch (wParam) {
case VK_RETURN:
if ((GetWindowLong(hwnd, GWL_STYLE) & ~ES_MULTILINE)) {
processKeystroke = false;
}
break;
case VK_LEFT:
{
::SendMessage(hwnd, EM_GETSEL, (WPARAM) &start, (LPARAM) &end);
if (start == 0 && end == 0) {
processKeystroke = false;
}
}
break;
case VK_RIGHT:
{
LPARAM charCount = ::SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
::SendMessage(hwnd, EM_GETSEL, (WPARAM) &start, (LPARAM) &end);
if (wParam == VK_RIGHT && start == charCount && end == charCount) {
processKeystroke = false;
}
}
break;
}
if (processKeystroke) {
lResult = DefSubclassProc(hwnd, message, wParam, lParam);
}
}
}
In a Windows desktop app, I got the same problem while handling VK_TAB in WM_GETDLGCODE.
so I found the following solution.
SystemParametersInfo(SPI_SETBEEP, FALSE, NULL, 0); // turn of the beep
// do somthing ... //
SystemParametersInfo(SPI_SETBEEP, TRUE, NULL, 0); // turn on the beep