Click here to Skip to main content
15,884,472 members
Articles / Desktop Programming / ATL

Win32 Dialog Helpers

Rate me:
Please Sign up or sign in to vote.
4.94/5 (38 votes)
18 Apr 200311 min read 273.9K   3.1K   79  
Easy support for dialog resizing and ActiveX controls
This article provides a few samples to enable features in WIN32 dialogs such as support for dialog resizing and ActiveX controls. VC++6 / VC++7.x projects are provided.
// ResizableGrip.cpp: implementation of the CResizableGrip class.
//
/////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2000-2001 by Paolo Messina
// (http://www.geocities.com/ppescher - ppescher@yahoo.com)
//
// The contents of this file are subject to the Artistic License (the "License").
// You may not use this file except in compliance with the License. 
// You may obtain a copy of the License at:
// http://www.opensource.org/licenses/artistic-license.html
//
// If you find this code useful, credits would be nice!
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ResizableGrip.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#endif





// Constructor
CResizableControl::CResizableControl()
{
	m_hCtrl = NULL;
	m_bAllowMoveX = m_bAllowMoveY = m_bAllowResizeX = m_bAllowResizeY = FALSE;
}

// Methods
void CResizableControl::AllowMoveOnResize(BOOL bAllow)
{
	m_bAllowMoveX = m_bAllowMoveY = bAllow;
}

void CResizableControl::AllowMoveXOnResize()
{
	m_bAllowMoveX = TRUE;
}

void CResizableControl::AllowMoveYOnResize()
{
	m_bAllowMoveY = TRUE;
}

void CResizableControl::AllowResizeOnResize(BOOL bAllow)
{
	m_bAllowResizeX= m_bAllowResizeY = bAllow;
}

void CResizableControl::AllowResizeXOnResize()
{
	m_bAllowResizeX = TRUE;
}

void CResizableControl::AllowResizeYOnResize()
{
	m_bAllowResizeY = TRUE;
}

void CResizableControl::Init(HWND hCtrl)
{
	// save the initial bounding rects of this control, and its parent
	m_hCtrl = hCtrl;
	if (m_hCtrl)
	{
		::GetWindowRect(m_hCtrl, &m_rect);
		HWND hParent = ::GetParent(m_hCtrl);
		if (hParent)
			::GetWindowRect(hParent,&m_parentrect);
	}
}

void CResizableControl::MoveAndResize()
{
	if (!m_hCtrl) return;

	if ( (m_bAllowMoveX || m_bAllowMoveY) && !(m_bAllowResizeX || m_bAllowResizeY) ) // move the ctrl
	{
		HWND hParent = ::GetParent(m_hCtrl);
		if (hParent)
		{
			::InvalidateRect(m_hCtrl, NULL, TRUE);

			::GetWindowRect(m_hCtrl,&m_rect);
			POINT pt1 = { m_rect.left, m_rect.top };
			POINT pt2 = { m_rect.right, m_rect.bottom };
			::ScreenToClient(hParent, &pt1);
			::ScreenToClient(hParent, &pt2);
			m_rect.left = pt1.x;m_rect.top = pt1.y;
			m_rect.right = pt2.x;m_rect.bottom = pt2.y;

			RECT parentrect;
			::GetWindowRect(hParent,&parentrect);
	
			int x = m_rect.left + (m_bAllowMoveX ? 
				( (parentrect.right - parentrect.left) - (m_parentrect.right - m_parentrect.left)) : 0);
			int y = m_rect.top + (m_bAllowMoveY ? 
				( (parentrect.bottom - parentrect.top) - (m_parentrect.bottom - m_parentrect.top)) : 0);

			m_parentrect = parentrect;

			::SetWindowPos(m_hCtrl, NULL, x,y, 0,0, SWP_NOSIZE);
		}
	}
	else if ( !(m_bAllowMoveX || m_bAllowMoveY) && (m_bAllowResizeX || m_bAllowResizeY) ) // resize the ctrl
	{
		HWND hParent = ::GetParent(m_hCtrl);;
		if (hParent)
		{
			RECT parentrect;
			::GetWindowRect(hParent,&parentrect);
	
			int cx = (m_rect.right-m_rect.left) + (m_bAllowResizeX ? 
				( (parentrect.right - parentrect.left) - (m_parentrect.right - m_parentrect.left)) : 0);
			int cy = (m_rect.bottom-m_rect.top) + (m_bAllowResizeY ? 
				( (parentrect.bottom - parentrect.top) - (m_parentrect.bottom - m_parentrect.top)) : 0);

			::SetWindowPos(m_hCtrl, NULL, 0,0, cx,cy, SWP_NOMOVE);
		}
	}
	else if ( (m_bAllowMoveX || m_bAllowMoveY) && (m_bAllowResizeX || m_bAllowResizeY) ) // move and resize the ctrl
	{
		HWND hParent = ::GetParent(m_hCtrl);;
		if (hParent)		
		{
			if (::IsIconic(hParent) || !::IsWindowVisible(hParent) || !::IsWindowEnabled(hParent))
				return;

			::InvalidateRect(m_hCtrl, NULL, TRUE);

			::GetWindowRect(m_hCtrl,&m_rect);
			POINT pt1 = { m_rect.left, m_rect.top };
			POINT pt2 = { m_rect.right, m_rect.bottom };
			::ScreenToClient(hParent, &pt1);
			::ScreenToClient(hParent, &pt2);
			m_rect.left = pt1.x;m_rect.top = pt1.y;
			m_rect.right = pt2.x;m_rect.bottom = pt2.y;

			RECT parentrect;
			::GetWindowRect(hParent,&parentrect);
	
			int x = m_rect.left + (m_bAllowMoveX ? 
				( (parentrect.right - parentrect.left) - (m_parentrect.right - m_parentrect.left) ) : 0);
			int y = m_rect.top + (m_bAllowMoveY ? 
				( (parentrect.bottom - parentrect.top) - (m_parentrect.bottom - m_parentrect.top) ) : 0);
			int cx = (m_rect.right-m_rect.left) + (m_bAllowResizeX ? 
				( (parentrect.right - parentrect.left) - (m_parentrect.right - m_parentrect.left) ) : 0);
			int cy = (m_rect.bottom-m_rect.top) + (m_bAllowResizeY ? 
				( (parentrect.bottom - parentrect.top) - (m_parentrect.bottom - m_parentrect.top) ) : 0);

			m_parentrect = parentrect;

			::SetWindowPos(m_hCtrl, NULL, x,y, cx,cy, 0);
		}
	}
}










//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CResizableGrip::CResizableGrip()
{
	m_hParent = NULL;

	m_sizeGrip.cx = GetSystemMetrics(SM_CXVSCROLL);
	m_sizeGrip.cy = GetSystemMetrics(SM_CYHSCROLL);

	m_binitialrect = FALSE;
}

CResizableGrip::~CResizableGrip()
{
	// remember to destroy the control dynamic helpers
	long nSize = m_wndControls.GetSize();
	for (long i=0; i<nSize; i++)
		delete (CResizableControl *) m_wndControls.GetAt(i);
}

void CResizableGrip::UpdateGripPos()
{
	// size-grip goes bottom right in the client area
	// (any right-to-left adjustment should go here)

	RECT rect;
	::GetClientRect(m_hParent,&rect);

	rect.left = rect.right - m_sizeGrip.cx;
	rect.top = rect.bottom - m_sizeGrip.cy;

	// must stay below other children
	::SetWindowPos(m_wndGrip,HWND_BOTTOM, rect.left, rect.top, 0, 0,
		SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREPOSITION);

	// maximized windows cannot be resized
	
	

	if ( ::IsZoomed(m_hParent) )
	{
		::EnableWindow(m_wndGrip, FALSE);
		ShowSizeGrip(FALSE);
	}
	else
	{
		::EnableWindow(m_wndGrip, TRUE);
		ShowSizeGrip(TRUE);
	}
}

void CResizableGrip::ShowSizeGrip(BOOL bShow)
{
	::ShowWindow(m_wndGrip, bShow ? SW_SHOW : SW_HIDE);
}


HWND CResizableGrip::GetSafeHwnd()
{
	return ::IsWindow(m_wndGrip) ? m_wndGrip : NULL;
}

#define RSZ_GRIP_OBJ	_T("ResizableGrip")

BOOL CResizableGrip::InitGrip(HWND hParent)
{
	m_hParent = hParent;

	RECT rect = { 0 , 0, m_sizeGrip.cx, m_sizeGrip.cy };

	m_wndGrip = ::CreateWindowEx(0, _T("SCROLLBAR"), 
								(LPSTR)NULL, 
								WS_CHILD | WS_CLIPSIBLINGS | SBS_SIZEGRIP,
								rect.left, rect.top, 
								rect.right-rect.left,
								rect.bottom-rect.top,
								hParent,
								(HMENU)0,
								NULL,
								NULL);

	if (m_wndGrip)
	{
		// set a triangular window region
		HRGN rgnGrip, rgn;
		rgn = ::CreateRectRgn(0,0,1,1);
		rgnGrip = ::CreateRectRgnIndirect(&rect);

		for (int y=0; y<m_sizeGrip.cy; y++)
		{
			::SetRectRgn(rgn, 0, y, m_sizeGrip.cx-y, y+1);
			::CombineRgn(rgnGrip, rgnGrip, rgn, RGN_DIFF); 
		}
		::SetWindowRgn(m_wndGrip, rgnGrip, FALSE);

		// subclass control
		::SetProp(m_wndGrip, RSZ_GRIP_OBJ,
			(HANDLE)::GetWindowLong(m_wndGrip, GWL_WNDPROC));
		::SetWindowLong(m_wndGrip, GWL_WNDPROC, (LONG)GripWindowProc);

		// force dialog styles (RESIZABLE BORDER, NO FLICKERING)
		::SetWindowLong(hParent, GWL_STYLE, 
			::GetWindowLong(hParent, GWL_STYLE) | WS_THICKFRAME | WS_CLIPCHILDREN);
		

		// update pos
		UpdateGripPos();
		ShowSizeGrip();
	}

	return m_wndGrip!=NULL;
}

LRESULT CResizableGrip::GripWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	WNDPROC oldWndProc = (WNDPROC)::GetProp(hwnd, RSZ_GRIP_OBJ);

	switch (msg)
	{
	case WM_NCHITTEST:

		// choose proper cursor shape
		if (IsRTL(hwnd))
			return HTBOTTOMLEFT;
		else
			return HTBOTTOMRIGHT;

	case WM_DESTROY:
		
		// unsubclass
		::RemoveProp(hwnd, RSZ_GRIP_OBJ);
		::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)oldWndProc);

		break;
	}

	return ::CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam);
}



CResizableControl *CResizableGrip::AddDynamicControls()
{
	CResizableControl *pControl = new CResizableControl();
	if (pControl) m_wndControls.Add( pControl );
	return pControl;
}


void CResizableGrip::RemoveDynamicControls(CResizableControl *p)
{
	long nSize = m_wndControls.GetSize();
	for (long i=0; i<nSize; i++)
	{
		CResizableControl *pControl = (CResizableControl *) m_wndControls.GetAt(i);
		if (pControl && pControl==p)
		{
			m_wndControls.RemoveAt(i);
			delete pControl;
			return;
		}
	}
}

void CResizableGrip::MoveAndResize()
{
	long nSize = m_wndControls.GetSize();
	for (long i=0; i<nSize; i++)
	{
		CResizableControl *pControl = (CResizableControl *) m_wndControls.GetAt(i);
		if (pControl)
			pControl->MoveAndResize();
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
France France
Addicted to reverse engineering. At work, I am developing business intelligence software in a team of smart people (independent software vendor).

Need a fast Excel generation component? Try xlsgen.

Comments and Discussions