#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.