If a mouse button is pressed and a window is shown that window will receive the MouseUp event when the mouse button is released.
Is it possible to detect, once the window is shown, whether or not a mouse button is already pressed?
I would try this:
procedure TForm1.FormShow(Sender: TObject);
begin
if GetKeyState(VK_LBUTTON) and $8000 <> 0 then
ShowMessage('Left mouse button is pressed...')
else
ShowMessage('Left mouse button is not pressed...')
end;
To answer your question directly, you can test for mouse button state with GetKeyState or GetAsyncKeyState. The virtual key code you need is VK_LBUTTON.
The difference between these is that GetKeyState reports the state at the time that the currently active queued message was posted to your queue. On the other hand, GetAsynchKeyState gives you the state at the instant that you call GetAsynchKeyState.
From the documentation of GetKeyState:
The key status returned from this function changes as a thread reads key messages from its message queue. The status does not reflect the interrupt-level state associated with the hardware. Use the GetAsyncKeyState function to retrieve that information.
An application calls GetKeyState in response to a keyboard-input message. This function retrieves the state of the key when the input message was generated.
I suspect that you should be using GetKeyState but I can't be 100% sure because I don't actually know what you are trying to achieve with this information.
Related
Is it possible to determine the source of a close request in a Windows application (Delphi)?
Background: I have an option to route close requests to minimizing the window to keep the app running "in Background".
procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
... different checking stuff e.g. unsaved changes
// Redirect Close to minimize but allow close if requested from minimized state
if FMinimize and (WindowState <> wsMinimized) then
begin
logger.debug('... closing main form redirected to minimize');
WindowState := wsMinimized;
CanClose := false;
exit;
end;
end;
This works well and allows closing the window by right clicking in the taskbar if already minimized. As icing of the cake I would like to determine if the close request came from right clicking the taskbar icon to close immediately even if the window is not already minimized. Is there a way to determine the source of the close request?
There is no difference between closing a window via the X button in its top-right corner, vs the Close window option on the right-click menu of the window's Taskbar button, vs the ALT-F4 keystroke. They all represent the same close command. If any of those options are invoked, the window will receive a WM_SYSCOMMAND(SC_CLOSE) message, which if passed to DefWindowProc() will generate a WM_CLOSE message that will trigger the Form's OnCloseQuery event. So no, there is no way to differentiate the source of the initial WM_SYSCOMMAND message. Only that the user wishes for the window to close.
That being said, you might try having your Form intercept the WM_NCHITTEST and WM_SYSKEYDOWN messages to detect when the user is clicking on the X button or pressing ALT-F4 on the keyboard. You can use those messages to set flags that your OnCloseQuery event can look at. That is about the only way I can think of right now to differentiate between Taskbar vs non-Taskbar closures.
I'm using the win32sdk, but some messages would never work as expected while mouse was captured by calling SetCapture(), such as:
case WM_LBUTTONDOWN:
SetCapture(hWnd);
SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
ReleaseCapture();
return 0;
The Window won't be maximized. but why?
Additional,
1. if I use PostMessage() instead, it works.
2. if I use PostMessage() instead and remove the ReleaseCapture(); statement, it doesn't work again.
In general:
PostMessage is asynchronous and you call ReleaseCapture() before WM_SYSCOMMAND is processed. So you have only one question: Why you can't maximize if mouse is captured?
I haven't found any info on this but read here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646262(v=vs.85).aspx
"When the mouse is captured, menu hotkeys and other keyboard accelerators do not work." I suppose WM_SYSCOMMAND is not processed also because of this restriction. May be it was done like this to keep coords consistent.
As norekhov said menu hotkeys don't work when the mouse is captured. When the mouse is captured the the only action a user can take that will result in the WM_SYSCOMMAND message being sent is to use a system menu hotkey.
Note that the WM_SYSCOMMAND message is only meant to be used to notify a window of a user initiated action. When you send it to a window, you're in essence trying to mimic a user's action. In this case you don't need to do this. You can tell the window to maximize itself directly:
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
In this case it won't appear to be a user command, so it won't be ignored because the mouse has been captured.
In a Qt dialog I have an embedded native Win32 window. As in any standard Win32, I define my own message queue, where, per default, I forward all events to the parent window, and in case an event of interest arrives, I perform some extra work.
My problem is that when I press the left mouse button, then I get the WM_LBUTTONDOWN as expected, but if I keep it pressed, then I get no more mouse clicks events, that is, I get the WM_MOUSE messages, but the mask (wParam), or calling GetKeyState, do not indicate that the mouse key is kept pressed.
The window is created with following parameters,
dwExStyle = WS_EX_TRANSPARENT;
dwStyle &= ~(WS_BORDER| WS_CAPTION | WS_DLGFRAME | WS_THICKFRAME);
CreateWindowExW(0,"Window","Name",dwStyle,
0,0,512,512,
hwndParent,NULL,hInstance,NULL )
When this native window is not embedded in any dialog, it works correctly.
I could also embed this window in a .NET dialog window and observe the same problem.
Any clue what could be going wrong?
Did you mean WM_MOUSEMOVE? Did you try capturing the mouse first?
WM_LBUTTONDOWN is sent only once per click. You'll have to use a boolean to keep track of whether the button is pressed or released during the WM_MOUSEMOVE events. Make use of the WM_LBUTTONDOWN and WM_LBUTTONUP messages together to keep track of this.
A program has called XGrabKey() to make a hotkey.
The user presses that key combination (while another window is focused).
The program receives control to do something in response to the key combination. Meanwhile, the program has been temporarily focused (because of the effects of XGrabKey (see man XGrabKey, man XGrabKeyboard)).
I want the program to create a synthetic X event (a keypress or mouse click) to the originally focused window. In some cases this means I need to focus that window before sending it the event (Firefox ignores synthetic events when it is not focused), which means I need to know which window it is. How can I find out which window it is?
Wait for the next FocusOut event, verify that the mode is set to NotifyUngrab, get the focus with XGetInputFocus(), and send away your synthetic events.
I am trying to put form into "help mode" in Delphi 2010.
I have a button which the user clicks, and I want the cursor to change to the help cursor, then when a user clicks onto a control, the help for the control is displayed
Is there a window message that I can send?
Send a WM_SYSCOMMAND message to the form passing SC_CONTEXTHELP as lParam.
Changes the cursor to a question mark with a pointer. If the user then clicks a control in the dialog box, the control receives a WM_HELP message.
Write something like this in your button OnClick event handler:
procedure TMyForm.Button1Click(Sender: TObject);
begin
SendMessage(Handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
end;