c++winapi

Win32 detect if window is maximized/docked to half screen (Win-key + Left/Right)


I have a classic Win32-API (C++) application and need to detect if the window is docked to the left/right half of the screen.

Background of the question is that the window only sizes in grid steps, let's say 32 pixel. In full screen the program detects that state, allow size to match the full screen and pad the excess space. With Windows 8 and later I would like to do the same instead of currently leaving borders (because the size snaps to a multiple of 32 pixel).


Solution

  • In addition to what IInspectable has already mentioned, there is another way to determine this information and act accordingly.

    1. Wait for a WM_WINDOWPOSCHANGED message and read its x, y, cx, and cy values from the WINDOWPOS pointer stored in lParam.
    2. Get a handle to the current monitor on which the window is placed by calling MonitorFromWindow.
    3. Create a MONITORINFO variable and set its cbSize field to sizeof(MONITORINFO).
    4. Use the monitor handle and the address of your MONITORINFO variable to call GetMonitorInfo.
    5. Read the rcWork value from your MONITORINFO variable.
      • rcWork.top == WINDOWPOS.y && rcWork.bottom == (WINDOWPOS.y + WINDOWPOS.cx) && rcWork.left == WINDOWPOS.x - the window is "docked" to the left
      • rcWork.top == WINDOWPOS.y && rcWork.bottom == (WINDOWPOS.y + WINDOWPOS.cx) && rcwork.right == (WINDOWPOS.x + WINDOWPOS.cx) - the window is "docked" to the right
      • rcWork.top == WINDOWPOS.y && rcWork.left == WINDOWPOS.x && rcWork.right == (WINDOWPOS.x + WINDOWPOS.cx) - the window is "docked" to the top
      • rcWork.top == (WINDOWPOS.y + WINDOWPOS.cy) && rcWork.left == WINDOWPOS.x && rcWork.right == (WINDOWPOS.x + WINDOWPOS.cx) - the window is "docked" to the bottom

    You say you already have logic to determine if the window is fullscreen (do you mean fullscreen or maximized?), but effective maximization can be determined if left == x && top == y && right == x + cx && bottom == y + cy.

    Here is an MSDN example of something similar.

    Note that it may be more desirable to cache the MONITORINFO values so you don't need to call it every time the window is repositioned.


    If you only want this to apply when a user does NOT manually resize the window, here is a contrived example of a possible way to do so:

    LRESULT CALLBACK windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
      static bool userSizing = false;
    
      switch (msg)
      {
      // could also catch WM_ENTERSIZEMOVE here, but this will trigger on 
      // moves as well as sizes
      case WM_SIZING:
        userSizing = true;
        break;
    
      case WM_EXITSIZEMOVE:
        userSizing = false;
        break;
    
      case WM_WINDOWPOSCHANGED:
        if (userSizing)
        {
          break;
        }
    
        // do logic to check to see if the window is sized in a "docked"
        // manner here
        break;
    
      // handle other window messages ...
    
      }
    }