Thread: Size Grip & Window Resizing

  1. #1
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591

    Size Grip & Window Resizing

    How may I add a "size grip" to the bottom-right corner of my window? And what is the standard method of resizing a window and re-positioning/resizing its controls?
    As usual, a search for this on MSDN yields everything BUT basic win32 API solutions.

    So far, I am planning on catching the WM_SIZING notification and updating each control based on the new client rect. Is this the standard way of doing things? Also, I am able to get the resize mouse icon with the WS_SIZEBOX style, but still no size grip icon.

  2. #2
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    Here's some code I've created to prevent the window from being sized smaller than default:
    Code:
            case WM_SIZING:
            {
                LPRECT pRect = (LPRECT)lParam;
    
                TITLEBARINFO tbi;
                tbi.cbSize = sizeof(tbi);
                GetTitleBarInfo(hwnd, &tbi);
    
                switch(wParam)
                {
                    case WMSZ_BOTTOMLEFT:
                    {
                        if(pRect->right - pRect->left < DEF_WIDTH_SETUPDLG)
                            pRect->left = pRect->right - DEF_WIDTH_SETUPDLG;
                    }
                    case WMSZ_BOTTOM:
                    {
                        if(pRect->bottom - pRect->top -
                           (tbi.rcTitleBar.bottom-tbi.rcTitleBar.top) < DEF_HEIGHT_SETUPDLG)
                            pRect->bottom = pRect->top + DEF_HEIGHT_SETUPDLG + (tbi.rcTitleBar.bottom - tbi.rcTitleBar.top);
                        break;
                    }
    
                    case WMSZ_BOTTOMRIGHT:
                    {
                        if(pRect->bottom - pRect->top -
                           (tbi.rcTitleBar.bottom-tbi.rcTitleBar.top) < DEF_HEIGHT_SETUPDLG)
                            pRect->bottom = pRect->top + DEF_HEIGHT_SETUPDLG + (tbi.rcTitleBar.bottom - tbi.rcTitleBar.top);
                    }
                    case WMSZ_RIGHT:
                    {
                        if(pRect->right - pRect->left < DEF_WIDTH_SETUPDLG)
                            pRect->right = pRect->left + DEF_WIDTH_SETUPDLG;
                        break;
                    }
    
    
                    case WMSZ_TOPLEFT:
                    {
                        if(pRect->bottom - pRect->top -
                           (tbi.rcTitleBar.bottom-tbi.rcTitleBar.top) < DEF_HEIGHT_SETUPDLG)
                            pRect->top = pRect->bottom - DEF_HEIGHT_SETUPDLG - (tbi.rcTitleBar.bottom - tbi.rcTitleBar.top);
                    }
                    case WMSZ_LEFT:
                    {
                        if(pRect->right - pRect->left < DEF_WIDTH_SETUPDLG)
                            pRect->left = pRect->right - DEF_WIDTH_SETUPDLG;
                        break;
                    }
    
    
                    case WMSZ_TOPRIGHT:
                    {
                        if(pRect->right - pRect->left < DEF_WIDTH_SETUPDLG)
                            pRect->right = pRect->left + DEF_WIDTH_SETUPDLG;
                    }
                    case WMSZ_TOP:
                    {
                        if(pRect->bottom - pRect->top -
                           (tbi.rcTitleBar.bottom-tbi.rcTitleBar.top) < DEF_HEIGHT_SETUPDLG)
                            pRect->top = pRect->bottom - DEF_HEIGHT_SETUPDLG - (tbi.rcTitleBar.bottom - tbi.rcTitleBar.top);
                        break;
                    }
    
                    default: return FALSE;
                }
    
                // ToDo: Resize & reposition controls here //
    
                return TRUE;
                break;
            }
    Everything seems to be working fine, is this the standard solution for this task?

  3. #3
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> is this the standard solution for this task? <<

    No, WM_GETMINMAXINFO is.

    Typically, client controls are resized/positioned in response to a WM_SIZE message.

  4. #4
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    Wow thanks! I knew there was something a bit kludgey about my approach.
    Now all I have to worry about is getting the "size grip" icon to appear bottom-right... any ideas?

  5. #5
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    I've implemented the WM_GETMINMAXINFO and WM_SIZE again, and the first works perfectly, however repositioning child controls in WM_SIZE leaves artifacting all over the place (i.e. if I resize left-to-right and back repeatedly I can see remnants of the controls overlapping themselves) no matter how much I try to redraw the window. Here's the code I'm using, with my multiple redraw attemps highlighted in bold (none of which work):
    Code:
           //this works great, thanks anony
            case WM_GETMINMAXINFO:
            {
                TITLEBARINFO tbi;
                tbi.cbSize = sizeof(tbi);
                GetTitleBarInfo(hwnd, &tbi);
    
                ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = DEF_WIDTH_SETUPDLG;
                ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = DEF_HEIGHT_SETUPDLG + (tbi.rcTitleBar.bottom - tbi.rcTitleBar.top);
    
                return 0;
                break;
            }
            //this leaves artifacting
            case WM_SIZE:
            {
                if(wParam == SIZE_RESTORED)
                {
                    RECT rect;
                    TITLEBARINFO tbi;
                    int origWidth = curWidth;
                    int origHeight = curHeight;
                    tbi.cbSize = sizeof(tbi);
                    GetTitleBarInfo(hwnd, &tbi);
                    GetWindowRect(hwnd, &rect);
                    curWidth = rect.right - rect.left;
                    curHeight = rect.bottom - rect.top - (tbi.rcTitleBar.bottom-tbi.rcTitleBar.top);
    
                    if(origWidth != curWidth)
                    {
                        int i;
                        HWND hCtrl;
                        RECT rcCtrl;
                        for(i = IDC_FIRSTCTRL; i <= IDC_LASTCTRL; ++i)
                        {
                            hCtrl = GetDlgItem(hwnd, i);
                            GetWindowRect(hCtrl, &rcCtrl);
                            POINT pt = {rcCtrl.left + (curWidth-origWidth), rcCtrl.top};
                            ScreenToClient(hwnd, &pt);
    
                            SetWindowPos(hCtrl, NULL, pt.x, pt.y, 0,0,
                                         SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
                            ShowWindow(hCtrl, SW_SHOW);
                        }
                    }
                    RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
                    UpdateWindow(hwnd);
                }
                return 0;
                break;
            }
    Windows even gives an example of this in which they use MoveWindow to move the control and ShowWindow to update it in response to WM_SIZE. I've tried MoveWindow and it produces the same artifacting. I've also tried updating control positions only on response to WM_EXITSIZEMOVE, however this does not allow the user to concurrently track where the controls will end up. So what do I need to do inorder to prevent the controls from being improperly redrawn while moving them about in response to WM_SIZE?

  6. #6
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    I don't think you should do any redrawing until all the controls are moved. Use MoveWindow with FALSE as the last argument and only call UpdateWindow at the end (you can probably even avoid using UpdateWindow, Windows should do it automatically). ShowWindow and RedrawWindow shouldn't be needed.

    Other than that, there may be a problem with the painting. Possible suggestions include:
    * You are using a NULL background brush.
    * You have overridden the WM_ERASEBKGND message.
    * You are not calling BeginPaint in your WM_PAINT handler.

  7. #7
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    I've tried moving first then updating afterwards both with MoveWindow using TRUE and FALSE and with SetWindowPos to no avail. The background brush is the default for dialog boxes (though I'm not sure what that is), and I have no implementations for the other two messages.

    There's another layer to the problem:
    I have two columns of controls and on resizing the window to the right, the right-most column is consistently artifacted.. However, if I reverse the order in which the controls are moved (i.e. inverse the for loop) and instead reposition them starting with the right-bottom-most control first, then the behaviour is reversed and the leftmost controls experience artifacting when I resize to the left. So in brief, when the controls are updated starting top-left-most to bottom-right-most (i.e. in reading order), then when resizing to the right, the leftmost control is drawn ontop of the right control. And when the controls are updated right-to-left and bottom-to-top, then when resizing to the left, the rightmost control is drawn overtop of its neighbouring left one.

    I've found that when resizing is done deliberately slowly, this effect can be avoided. Even more perplexing and baffling though, is as to why the left control would be drawn over the right control if we are resizing right!!?? I could understand if, when resizing right, the right control failed to update and it was drawn over or drew over the left control, but the otherway around leaves me just scratching my head!
    The first screenshot shows the left controls overlapping the right when the controls are updated in reading order and when resizing right. The second shows the right controls overlapping the left when updating in reverse order and resizing to the left (the arrows show the direction of resizing):

    edit: I wonder if placing those controls in a child-window and then moving it would help things?
    edit2: well at least I found out how to add the "grippie" now. Apparently its a Scrollbar control?!... wow... only in bizarro world...
    Last edited by @nthony; 08-23-2007 at 06:14 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Just starting Windows Programming, School me!
    By Shamino in forum Windows Programming
    Replies: 17
    Last Post: 02-22-2008, 08:14 AM
  2. Why only 32x32? (OpenGL) [Please help]
    By Queatrix in forum Game Programming
    Replies: 2
    Last Post: 01-23-2006, 02:39 PM
  3. An exercise in optimization
    By Prelude in forum Contests Board
    Replies: 10
    Last Post: 04-29-2005, 03:06 PM
  4. Problem with creating new window, from another window
    By Garfield in forum Windows Programming
    Replies: 6
    Last Post: 01-11-2004, 02:10 PM
  5. Invoking MSWord
    By Donn in forum C Programming
    Replies: 21
    Last Post: 09-08-2001, 04:08 PM