Win32 prevent window "snap"

2.3k views Asked by At

How can I disable the snap feature of Windows 7 for my application (progmatically)? Or is there any way to detect if the application has been snapped, and specifically call an API function to unsnap it?

Calling SetWindowPos() or ShowWindow() does not unsnap it correctly *(SW_MAXIMIZE does). Calling SetWindowPos() actually causes strange behavior in future calls to SetWindowPos() and MoveWindow(). The same inconsistencies do not apply to a window that is maximized.

2

There are 2 answers

1
18C On
#define WM_RESTOREORIGINALSTYLE WM_USER+... /* your first free USER message */

case WM_SYSCOMMAND:
{
   if(wParam==(SC_MOVE|2)) wParam=SC_SIZE|9;
   if((wParam&0xFFE0)==SC_SIZE && (wParam&0x000F)) // handles MOVE and SIZE in one "if"
   {
      long int oldStyle=GetWindowLongW(hwnd,GWL_STYLE);
      PostMessageW(hwnd,WM_RESTOREORIGINALSTYLE,GWL_STYLE,oldStyle);
      SetWindowLongW(hwnd,GWL_STYLE,oldStyle &0xFEFEFFFF); // disable WS_MAXIMIZE and WS_MAXIMIZEBOX
      DefWindowProcW(hwnd,WM_SYSCOMMAND,wParam,lParam);
      return 0;
   }
   return DefWindowProcW(hwnd,WM_SYSCOMMAND,wParam,lParam);
}
case WM_RESTOREORIGINALSTYLE:
{
   if((long int)wParam==GWL_STYLE)
      SetWindowLongW(hwnd,GWL_STYLE,lParam);
   return 0;
}

The PostMessage will be processed in subsequent message loop - it means ASAP after entering into move-size loop. If you use own drawing method of frame, please do not forget to redraw your frame correctly on WM_STYLECHANGED message, internally store oldStyle in your class. Why it works? Windows check snap condition at start of move/size action. If WS_MAXIMIZE and WS_MAXIMIZEBOX are disabled at start, the snap behaviour is disabled.

The SC_SIZE|9 is equivalent of SC_MOVE|2 without blocking redrawing for half a second.

If you don't want to enable dragging maximized windows if they are fully maximized, check state of SC_MOVE item in system menu and if it is enabled, directly return 0 in WM_SYSCOMMAND.

Verified on Windows 8.1.

0
Keyboard Chimp On

I figured out a way to unsnap, by calling ShowWindow() with SW_MAXIMIZE. This is odd since no other values unsnap with this call, even though the window can be moved away, it is still anchored to the side of the screen. Maximizing it fixes the problem, whereafter I can move the window where it needs to be.