How to use dwExtraInfo with SendInput - c

I'm using ::SendInput to send a mouse click event:
void LeftDown (LONG x_cord, LONG y_cord)
{
INPUT Input={0};
// left down
Input.type = INPUT_MOUSE;
Input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN;
Input.mi.dx = x_cord;
Input.mi.dy = y_cord;
Input.mi.dwExtraInfo = 0x12345; //Is this how to use it?
::SendInput(1,&Input,sizeof(INPUT));
}
I want to set the dwExtraInfo to some self defined value and extract it in the WndProc at the target application. Then (for example) I will ignore that click if the dwExtraInfo is set to some specific value:
LRESULT CALLBACK OSRWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if(message == WM_LBUTTONDOWN)
{
if(GetMessageExtraInfo() == 0x12345) //Is this how to use it?
//ignore
else
//do something
}
}
Is this naive way is the proper way to use dwExtraInfo or is there a better practice? Thanks!

The documentation says:
dwExtraInfo
An additional value associated with the mouse event. An application calls GetMessageExtraInfo to obtain this extra information.
So yes, use it just as you have shown it in your question.

Related

In WinAPI, how do I know when the mouse has moved outside the current window?

Basically, I want to write a program that shows in a small window the color of the pixel currently pointed by the mouse cursor.
Of course, I could poll the mouse cursor position once in a while, but I would like to opt to a mechanism that calls my code when the mouse cursor has moved, regardless whether it's pointing the current window or not.
Is there some WinAPI trickery that could achieve that functionality?
After some search, I found this:
HHOOK mouseHook =
SetWindowsHookExA(
WH_MOUSE_LL,
LowLevelMouseProc,
hInstance,
0);
...
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (wParam == WM_MOUSEMOVE) {
// Notify me.
}
return 0;
}

Moving frameless window by dragging it from a portion of client area

As the title says, I would like to move the window only when the user will drag it from a portion of the client area. This will be an imitation of the normal caption bar movement and it's because my form is custom and it doesn't have any title or caption bars. At the moment, I use the code as follows:
...
case WM_NCHITTEST:
return HTCAPTION;
and that works fine for making the user able to move the window no matter where he drags from. I would like to limit this possibility (only the top of the window will allow movement). I haven't tried checking the position of the mouse pressed because I don't know how to do it in the WM_NCHITTEST message.
I use plain Win32 (winapi) C code (no MFC or anything else at the moment) in Visual Studio 2015.
You will run into trouble if you just return HTCAPTION in response to all WM_NCHITTEST messages. You will break things like scrollbars, close buttons, resizing borders, etc. that are all implemented via different HT* values.
You have the right idea, though. You want to make the client area of your window draggable, so you need to trick Windows into thinking that your client area is actually the caption area (which, as you know, is draggable). That code looks like this:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// ...
case WM_NCHITTEST:
{
// Call the default window procedure for default handling.
const LRESULT result = ::DefWindowProc(hWnd, uMsg, wParam, lParam);
// You want to change HTCLIENT into HTCAPTION.
// Everything else should be left alone.
return (result == HTCLIENT) ? HTCAPTION : result;
}
// ...
}
However, based on the image in your question, you appear to want to restrict this to only a certain region of your window. You will need to define exactly what that area is, and then hit-test to see if the user has clicked in that area. Assuming that rcDraggable is a RECT structure that contains the bounds of the red box shown in your image (in screen coordinates), you can use the following code:
static RECT rcDraggable = ...
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// ...
case WM_NCHITTEST:
{
// Call the default window procedure for default handling.
const LRESULT result = ::DefWindowProc(hWnd, uMsg, wParam, lParam);
// Get the location of the mouse click, which is packed into lParam.
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
// You want to change HTCLIENT into HTCAPTION for a certain rectangle, rcDraggable.
// Everything else should be left alone.
if ((result == HTCLIENT) && (PtInRect(&rcDraggable, pt))
{
return HTCAPTION;
}
return result;
}
// ...
}
If you define rcDraggable in terms of client coordinates, you will need to convert it to screen coordinates before doing the hit-testing in response to WM_NCHITTEST. To do that, call the MapWindowPoints function, like so:
RECT rc = rcDraggable;
MapWindowPoints(hWnd, /* a handle to your window */
NULL, /* convert to screen coordinates */
reinterpret_cast<POINT*>(&rc),
(sizeof(RECT) / sizeof(POINT)));
You can call some magic code in WM_LBUTTONDOWN handler, AFAIR this:
ReleaseCapture();
SendMessage(yourWindowHandle, WM_SYSCOMMAND, 0xf012, 0) ;
I used this method a few years ago in Delphi and Windows XP. I think it must be similar for c++. Of course, you can check x and y before doing this.

How to stop FilterMessage to proceed further?

I am looking forward to find a way to stop my message to proceed further or in other words to make it handled.
Say, cursor location is at textbox and I am scanning a barcode "#Save#". I recognized using WindowProc that this is barcode text and I handled Save text (by saving my form) but now I don't want to write this text("#Save#") in textbox.
So in short sentence I am looking for property or method to say a window this text (input) is handled, don't do any further action.
HwndSource source = (HwndSource)PresentationSource.FromDependencyObject(this);
source.AddHook(WindowProc);
private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if(device == barcode)
{
......
.....
//Did some action
//tried to stop msg to follow further in loop, but not working
handled ==true;
}
return IntPtr.Zero;
}
Is that a typo, extra equals sign? Your code reads:
handled ==true;
that's not an assignment, although, I don't think that should even compile...
did you mean:
handled = true;

Extending mouse click event - C

Currently I am detecting the x and y position of a mouse click, storing it in a Point and displaying it through the message box.
I want to be able to read if another keyboard key is being held down such as the Shift or Control button.
Looking on MSDN I found the following information:
wParam Indicates whether various
virtual keys are down. This parameter
can be one or more of the following
values.
MK_CONTROL The CTRL key is down.
MK_MBUTTON The middle mouse button is
down.
MK_RBUTTON The right mouse button is
down.
MK_SHIFT The SHIFT key is down.
MK_XBUTTON1 Windows 2000/XP: The first
X button is down.
MK_XBUTTON2 Windows 2000/XP: The
second X button is down.
The problem I am having is I'm unsure as to how to store the results from wParam for each parameter and use them like I have to display them through the message box.
Here is my progress so far:
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message,
WPARAM wParam, LPARAM lParam)
{
POINTS mouseXY;
WCHAR buffer[256];
// Act on current message
switch(message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONUP:
// Get mouse x, y
mouseXY = MAKEPOINTS(lParam);
// Output the co-ordinates
swprintf(buffer, 255, L"x = %d, y = %d", mouseXY.x, mouseXY.y);
MessageBox(0, buffer, L"Mouse Position", MB_OK);
break;
default:
return DefWindowProc(hMainWindow, message, wParam, lParam);
}
return 0;
}
Thanks for the help
The different virtual keys are ORed together in wParam. To check for single values, you have to AND them out (think basic bit operations).
Example:
swprintf(buffer, 255, L"x = %d, y = %d, Shift = %s, Ctrl = %s",
mouseXY.x, mouseXY.y,
wParam & MK_SHIFT ? L"yes" : L"no",
wParam & MK_CONTROL ? L"yes" : L"no");
You can use GetAsyncKeyState to find out the state of the most of the buttons:
SHORT lshift = GetAsyncKeyState(VK_LSHIFT);
SHORT rshift = GetAsyncKeyState(VK_RSHIFT);
// etc...
Here is a description of the difference between GetKeyState and GetAsyncKeyState.
You can also use GetKeyboardState:
BYTE keyboardState[256];
GetKeyboardState(keyboardState);

How can I simulate key presses to any currently focused window?

I am trying to change the keys my keyboard sends to applications. I've already created a global hook and can prevent the keys I want, but I want to now send a new key in place. Here's my hook proc:
LRESULT __declspec (dllexport) HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int ret;
if(nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
kbStruct = (KBDLLHOOKSTRUCT*)lParam;
printf("\nCaught [%x]", kbStruct->vkCode);
if(kbStruct->vkCode == VK_OEM_MINUS)
{
printf(" - oem minus!");
keybd_event(VK_DOWN, 72, KEYEVENTF_KEYUP, NULL);
return -1;
}
else if(kbStruct->vkCode == VK_OEM_PLUS)
{
printf(" - oem plus!");
keybd_event(VK_UP, 75, KEYEVENTF_KEYUP, NULL);
return -1;
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
I've tried using SendMessage and PostMessage with GetFocus() and GetForegroudWindow(), but can't figure out how to create the LPARAM for WM_KEYUP or WM_KEYDOWN. I also tried keybd_event(), which does simulate the keys (I know because this hook proc catches the simulated key presses), including 5 or 6 different scan codes, but nothing affects my foreground window.
I am basically trying to turn the zoom bar on my ms3200 into a scroll control, so I may even be sending the wrong keys (UP and DOWN).
Calling keybd_event is correct. If all you're doing is a key up, maybe the window processes the key down message instead. You really need to send a key down followed by a key up:
keybd_event(VK_UP, 75, 0, NULL);
keybd_event(VK_UP, 75, KEYEVENTF_KEYUP, NULL);
Or, better yet, send the key down when the OEM key goes down and a key up when the OEM key goes up. You can tell the down/up state by kbStruct->flags & LLKHF_UP.
You may wish to use SendInput, as keybd_event as has been superseded. The MSDN Magazine article C++ Q&A: Sending Keystrokes to Any App has a useful example.
You might want to try Control-UpArrow and Control-DownArrow instead of Up and Down. However this doesn't seem to work for all applications, and even on application where it does work, it may depend on where the focus is.

Resources