I have a strange problem about a MFC windows application in dual monitor system.
Let's say I have monitor A and monitor B.
If my window toolbar (start menu etc) is in monitor A and A is alsom my primary monitor. My application works fine. However, if A has toolbar while B is the primary monitor. When I move my application to window A, the tab is not clickable while other controls (buttons..)work.
I have no clue what's going on. Any suggesttions are appreciated..
Finally I figured out the problem. To get the tab index, the code use last message position to get the click point and use HitTest to figure out which tab is clicked. In the multiple monitor system, we should not use LOWORD and HIWORD as described below:
"Important Do not use the LOWORD or HIWORD macros to extract the x- and y- coordinates of the cursor position because these macros return incorrect results on systems with multiple monitors. Systems with multiple monitors can have negative x- and y- coordinates, and LOWORD and HIWORD treat the coordinates as unsigned quantities."
http://msdn.microsoft.com/en-us/library/ms644938(v=vs.85).aspx
After I use the GET_X_LPARAM or GET_Y_LPARAM it works!
Related
I have an application that creates a windows tray icon. When the user right clicks on it, a context menu is displayed. The application works fine until DPI scaling is done from control panel. For eg. when DPI scaling is set to 150% (Scaling value when I logged in), the context menu will be shown correctly, but when I change DPI scaling to 125% (without logging out and logging back again - after logging out and logging in again they agree), the context menu gets displaced, and is shown at a position far away from the tray icon. This does not happen if I use GetCursorPos() instead of GET_X_LPARAM(wParam), and GET_Y_LPARAM(wParam) to get mouse coordinate.
MSDN documentation on NOTIFYICONDATA (https://msdn.microsoft.com/en-us/library/windows/desktop/bb773352(v=vs.85).aspx) data structure says that GET_X_LPARAM(wParam), and GET_Y_PARAM(wParam), inside the callback function which handles uCallbackMessage should give X, and Y coordinates of the right-mouse-button click event (which is used to invoke tray icon's context menu). This does not happen when DPI is changed in the manner written above. GetCursorPos() however continues to give correct value.
I feel that they should always report the same value.
EDIT 1 - Assume that after a right click, the mouse hasn't moved, in which case both should give the same coordinates.
EDIT 2 - Repro (Information regarding reproducing the bug)
Have a look at the following open source project, Picotorrent.
In NotifyIconController.cpp::NotifyIconController::Execute() , I added the following lines of code to print the values returned by GET_X_LPARAM(), and GetCursorPos() (highlighted code in the image).
TCHAR debug_string[50];
_stprintf_s(debug_string,sizeof(debug_string), _T("\n\n[wParam :(x,y)=(%d,%d)]\n"), GET_X_LPARAM(wParam), GET_Y_LPARAM(wParam));
OutputDebugString(debug_string);
POINT pt;
GetCursorPos(&pt);
_stprintf_s(debug_string,sizeof(debug_string),_T("[GetCursorPos:(x,y)=(%d,%d)]\n"), pt.x, pt.y);
OutputDebugString(debug_string);
The program, Picotorrent when run, creates a tray icon. When user right clicks on the tray icon, a context menu is shown on the location of mouse pointer at the time of click. As of now, to display the context menu the X,Y coordinates of the click are being obtained using GET_X_LPARAM(wParam), and GET_Y_LPARAM(wParam).
See the following screenshots showing the position of context menu with respect to the tray icon at different DPI scaling values.
The following image shows the position of the context menu when the DPI scaling is 150%. This was the DPI scaling value when I logged in to the system.
The following image shows the position of the context menu when DPI scaling is changed to 125%. Notice that windows is telling me to log out, and log back in. But since our task here is to study why GET_X_LPARAM(), and GetCursorPos() aren't showing same value (whether right or wrong, doesn't matter). Also, notice that the context menu is no longer displayed near the tray icon. Remember that here I am using GET_X_LPARAM(wParam), and GET_Y_LPARAM(wParam) to get X, and Y coordinates for displaying the menu, and not GetCursorPos().
Now, let us see the output in the debugger's output window.
[wParam :(x,y)=(1539,1045)]
[GetCursorPos:(x,y)=(1539,1045)]
[wParam :(x,y)=(1606,1054)]
[GetCursorPos:(x,y)=(1927,1265)]
Also, see the following screenshot.
From the output we can clearly see that initially GET_X_LPARAM(), and GetCursorPos() agree on the values of coordinates, but when scaling value is changed, they do not.
I can't seem to find how to select text in my console application via WinAPI. Pretty much what could be done with the mouse, if someone right-clicks the console window and selects "Mark":
and then drags the mouse on the console window:
Can I do this with WinAPIs?
There is no API to do what you are asking for. So you will have to simulate it instead.
Use SetConsoleMode() to enable the ENABLE_QUICK_EDIT_MODE to enable selecting text with the mouse. Then use SendInput() or mouse_event() to manipulate mouse movement and clicks as needed.
Use GetConsoleWindow() to get the console's HWND, and GetWindowRect() to get its position onscreen. Use GetConsoleScreenBufferInfo/Ex() to get the column/row counts of the console, and the rectangle where the characters appear within the console window. Then you should be able to use some math to translate character column/row offsets into screen coordinates as needed when sending mouse actions.
Use ReadConsoleOutput to read the area that you want to select. Change the received CHAR_INFO Attributes for each character to reflect different (e.g. inverted) colours. Use WriteConsoleOutput to write the modified data to the same rectangular area. This will show a 'selected' area. If needed use SetConsoleCursorPosition to change the cursor position. An example how to use the ReadConsoleOutput and WriteConsoleOutput can be seen here.
I need to draw an icon that moves approximately in sync with mouse cursor and is always on top of all windows.
OS: Windows 7
I have a solutions that work to some extend by drawing my icon in a top most transparent window. There are some major drawbacks in this solution since that top most window interferes with other top most windows and some full screen apps do not work correctly. Examples are start menu and task bar that will overlay my window if I do not regulary set it to be top most. For some full screen applications performance of updating position of window with icon hugely drops and it does not follow mouse smoothly.
There is another method that I came across where an icon is drawn directly to the device context of desktop Draw mouse pointer icon?. This solution has a drawback that there seems to be no good way of how to remove "trail", especially if desktop content changes quickly.
So my question: is there an ultimate solution that does not have the above mentioned problems?
Is it possible to draw above all windows in the "layer" of mouse cursor? Or make a second mouse cursor with my custom icon that I will control (I know that widows can display two independently controlled mouse cursors like CPNMouse)?
Can someone point me to the right direction?
Thanks!
Use a top-most window with transparency set via WS_EX_LAYERED / UpdateLayeredWindow.
If you set the WS_EX_TRANSPARENT style as well then the window won't intercept mouse input.
I am using Qt, what I want to do is to display custom popup over the icon in system tray in Windows. I can obtain icon coordinates by using geometry() and taskbar height by finding difference between screenGeometry() and availableGeometry(). So the popup can be alligned correctly and does not overlap taskbar for different taskbar orientations (e.g. when taskbar is on the left side or on the top of the screen).
The problem starts when autohide of taskbar is turned on, then apparently availableGeometry returns the same value as screenGeometry, and I cannot find the taskbar height anymore. This results in the popup overlapping with taskbar, or even displayed at the wrong location.
My question is: how can I detect correctly orientation and size of taskbar in Windows, when the autohide is enabled? Should I use some winapi function, or can I do it purely in Qt (preferable) ?
1) Autohide state you check using this: http://msdn.microsoft.com/en-us/library/bb787947(v=vs.85).aspx
2) And find width/height/orientation using this: http://msdn.microsoft.com/en-us/library/bb787953(v=vs.85).aspx
Hope this helps. Yes, this is WinAPI functions, so you should use this code in "#ifdef Q_OS_WINDOWS" only - if want to compile on Linux too.
I would like to send some keystrokes from a C++ program into another window.
For that reason I would like to have the user select the target window similar to how it is done in the Spy++ utility that comes with Visual Studio (drag a crosshair cursor over target window and have target window highlighted by a frame).
How is this dragging and selecting done in Windows? I am completely lost as to where I might start to look for a mechanism to implement this feature.
Here's how it's usually done:
Capture the mouse using SetCapture. This will cause all mouse messages to be routed toward your app's window.
Handle the WM_MOUSEMOVE message. In your handler code, grab the window underneath the mouse using WindowFromPoint. That will get you the HWND of the window the mouse is currently over.
Now that you've got the window, you need a device context (HDC). You can get one using GetWindowDC for the specified window.
Now you can draw into the DC using typical GDI functions.
There are some things you have to look out for - cleanly erasing the selection rectangle and so forth, but that's one way to do it.
You could also draw into a screen DC to do this, but in any case you'll need the window handle in order to get the window rect.
If you Google around Spy++ source code you'll see a few examples of this technique.
Formers answers are wrong.
Spy++ source code has been given on G. Groups for years (see mainly Win32 api ng news://194.177.96.26/comp.os.ms-windows.programmer.win32)