Is this test enough to determine if user is dragging? - winapi

I want to determine if user is dragging listview item, by pressing ( and holding ) left mouse button.
I am processing WM_MOUSEMOVE and testing if user is dragging with if( wParam & MK_LBUTTON ).
Does this condition give me 100% accurate info about user dragging the mouse, or are there other pitfalls ( when testing like this ) I am unaware of?

Related

How to capture the action about starting dragging a window and releasing the capture of a window?

When cursor honver over the title zone (HTCAPTION),press left mouse button, then you can drag a window and move it. When you release the left mouse button , you can stop this dragging action. When you move a window , it triggered the message WM_MOVE. When release the mouse button , I don't know which message should be handled for catching this action.
What I'm doing is when you drag a window(let's say window A) into another window's area(window B), make window A a child window of window B, when drag window A out of window B's area , make window A a WS_POPUP window, without WS_CHILD style.
I handled message WM_MOVE and WM_CAPTURECHANGED( I don't think it's the right one).
In WM_CAPTURECHANGED , I found something wired. The API SetWindowPos seemed not work well. To be percise, the 3rd and the 4th parmater , specified the window's position not work.
case WM_CAPTURECHANGED: {
RECT rcc;
GetClientRect(main,&rcc);
// here main is the handler of window B , hwnd is for window A,as referrence above.
if(docker_mode==DOCKER_LEFT) {
// docker_mode is assigned by WM_MOVE message handler. recording which area window A was moved into.
if((WS_CHILD&GetWindowLongPtr(hwnd,GWL_STYLE))!=WS_CHILD) {
SetWindowLongPtr(hwnd,GWL_STYLE,(~WS_POPUP)&(WS_CHILD|GetWindowLongPtr(hwnd,GWL_STYLE)));
SetParent(hwnd,main);
}
//The following code not work. It should be moved into the left-top corner of window B,
//but NOT in fact.
SetWindowPos(hwnd,NULL,0,0,300,rcc.bottom-rcc.top,SWP_NOZORDER);
}
else {
if((WS_CHILD&GetWindowLongPtr(hwnd,GWL_STYLE))==WS_CHILD) {
SetWindowLongPtr(hwnd,GWL_STYLE,((~WS_CHILD)&GetWindowLongPtr(hwnd,GWL_STYLE))|WS_POPUP);
SetParent(hwnd,NULL);
SetWindowPos(hwnd,NULL,300,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
}
}
} break;
SetWindowLongPtr(...,GWL_STYLE,...) was called to set the window style . A top level has no WS_CHILD style, and the handle of parent window should be NULL , I use SetParent(hwnd,NULL) to do this. A child window should have WS_CHILD style, and the parent window should be assigned.
I put a button into the window , and copy those code into the handle of button click event. When click the button it works well , change a popup window into a sub window , put the sub window into right position. SetWindowPos has no problem at all. I don't know why.
SetWindowPos is a very interesting API when working on WM_CAPTURECHANGED handler. What's wrong ?
If I recall correctly, when the user drags a window, that window receives a sequence of messages like this:
WM_ENTERSIZEMOVE
WM_WINDOWPOSCHANGING
WM_MOVING
WM_WINDOWPOSCHANGED
WM_MOVE
WM_EXITSIZEMOVE
(There are other messages, too, but I don't think you need to worry about those. There may be some final messages after WM_EXITSIZEMOVE with the final resting place for the window.)
The steps in the middle will happen repeatedly as the user drags the window. (In the Old Days, only some of those middle steps would happen, and there may still be an option to cut down on the messages during the drag operation.)
You can try using Spy++ (included with Visual Studio) to confirm the above.
So you shouldn't need to deal with the mouse capture messages. Have window A watch for WM_EXITSIZEMOVE. At that point, window A can check its position to see if it overlaps the target window (B). If it does overlap, then it should send a message to window B to initiate the docking operation.

Stop a sheet from making a window the main/key window

I have two windows in my application (document based), a main and secondary window. I want to keep the secondary window behind the main window unless the user clicks on it or the main window decides to show it (via a user pressed button).
The issue is that the secondary window has a modal sheet which makes it come to the foreground. I want to stop it from doing that.
Current solution:
Before the sheet appears I increase the main window's level by 1
After the sheet is done I decrease the main window's level by 1
Problems:
My timing of knowing when these sheets occur is bad and unreliable
The window flickers a bit
Notes:
I have tried making the secondary window a child window of the main one, however this links them too strongly, where dragging one drags the other and I do want the secondary window to surface when the user clicks on it.

WinAPI Methodology to Detect Button Swiping/Dragging

I have a virtual keyboard and I am trying to figure out a way to detect the user swiping keys, ie, pressing one winapi button control down (for eg 'Q') then moving the mouse/finger around over other keys to type out words. For a better description see the below image.
Currently the only solution I can think of is detect a WM_LBUTTONDOWN on a button. Then detect WM_MOUSEMOVE events over other buttons (by hit testing?) and record that key. When I next receive a WM_LBUTTONUP I know the user is finished typing. I've also tried to detect WM_TOUCH and WM_TOUCHHITTESTING events but on a Surface Pro 3 these events are not firing but this could be I need to register for these events?
Is there an existing WinAPI function/methodology I could use that I am unaware of?

Is it possible to see where control focus is being lost to?

I have a ClistCtrl (wraps Windows list view for non-MFC users) on a dialog. I set functionality that when the list loses focus, any selected items are unselected.
I also have a "remove items" button, whose on-click handler will delete any selected items in the list.
The idea is you select items in the list, and then either click the button to remove these items, or click somewhere else and the selection is cancelled.
But, when you click the delete button, the list loses focus first and therefore nothing happens! Is there a way around this?
You can receive message about lost focus with WM_KILLFOCUS, its wParam will give you a handle to window which got focus:
wParam
A handle to the window that receives the keyboard focus. This
parameter can be NULL.
You should be able to use Spy++ to see WM_KILLFOCUS on you list window, and read its wParam - and later find also with spy++ which window is it.
As said in other posts, you can use WM_KILLFOCUS for that.
But I think it's a very bad idea to clear the selection on losing focus.
Just imagine: the user selects a whole bunch of items using multiselect (using shift, ctrl, scrollbar..), and then, one of the following happens:
The phone rings, urgent call - the user needs to check a mail: selection: gone!
An annoying message box pops up taking focus (yes, it does happen): selection -> gone.
Your users might hate you for this, so don't do it :) (not even if there are only 3 items in the listcontrol).
The usual way is to gray the selection on losing focus. You could add a 'clear selection' button, but even that isn't needed. Just clicking on one item will clear the selection (except for that one item of course).
Bottom line: don't clear the selection on losing focus, ever.
Update:
If the selection is not visible on losing focus, the LVS_SHOWSELALWAYS flag is what you need:
LVS_SHOWSELALWAYS
The selection, if any, is always shown, even if the control does not
have the focus.

How can I tell if a window has focus? (Win32 API)

Using the Win32 API (in C, but that's inconsequential), how can I tell if a given window (identified by HWND) has focus?
I'm hooking an application watching for an event, and when that event occurs I want to check if the application already has focus. If it doesn't, I want to flash the window until they give focus to it.
Alternately, does the FlashWindowEx struct flag FLASHW_TIMERNOFG that flashes until the window has focus just not flash if the window already has focus?
I cannot test this now since I am not in my development environment, but I was under the impression that it would flash anyways, which is what I'm trying to avoid.
Also, if it matters, the application uses DirectX in this window.
GetActiveWindow will return the top-level window that is associated with the input focus. GetFocus will return the handle of the window that has the input focus.
This article might help:
http://www.microsoft.com/msj/0397/Win32/Win320397.aspx
Besides gkrogers answer using GetActiveWindow, you can also maintain a boolean variable for the window you want to know if it has focus or not by trapping the WM_SETFOCUS and WM_KILLFOCUS events, or WM_ACTIVATE:
WndProc() ..
case WM_SETFOCUS:
puts( "Got the focus" ) ;
break ;
case WM_KILLFOCUS:
puts( "Lost the focus" ) ;
break;
case WM_ACTIVATE:
if( LOWORD(wparam) == WA_INACTIVE )
puts( "I AM NOW INACTIVE." ) ;
else // WA_ACTIVE or WA_CLICKACTIVE
puts( "MEGAZORD ACTIVATED kew kew kew (flashy-eyes)" ) ;
break ;
Do you really mean "focus" or do you mean "active?"
One window has the focus -- the one that's first in line to get keyboard events. The outer window (that the user can drag around the screen) is "active" if one of its subwindows has the focus, but it might or might not have focus itself.
Use GetForegroundWindow function to get the Hwnd that you are focusing right now. Then you just need to compare it to the window of your application to check whether it contains focus or not.
For multiple modeless children:
Within the child you could save the focus, 13/08/2019 Visual Studio 2017.
You can save the focus so the parent knows which modeless child was clicked on.
In the child's callback handler:
case WM_CHILDACTIVATE: // Only gets called when the child border is click on.
//CurrentFocus = hDlg; // Example: can save the focus globally for parent usage.
//Beep(2000, 250); // So you can test
break;
case WM_GETMINMAXINFO: // Gets called when child window is being moved or sized.
//Beep(2000, 250);
break;
case WM_LBUTTONDOWN: // Only called when cursor is inside the child client area
//CurrentFocus = hDlg; // Following the focus.
//Beep(2000, 250);
break;

Resources