I am currently writing an application which allows scrolling, without focusing windows.
What I've done yet: I created a LowLevelMouseHook. If the LowLevelMouseProc recieves a MouseWheel-message I am searching for the handle at the cursor-position and send scroll-messages to that handle.
The hook looks like this:
LRESULT CALLBACK MouseHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
if(code < 0)
return CallNextHookEx(mouseHookInstance, code, wparam, lparam);
if(UserMouseHookCallback != NULL)
{
UserMouseHookCallback(code, wparam, lparam);//scroll the hovered window here
if(wparam == WM_MOUSEWHEEL)
return -1;
}
return CallNextHookEx(mouseHookInstance, code, wparam, lparam);
}
As you can see, I am returing -1 if the message is a mousewheel-message. That should avoid scrolling the currently focused window(I don't want to scroll the focused window, I want to scroll the window which is hovered by the cursor). The problem is, that it does not cancel scrolling the focused window. So does anyone has an idea how to avoid scrolling the currently focused window? At the moment there are two windows which are getting scrolled. The one my mouse is hover and the one which is focused.
Please don't downvote my question and give me a chance. I am really doing my best but I am not able to find a solution.
I've found the solution. It is very, very, very simple. Set <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> in your manifest or start it as administrator manually and it works :)
Related
I am trying to make a program that sits in the background that can ignore mouse clicks - outside of the program.
How do I tell Windows this through c++?
I already made the program recognize the mouse click. Just not how to ignore it.
The reason I need to do this is because my mouse has a flaw where it accidentally double-clicks (or more) when I only click one time.
So basically, when the program register that I click with the mouse, it will let the first click through, but then disable that button (ignoring every following clicks) for ~200 milliseconds.
If possible, I would like to avoid using any external libraries. Only the standard ones that comes with Visual Studio.
Thank you very much for reading!
You can use a low-level mouse hook:
// Variable to store the hook handle
HHOOK miHook;
// This is the hook procedure
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if(nCode == HC_ACTION) {
MSLLHOOKSTRUCT &msll = *(reinterpret_cast<MSLLHOOKSTRUCT*>(lParam)); // In there is more context if you need it
if(wParam == WM_LBUTTONDOWN) {
// Do your logic here
if(letsIgnoreThisClick) {
return -1; // This will make the click be ignored
}
}
}
return CallNextHookEx(miHook, nCode, wParam, lParam); // Important! Otherwise other mouse hooks may misbehave
}
// This is how you install the hook
miHook = SetWindowsHookEx(WH_MOUSE_LL, reinterpret_cast<HOOKPROC>(&LowLevelMouseProc), hInstance, 0);
// And this is how you would remove the hook again
UnhookWindowsHookEx(miHook);
This code example can't be used as-is of course, but has to be adjusted to your needs and the individual parts have to be put in the right locations in your code.
Please also read the remarks section for SetWindowsHookEx. You are probably going to need to create a DLL where your function is located (you can load it from your main code). The hInstance in my example has to be the instance handle of the module which contains the hook procedure. Also you need to pump messages in order for your hook to work correctly!
I noticed that RichEdit does not send messages to parent window when CTRL key is pressed when the control is in focus. When parent window is active then all goes ok. But when cursor is in RichEdit only mouse 0x20 WM_SETCURSOR messages go ok. When pressing a key as in typing without control keys 0x111 WM_COMMAND is send, and when I try to press CTRL and during this any other key like 'S' for implementing save-as function, nothing is sent. Is there a way to create callback to RichEdit or in other way capture CTRL+S ?
Escape also doesn't send a message to parent window.
Found how to set a callback to richedit.
DefEditProc = (WNDPROC)SetWindowLong(richeditWindow, GWL_WNDPROC, (long)&richEdit.EditKeyProc);
and before in code:
LRESULT EditKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if(uMsg == WM_KEYDOWN) {
if(wParam == 'S' && GetAsyncKeyState(VK_CONTROL));
return 0;
}
return CallWindowProc(DefEditProc, hwnd, uMsg, wParam, lParam);
}
I think that it's not the best way to go if you just want to catch some particular key shortcuts to make defined actions like Ctrl+S for save.
I would say that the right way to go is to use accelerator tables. It has two advantages :
If the accelerator table is in resources, you can easily change or remove the shortcut without actually digging into the C/C++ code. There are also facilities for multilingual software, and you can also quite easily open/save the accelerator table in a file unstead of using resources if you want the user to customize the shortcuts, etc.
The shortcut is not only triggered when you are in that particular richedit. I think it's a good thing for users. Imagine that you have another control in the same window. With your code, Ctrl+S wouldn't work, unless you register your callback on all control windows. I'm an user, I'm currently on the other control, and I press Ctrl+S. Oh no, my document hasn't been saved ! frustrating and buggy-looking...
IF you are also using menus, there is no that much code to add...
If I have a console application with a handle to it set up like so;
HWND hWnd = GetConsoleWindow();
Then how do I set up a new wndProc for the window?
I tried using
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)conProc);
With conProc being defined as
LRESULT CALLBACK conProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_NCHITTEST:
return HTCAPTION;
}
return DefWindowProc(hWnd, msg, wParam, lParam );
}
But it doesn't work and says "Error code: 5 - Access is denied" on GetLastError()
I understand that it's pretty difficult to modify the console application like this, since it's a csrss.exe application and all, but I'd still like to try..
Thanks.
While the impression is that console window belongs to your process (like other window), it is in fact hosted by CSRSS system process and its WndProc is there. This makes you unable to subclass the window and provide your own WndProc living in your process.
Some related reading:
The process that is in charge of displaying the GUI windows in which consoles are presented is... CSRSS
SetWindowsHookEx with WH_KEYBOARD doesn't work for me, what do I wrong?
Subclassing XP Console Window
First of all SetWindowLong is superseded by SetWindowLongPtr, you should use that function.
Are you trying to change the WNDPROC of your own console window or another process?
From the MSDN docs :
GWL_WNDPROC
-4
Sets a new address for the window procedure.
You cannot change this attribute if the window does not belong to the same process as the calling thread.
For those of you who do not know what I am talking about:
http://www.teamviewer.com/images/presse/quickconnect_en.jpg
Teamviewer overlays that button on all windows to allow you to quickly share a window with someone else. I would like any ideas on implementing something similar -- if you have example code, even better (specifically, the button -- not the sharing). I am interested in C++ and QT... but I would be interested in good solutions in other languages/libraries if there are any.
Thanks.
To draw buttons or other stuff in foreign windows, you need to inject code into the foreign processes.
Check the SetWindowsHookEx method for that:
You most probably want to install a hook for WH_CALLWNDPROCRET and watch out for the WM_NCPAINT message. This would be the right place to draw your button.
However, I'm not really sure, if you can place a window within a Non-Client-Area, so in the worst case, you'd have to paint the button "manually".
Just call this from your main application (or from within a DLL)
SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, hModule, 0);
Note that myCallWndRetProc must reside within a DLL and hModule is the Module-HANDLE for this DLL.
Your myCallWndRetProc could look like:
LRESULT CALLBACK myCallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HT_ACTION) {
CWPRETSTRUCT* cwpret = (CWPRETSTRUCT*)lParam;
if (cwpret->message == WM_NCPAINT) {
// The non-client area has just been painted.
// Now it's your turn to draw your buttons or whatever you like
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
When starting with your implementation, I'd suggest, you just create a simple dialog application and hook your own process only:
SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, NULL, GetCurrentThreadId());
Installing a global hook injects the DLL into all processes, which makes debugging pretty hard, and your DLL may be write-protected while it's in use.
if i close my application via Alt-F4, or the corner "X" button, or by posting destroywindow(hwnd) myself, the application closes correctly, and everything works just as expected.
but recently i realized, on windows7, when i close the app by right klicking on the icon in the taskbar, and clicking "Close Window", the window closes, but my app is still running. when debugging, i don't get into either of the WM_QUIT/DESTROY/CLOSE events.
is there some special behavior when closing a window via taskbar? how can i detect that?
You should get WM_CLOSE. Maybe you're getting it on a different window that the one you're expecting? Although that shouldn't be able to happen unless you have multiple top-level windows.
via Alt-F4, or the corner "X" button, or by posting destroywindow(hwnd) myself
You can't post DestroyWindow(). Ensure that the window procedure of your main window resembles this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
// Other cases
//...
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
The PostQuitMessage() function call ensures that your message loop exits, GetMessage() returns FALSE when it receives the WM_QUIT message. This makes your main window behave like the main window, closing it ends the process. You may have other top-level windows that don't, they shouldn't have this WM_DESTROY message handler. DestroyWindow() is already called automatically by DefWindowProc() when it processes the WM_CLOSE message.