How can I send a zoom gesture to the current active window?
I tried creating a GESTUREINFO struct but I do not know how to pass the struct properly. So far, here's what I got.
GESTUREINFO gi;
POINT pt;
ZeroMemory(&gi, sizeof(GESTUREINFO));
gi.dwID = GID_ZOOM;
GetCursorPos(&pt);
gi.ptsLocation.x = pt.x;
gi.ptsLocation.y = pt.y;
gi.ullArguments = value;
gi.cbSize = sizeof(GESTUREINFO);
::SendMessage(hwnd, WM_GESTURE, reinterpret_cast<WPARAM>(&gu.ullArguments), reinterpret_cast<LPARAM>(&gi));
Is my way of sending the WPARAM and LPARAM wrong?
You cannot fake input using SendMessage. WM_GESTURE is no exception. While wParam is easy to construct, the system does not offer an API to create a handle to a GESTUREINFO, which needs to be passed as lParam.
Starting with Windows 8, there is the Touch Injection API that allows you to generate touch input for arbitrary targets. Note that touch input is inherently more complex than mouse input (because of contact-area size, multi-touch, pressure, and other factors), so be prepared that it's not as simple as simulating mouse input by calling SendInput.
Related
Im using a spin button and want to read it's position.
I've overwritten OnDeltaposSpin(...) , but then i have to evaluate the NMHDR. If I set *pResult=0, it will do the calculations for me, but my value lags behind.
void CClass::OnDeltaposSpin(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
*pResult = 0;
UpdateData(TRUE);
// I want to use the data here
}
So if the Spin is initially 0, the first click won't do anything to my data, the second click gets it to 1, and so on.
Is there another message i can handle that triggers after UDN_DELTAPOS that would work like EN_CHANGE for other controls? Or can i tell the spin control to use the *pResult to do it's calculations inside OnDeltaposSpin?
It looks like UDN_DELTAPOS is used for overriding the position change amount, or preventing a change, but the actual change happens with a WM_VSCROLL (or WM_HSCROLL) message. I suspect those might be the messages you would need to handle to get the results....
(I'm basing this on this doc.)
About
I am trying to build a custom mouse input for Unity that gets the data directly from the HID. I do this because I want to try if there is any difference (when using my own custom mouse input) to the Unity API that gives me raw mouse input.
Also I need to say that everything I am doing right now does not happen within Unity. I want to build an C++ application and then pass the data to Unity (that's not a part of this question).
This link (MSDN High-Definition Mouse Movement) shows that there are three different types of messages I can use. Due to I need so called "High-Definition Mouse Movement" I need to go with WM_INPUT.
This message can be caught with the WinProc handler as the documentation says. Within that callback the raw mouse data can be accessed. This is what I want to achieve and where I need help.
My current approach
The documentation (link above) gives me this example to register the mouse:
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = gameWindowHandle;
regDeviceDone = RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
The following two lines were modified by me:
Rid[0].hwndTarget = gameWindowHandle;
There I define the Unity window as target. gameWindowHandle is set by EnumWindows.
The other line I changed is the last one due to there is a syntax error (missing parenthesis).
As far as I understood the documentation right this should be it. Now the following callback should be called when there are WM_INPUT messages sent to the Unity window.
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
) {
printf("%d", uMsg);
switch (uMsg) {
case WM_INPUT:
UINT dwSize = 40;
static BYTE lpb[40];
GetRawInputData((HRAWINPUT)lParam, RID_INPUT,
lpb, &dwSize, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
int xPosRelative = raw->data.mouse.lLastX;
int yPosRelative = raw->data.mouse.lLastY;
printf("X: %d, Y: %d", xPosRelative, yPosRelative);
}
break;
}
return NULL;
}
My problems
The first problem I have is that calling this
regDeviceDone = RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
does not return true as it should. Instead it returns false and GetLastError gives me error 87 (after googling this I found out it has to do with wrong parameters).
The documentation says to do so but unfortunately it does not work the way I do it.
Another problem is how to keep the application alive. After registering the device I need to wait for the callbacks to trigger (if they would work). How can I achieve that the application does nothing than waiting for the callbacks?
Is my approach even reasonable or am I doing completely wrong and have to use different APIs?
Your approach is wrong. First, RawInput requires Window. A Window under your control with your own WndProc. Hence in your C++ library, you should define a window procedure. Start a thread. In this thread register window class with that procedure. After you succeed in registering your class, create HWND_MESSAGE window, register your devices and enter a while GetMessage... DispatchMessage loop. This should be done in a separate thread. In your window procedure you must now catch WM_INPUT messages. Enjoy.
I started recently learning C++ and WinAPI, I want to be able to create my own programs
I am subclassing a button (into separate file, because I like things clean and organized - is that a bad idea?), because I want to have few of the kind with same parameters. I also want to draw it, and the question that pops to my mind is: wouldn't it be better to have it all in the class file? Meaning all parameters including custom draw. It is annoying to go to main file to change the looks and set all other parameters in the class file. I use codeblocks.
EDIT (explanation):
#include <Windows.h>
#include <Winuser.h>
#include "CustomButton.h"
/*global vars*/
WNDPROC CustomButton::CustomButtonLongPtr;
/*functions*/
LRESULT CALLBACK CustomButtonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
CustomButton * CustomButton::CreateCustomButton(HINSTANCE hInstance, HWND hwnd, int pos_x, int pos_y, int width, int height)
{
CustomButton * p_CustomButton = new CustomButton;
HWND customButton = CreateWindowEx(0, "BUTTON", "OK", WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, pos_x, pos_y, width, height, hwnd, (HMENU)200, (HINSTANCE)GetWindowLong(hwnd, GWLP_HINSTANCE), p_CustomButton);
if(customButton == NULL)
{
delete p_CustomButton;
MessageBox(NULL, "Problem creating the Search box.", "Error", 0);
return 0;
}
CustomButton::CustomButtonLongPtr = (WNDPROC)SetWindowLongPtr(customButton, GWLP_WNDPROC, (LONG_PTR)&CustomButton::CustomButtonProc);
return p_CustomButton;
}
I want to use WM_DRAWITEM for this button in CustomButtonProc and I am wondering why did the developers think that it would be smarted to allow to use it only in parent WinProc.
This is a little complicated to explain.
You're probably coming from a background where you plug a function into an outlet to handle events, something like
extern void onClicked(void);
button->OnClicked = onClicked;
And while it's fully possible for Windows to have done this from the start, you have to remember that Windows was originally designed to run on systems with severely limited memory, so it was important that controls not waste memory. And there are a lot of events you can get from a button:
void (*OnClicked)(void);
void (*OnDoubleClicked)(void);
void (*OnDisabled)(void);
void (*OnHighlight)(void);
void (*OnKillFocus)(void);
void (*OnPaint)(void);
void (*OnSetFocus)(void);
void (*OnUnhighlight)(void);
void (*OnUnpushed)(void);
HBRUSH (*OnCtlColorButton)(void);
Having these for every button in your program — that is, push buttons, checkboxes, radio buttons, and groupboxes — with most of them likely to be unused would just be a massive waste of memory.
Because Windows needs a way to communicate between the system and a window and between windows, Microsoft decided to create a message-passing interface where each message had a 16-bit code and two pointer-sized (originally one 32-bit and one 16-bit) parameters and a pointer-sized return value. And there aren't a lot of messages that Windows needs for itself, giving both window classes and the application a lot of real estate for using messages to communicate. So why not use a message to signal the event?
Using a message avoids the waste of memory while still allowing the button to pass data to and return data from its target window. So the logic follows that all a button would need to do is
/* this is not the correct syntax but let's use it for expository purposes */
#define BN_CLICKED someNumberHere
case WM_LBUTTONUP:
SendMessage(GetParent(hwnd), BN_CLICKED, hwnd);
break;
and the parent would handle that:
case BN_CLICKED:
if (whichButton == button1)
doButton1Stuff();
break;
No wasted memory, but still flexible and extensible. And even more importantly, also binary-compatible: if more events were added later, the size of the function pointer table would need to change, and newer programs that tried to use newer events on older systems would clobber random memory. With messages, these programs would just have dead code.
Now why send the message to the parent? If we view windows as communication endpoints, then this is obvious: you want the button to tell its parent that it was clicked because you're communicating that the button was clicked!
But more important, you didn't write the button's window procedure. Microsoft did, and they provide the same one to every program. If you could handle the message in the button procedure, where would you put it? You can't change the button procedure, after all.
(Nowadays we have something called "subclassing" which allows you to override a single window's window procedure to do custom processing. It's not used for event handling because it's more work than just sending up to the parent.)
All of this extends to custom draw; just substitute "custom draw" for "clicked" and it should still make sense. Hopefully this explanation was clear, even with that mental substitution.
If you want, you can write your own facility to handle events in the function pointer way. Keep a map of window handles to event functions and call a global dispatch function in all your window procedures to handle the event messages WM_COMMAND, WM_NOTIFY, and (for trackbars) WM_HSCROLL and WM_VSCROLL. How you do this is up to you, but think about whether you really want to do it this way; sometimes it's necessary, but sometimes it isn't. If you do, remember to provide a way to pass arbitrary data to the event function that's decided at event connection time, so the event handler can do something reasonable without relying on global state.
Thanks to comments by RemyLebeau and IInspectable I was able to also find solution to my frustration, which I am going to explain here for anybody else who's scratching their heads over this very issue.
This solution does not require VCL nor any component from Visual Studio and such.
First define your own custom message, in the way that you can reach it inside WndProc:
#define MY_DRAWITEM (WM_APP+1)
UINT uDrawButtonMsg = RegisterWindowMessage(_T("MY_DRAWITEM"));
Then find out what number it is assigned:
std::cout << uDrawButtonMsg; //for example 49648
And send this message from WndProc to your subclassed control from any message you wish, for example WM_DRAWITEM:
case WM_DRAWITEM:
{
::SendMessage(p_CustomButton->customButton, uDrawButtonMsg, wParam, lParam);
break;
}
And then in your subclass just catch the message by the 5 digit number you looked for while ago:
if(49648 == uMsg)
{
//do your DRAWITEM stuff here
}
Thanks to everybody who contributed to this article helping with exaplanation, tips and also historical background!
I am looking to create a program where I can set the maximum maximize size (as in the size the window maximises to when you hit the maximise button) and maximize position (X/Y coordinated for the maximised window) for all of the windows that are running. This is so that I can have my Rainmeter visible at all times on my secondary monitor without having to manually resize every window fit inside of it.
I have managed to do this for a simple program I wrote using MINMAXSIZE from the WinAPI. This method seems to work perfectly for my little program, but there is very little documentation on it beside 1 or 2 articles on the internet. I was wondering if this would be the best way to set the maximum maximise size, or if there is another way to do this.
They way I planned to implement this into all of the applications was going to be either DLL Injection or Hooks (neither of which I have any experience with), so I was also wondering your guys' thoughts on these methods.
I know there are a few applications out there that already do this, but I thought this could be a learning experience, and as well, all of the applications I tried do not work very well (although this could be the case with all of them due to the way Windows functions).
If any of you are still unsure about what I am talking about, MaxMax does exactly what I want (although it doesn't work so well, as I stated in my previous paragraph).
Thank you all in advance.
What you're probably looking for is the work area setting, that you can set/retrieve with the SystemParametersInfo function, called with the flags SPI_SETWORKAREA/SPI_GETWORKAREA.
What you want to do is use a global windows hook to handle WM_GETMINMAXINFO. As you may be aware, this is the message that is:
Sent to a window when the size or position of the window is about to
change. An application can use this message to override the window's
default maximized size and position, or its default minimum or maximum
tracking size.
The best way to use this to override the default maximum is to fill in the MINMAXINFO structure like so:
case WM_GETMINMAXINFO: {
DefWindowProc(hWnd, message, wParam, lParam);
MINMAXINFO* mmi = (MINMAXINFO*)lParam;
mmi->ptMaxTrackSize.x = 100;
mmi->ptMaxTrackSize.y = 100;
return 0;
}
This will allow the default values to be assigned to the sizes you don't care about (min x/y) in this case, leaving you to fiddle with the max values as you please. Your windows hook should be done with SetWindowsHookEx() and should look something like this:
SetWindowsHookEx(WH_CALLWNDPROC, hook_procedure, instance_handle, 0);
hMod (instance_handle) should only be set depending on the circumstances (check the docs for this). The dwThreadId mandates a global hook. Your CallWndProc might looks something like this:
__declspec(dllexport) LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
CWPSTRUCT* cwp = (CWPSTRUCT*)lParam;
if(WM_GETMINMAXINFO == cwp->message) {
DefWindowProc(hWnd, message, wParam, lParam);
MINMAXINFO* mmi = (MINMAXINFO*)lParam;
mmi->ptMaxTrackSize.x = 100;
mmi->ptMaxTrackSize.y = 100;
return 0;
}
return CallNextHookEx(next_hook, nCode, wParam, lParam);
}
Unfortunately something you are going to have to deal with is that the only windows that will be hooked are the ones that had were existing when you made your call to SetWindowsHookEx(). I'm not aware of a clean way of getting past this, short of looping a call to SetWindowsHookEx() (ergh!).
You could potentially do this with DLL injection and effectively subclass every window with EnumWindows, EnumChildWindow and SetWindowLongPtr/SetWindowSubclass. But why go to all that trouble when you could just use SetWindowsHookEx? :)
To alter the x/y, you might have to add an override for WM_SYSCOMMAND and check for SC_MAXIMIZE then use SetWindowPos/MoveWindow to position it properly (if you don't want it on the default 0, 0).
Basically i make mousestruct in the hook
MOUSEHOOKSTRUCT* str;
Then make it from lparam,
LRESULT CALLBACK MouseProc( int nCode, WPARAM wParam, LPARAM lParam )
{
str = (MOUSEHOOKSTRUCT *) lParam;
...
Then I catch mousemovements
case WM_MOUSEMOVE:
wParm = AU3_WM_MOUSEMOVE;
fromp = WindowFromPoint(str->pt);
Then validate and try not to send to many messages...
if (fromp != currentwindow)
{
currentwindow= fromp;
PostMessage(m_hHwndMouse, wParm,(WPARAM)( (MOUSEHOOKSTRUCT*) lParam )->hwnd, LPARAM(fromp));
}
break;
This sends the mousemove message along with hwnd to my autoit app which inspects hwnd and if that hwnd is not active it activates it.
Func mouse_func($hWndGUI, $MsgID, $wParam, $lParam)
Select
Case $MsgID = $WM_AUTOITMOUSEMOVE
If GUICtrlRead($activateundermouse) = 1 And $sitting = 0 Then
;Local $starttime = _Timer_Init()
If StringInStr(WinGetTitle($lParam), "ID=") Then
If Not WinActive($lParam) Then
;ConsoleWrite("HOVERING NEW, Activate It: " & WinGetTitle($lParam) & #LF)
WinActivate($lParam)
EndIf
;ConsoleWrite("diff is > " & _Timer_Diff($starttime) & #LF)
EndIf
EndIf
This is how I am activating window that is hovered by the mouse but the problem is that rarely autoit wont read the message that should signal new window being hovered(or the dll with hook didnt send it, I dont know)
Also if the window is overlapping another window and both of them are valid windows that should be activate once hovered I get flickering as autoit is constantly trying to activate the current window and the overlapped one, in a loop
Is there something that perhaps I missed or could be doing wrong here?
It's easiest just to use the facility built into Windows. For example on Windows 7 it looks like this:
This capability is present in older versions of Windows too but is not exposed in such a simple interface. Instead you have to set it with a PowerToy or through SystemParametersInfo.
As Raymond Chen explains, this is a user preference which should not be changed without the user's consent.
You can use the blocking SendMessage instead depending on surrounding implementation. PostMessage will send to the window message queue but may not have the priority you expect as it returns without waiting for the processing of the message.
Also check out SetCapture and ReleaseCapture to change which window is capturing mouse events based on a hit test in mouse move as an alternative to forwarding. Only one window at a time can capture mouse events using these functions so that will solve your flicker issue of the windows forwarding messages to each other most likely.