Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Determine if a window is 'moveable' or not

1 view
Skip to first unread message

Vinchenzo vinç

unread,
May 12, 2008, 5:01:41 PM5/12/08
to
Hi,
I only wish to know if, given a handle to window, we can determine if the window is moveable by the user interaction.

Firstly I thought that one way could be to call GetMenuState/GetSystemMenu/SC_MOVE, but fails until the system menu was invoked for a first time, when it seems to be generated (but this isn't correct at all), after that, further calls will return the correct state value, 3 (MF_DISABLED | MF_GRAYED). A simple example, one CommandButton on a Form:

'**************************
Private Declare Function GetMenuState Lib "user32.dll" ( _
ByVal hMenu As Long, _
ByVal wID As Long, _
ByVal wFlags As Long) As Long
Private Declare Function GetSystemMenu Lib "user32.dll" ( _
ByVal hwnd As Long, _
ByVal bRevert As Long) As Long
Private Const SC_MOVE = &HF010&

Private Sub Command1_Click()
Debug.Print Me.Moveable, GetMenuState(GetSystemMenu(Me.hwnd, 0), SC_MOVE, 0) = 0
End Sub
'**************************

if the 'Moveable' property of the Form is set to False, will print 'False True' until, at least, we show the Form's system menu (not always). Then, we can right-click on Form's title bar and see that the 'Move' command is disabled, cancel the menu and query again the menu state... the debug window now prints 'False False', as it should be.

I don't understand this behavior, and I don't know how to obtain the real moveable state.

And just out of curiosity, if we reset the menu on a Form that was started with "Moveable=False" at design time:

GetSystemMenu hWnd, -1

the 'Move' command is now enabled and operative, we can move the window, but actually, only with the system menu command, we will not be able to move it by the window's title bar (I supose that the windowproc is eating the mose notifications), and evidently from now GetMenuState will return 'True' because we are requesting the state of it's system menu command SC_MOVE, not the window's move capacity...


Thanks in advance.

--
Regards
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
( ! ) Preceding answers in Google:
http://groups.google.com/group/microsoft.public.vb.winapi
( i ) Temperance in the forum:
http://www.microsoft.com/communities/conduct/default.mspx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Jialiang Ge [MSFT]

unread,
May 13, 2008, 7:24:13 AM5/13/08
to
Hello Vinchenzo,

Thank you for sharing this creative way to determine whether a window is
moveable. I've reproduced the "False True" issue on my side. Please give me
some time, I am researching to see if I can work-around it, and whether or
not I can find other ways to accomplish the task. I will get back to you as
soon as possible.

Regards,
Jialiang Ge (jia...@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

=================================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msd...@microsoft.com.

This posting is provided "AS IS" with no warranties, and confers no rights.
=================================================

Vinchenzo vinç

unread,
May 13, 2008, 3:38:42 PM5/13/08
to

Thank you, Jialiang, I appreciate your attention and your time.

Jialiang Ge [MSFT]

unread,
May 15, 2008, 5:18:00 AM5/15/08
to
Hi, I think I am back with a good news. I find out a way to work-around the
"True False" issue. We need to post the WM_INITMENUPOPUP message to the
system menu like this:

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam
As Long) As Long
Private Const WM_INITMENUPOPUP = &H117

Dim menuHandle As Long
menuHandle = GetSystemMenu(Me.hwnd, 0)
SendMessage Me.hwnd, WM_INITMENUPOPUP, menuHandle, lParam:=&H10000
Debug.Print GetMenuState(menuHandle, SC_MOVE, 0) = 0

The description of WM_INITMENUPOPUP can be found at
http://msdn.microsoft.com/en-us/library/aa929343.aspx. Posting this message
to the form will initialize the system menu, and help us retrieve the
correct status of the "move" item.

Please have a try and let me know whether it works for you.

Vinchenzo vinç

unread,
May 15, 2008, 4:37:33 PM5/15/08
to
Hello Jialiang,
fully helpful answer, your workaround is working perfectly, WM_INITMENUPOPUP force the menu to be created, and now GetMenuState can retrieve the actual state of the menu item.

For those interested in, if there is a non-moveable window that is restored from the maximized or from the minimized state, we will get again SC_MOVE enabled, so we need to send the message each time we want to know the state because the menu is reset.


Jialiang, thank you very much for your help.

Randy Birch

unread,
May 29, 2008, 2:03:24 PM5/29/08
to
This is not a reliable way to determine if a window *is* moveable or not,
though it may be a way to determine if the user has the option to invoke a
Move command from a system menu item.

I can write subclassing code for VB that will trap and prevent any attempt
to move a window that has a complete sysmenu including the Move command.

--

Randy Birch
http://vbnet.mvps.org/

"Vinchenzo vinē" <Vinē@newsgroup.nospam> wrote in message
news:uJtQEust...@TK2MSFTNGP02.phx.gbl...

Vinchenzo vinç

unread,
Jun 1, 2008, 4:38:58 PM6/1/08
to

"Randy Birch" <rgb_rem...@mvps.org> escribió en el mensaje news:emLFLZbw...@TK2MSFTNGP03.phx.gbl...

> This is not a reliable way to determine if a window *is* moveable or not,
> though it may be a way to determine if the user has the option to invoke a
> Move command from a system menu item.
>
> I can write subclassing code for VB that will trap and prevent any attempt
> to move a window that has a complete sysmenu including the Move command.


Of course you are right, Randy, and also as you know, a borderless window without a system menu, wich is not moveable by the user, can be moved if the user is allowed to do it through 'SendMessage WM_NCLBUTTONDOWN, HTCAPTION'.
And more over, a window created at design-time as 'Moveable=False' can be "moved", at least through the Windows API functions MoveWindow, SetWindowPlacement and SetWindowPos.
So, I agree (as I said in my first post) that to retrieve the state of the SC_MOVE command is not reliable at all, but I can determine for a standard window if the user can move it by the title bar.

I think there's no trivial and absolutly realiable way to determine whether a window can be moved by the user (well, I hope I am wrong...). An indirectly way that I was thinking about is, given a window (not zoomed nor iconized), get its current coordinates, try to change the Top or the Left «mimicking a user interaction», compare the new coordinates (or an error return value may tell us) and restore to it's original position. I really don't like this way, and I don't want to use it (if it would work).

Meanwhile, I resigned to retrieve the SC_MOVE command state. Some day in the next weeks I'll get back to this feature, I don't surrender easily...


Thanks, your comments are appreciated.

0 new messages