Click here to Skip to main content
15,890,512 members
Articles / Desktop Programming / MFC
Article

Getting a window size-grip (“grippie”) without the statusbar

Rate me:
Please Sign up or sign in to vote.
4.23/5 (18 votes)
17 Jul 2006CPOL2 min read 76.4K   1.2K   20   15
An article that describes how to add a size-grip control to windows.

Sample Image - grippie.gif

Introduction

As mentioned by Jensen Harris, many applications tend to steal screen real-estate from the user by adding a status bar for the sole reason of getting a resize “grippie”:

Girppie

This article is dedicated to eating a pie while keeping it whole. I will show you how to add a “grippie” without using a status bar.

Creating the “grippie”

The first surprise is that a grippie is in fact a scroll bar. Well, at least, it was a surprise for me. Since I am fond of MFC for UI jobs, I am choosing an MFC dialog application to show the trick. First of all, I set my dialog border style to “Resizing”; otherwise, why bother with “grippie” at all? In my dialog, I add a new member variable of type CScrollBar, like this:

// GrippieTestDlg.h : header file

#pragma once
// CGrippieTestDlg dialog

class CGrippieTestDlg : public CDialog
{
public:
    CGrippieTestDlg(CWnd* pParent = NULL);
    enum { IDD = IDD_GRIPPIETEST_DIALOG };
protected:
    virtual void DoDataExchange(CDataExchange* pDX);
protected:
    HICON m_hIcon;
    virtual BOOL OnInitDialog();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnBnClickedOk();
private:
    CScrollBar m_grippie;
};

Now, I add a handler for the dialog’s WM_CREATE message and the MFC wizard provides me with the handler OnCreate(LPCREATESTRUCT lpCreateStruct) in my dialog class. I add the following code in the handler to create my “grippie”:

#define GRIPPIE_SQUARE_SIZE 11

int CGrippieTestDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDialog::OnCreate(lpCreateStruct) == -1)
        return -1;

    CRect clientRect;
    GetClientRect(&clientRect);
    
    CRect grippieRect;
    grippieRect.right=clientRect.right;
    grippieRect.bottom=clientRect.bottom;
    grippieRect.left=clientRect.right-GRIPPIE_SQUARE_SIZE;
    grippieRect.top=clientRect.bottom-GRIPPIE_SQUARE_SIZE;
    m_grippie.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP|WS_CLIPSIBLINGS,
    grippieRect, this, 0);
    return 0;
}

Here we are with a nice “grippie”, and it works fine. But wait! The damn thing stays in the same place when you resize the window. Well, no problem, we are going to fix that.

Moving the grippie on window resize

We will fix it by adding a handler for the dialog’s WM_SIZE event:

void CGrippieTestDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialog::OnSize(nType, cx, cy);
    CRect clientRect;
    GetClientRect(&clientRect);
    if(m_grippie.m_hWnd!=NULL)
        m_grippie.SetWindowPos(NULL,
            clientRect.right-GRIPPIE_SQUARE_SIZE,
            clientRect.bottom-GRIPPIE_SQUARE_SIZE,
            GRIPPIE_SQUARE_SIZE,
            GRIPPIE_SQUARE_SIZE,
            SWP_NOZORDER|SWP_SHOWWINDOW);
}

Now, let’s wrap it up in a nice class.

CGrippie class

I will add a class to my project that is derived from CScrollBar and is called CGrippie:

// Grippie.h : header file

#pragma once

#define GRIPPIE_SQUARE_SIZE 11

class CGrippie : public CScrollBar
{
    DECLARE_DYNAMIC(CGrippie)
    CGrippie(const CGrippie& other);
    void operator=(const CGrippie& other);
public:
    CGrippie();
    virtual ~CGrippie();
protected:
    DECLARE_MESSAGE_MAP()
public:
    BOOL Create(CWnd* parent);
    void OnParentSize(void);
private:
    CWnd* m_parent;
};

Here is the implementation:

// Grippie.cpp : implementation file

#include "stdafx.h"
#include "GrippieTest.h"
#include "Grippie.h"

IMPLEMENT_DYNAMIC(CGrippie, CScrollBar)

CGrippie::CGrippie()
{
    m_parent=NULL;
}

CGrippie::~CGrippie()
{
}

BEGIN_MESSAGE_MAP(CGrippie, CScrollBar)
END_MESSAGE_MAP()

BOOL CGrippie::Create(CWnd* parent)
{
    m_parent=parent;
    if(m_parent==NULL)
        return FALSE;
    CRect clientRect;
    m_parent->GetClientRect(&clientRect);
    
    CRect grippieRect;
    grippieRect.right=clientRect.right;
    grippieRect.bottom=clientRect.bottom;
    grippieRect.left=clientRect.right-GRIPPIE_SQUARE_SIZE;
    grippieRect.top=clientRect.bottom-GRIPPIE_SQUARE_SIZE;
    return CScrollBar::Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, 
                              grippieRect, m_parent, 0);
}

void CGrippie::OnParentSize(void)
{
    if(m_parent==NULL)
        return;
    CRect clientRect;
    m_parent->GetClientRect(&clientRect);
    if(m_hWnd!=NULL)
        SetWindowPos(NULL, clientRect.right-GRIPPIE_SQUARE_SIZE,
                clientRect.bottom-GRIPPIE_SQUARE_SIZE,
                GRIPPIE_SQUARE_SIZE, GRIPPIE_SQUARE_SIZE,
                SWP_NOZORDER|SWP_SHOWWINDOW);
}

Now, all we need is to change the type of the m_grippie variable in the dialog class to CGrippie and change the implementation of the dialog message handlers like this:

int CGrippieTestDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDialog::OnCreate(lpCreateStruct) == -1)
        return -1;
    m_grippie.Create(this);
    return 0;
}

void CGrippieTestDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialog::OnSize(nType, cx, cy);
    m_grippie.OnParentSize();
}

Well, in case you are using VS2005, you are done now, but for VS2003 code, there is still a small thing to be handled: that is the mouse pointer shape when it is in the grippie area, but not in the bottom-right corner of the dialog. The shape should be like this: Correct cursor. But instead, it is a regular mouse pointer.

Handling the mouse pointer in VS2003

To fix the problem, I am going to add a handler for the WM_SETCURSOR message. To do so, I am going to add an event to the message map:

BEGIN_MESSAGE_MAP(CGrippie, CScrollBar)
    ON_WM_SETCURSOR()
END_MESSAGE_MAP()

Override the parent method OnSetCursor in CGrippie with the following code:

BOOL CGrippie::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if ( pWnd == this  &&  nHitTest == HTCLIENT )
    {
        ::SetCursor( ::LoadCursor( NULL, IDC_SIZENWSE ) );
        return( TRUE );
    }
    return CScrollBar::OnSetCursor(pWnd, nHitTest, message);
}

Well, that is it! We have a grippie in the dialog without that status bar!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Israel Israel

Comments and Discussions

 
QuestionGreat job Pin
kindi22-Dec-15 21:44
kindi22-Dec-15 21:44 
QuestionGreat job, thanks! Pin
Martin Henk20-Feb-14 23:37
Martin Henk20-Feb-14 23:37 
QuestionVS 2008 [modified] Pin
chatnal16-Oct-08 9:17
chatnal16-Oct-08 9:17 
AnswerRe: VS 2008 Pin
zengkun10016-Sep-09 17:28
zengkun10016-Sep-09 17:28 
GeneralMinor issues... Pin
Steve Johnson (Sven)22-Apr-08 11:54
Steve Johnson (Sven)22-Apr-08 11:54 
QuestionDoes this work in VC6? Pin
David Howe26-Jul-06 15:18
David Howe26-Jul-06 15:18 
AnswerRe: Does this work in VC6? Pin
Maksim Libenson26-Jul-06 20:01
Maksim Libenson26-Jul-06 20:01 
AnswerRe: Does this work in VC6? Pin
cristitomi19-Mar-07 2:23
cristitomi19-Mar-07 2:23 
Yes it works in VC6. I have ported it.
Mail me if interested and I will send you the application.
Best regards,
Christian.

I am in love with VC++
Generalanother approach: DrawFrameControl Pin
Mike D.24-Jul-06 10:59
Mike D.24-Jul-06 10:59 
GeneralRe: another approach: DrawFrameControl Pin
Maksim Libenson26-Jul-06 20:06
Maksim Libenson26-Jul-06 20:06 
GeneralGet a look to... Pin
Kochise18-Jul-06 6:20
Kochise18-Jul-06 6:20 
GeneralHandling of mouse pointer Pin
Julberto Danray3-Jun-06 18:19
Julberto Danray3-Jun-06 18:19 
GeneralRe: Handling of mouse pointer Pin
Maksim Libenson3-Jun-06 23:35
Maksim Libenson3-Jun-06 23:35 
GeneralAvoiding paint side effects Pin
Julberto Danray1-Jun-06 12:18
Julberto Danray1-Jun-06 12:18 
GeneralRe: Avoiding paint side effects Pin
Pavel Yankelevich3-Jun-06 23:32
Pavel Yankelevich3-Jun-06 23:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.