A DevStudio like CControlBar
Posted
by Alger Pike
on August 7th, 1998

// Add our caption ModifyStyle(0, WS_CAPTION);At this point if you derive a CGripDialogBar object you will see that this one statement of code, does a lot for us. It creates a dialog bar that has a default windows caption. At this point the real work begins, as we want to override the ugly windows deactivated caption bar and add our own with grip bars that look like DevStudios. We also, will give it a color gradient so we will be one up on DevStudio. In order to draw your own caption bar, you need to provide your own support for several of the WM_NC??? messages. The painting itself is done in WM_NCPAINT. Add this point, add a message handler for this function:
//{{AFX_MSG(CInitDialogBar)
afx_msg void OnNcPaint();
//{{AFX_MESSAGE
BEGIN_MESSAGE_MAP(CGripDialogBar, CInitDialogBar)
//{{AFX_MSG_MAP(CInitDialogBar)
ON_WM_NCPAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CGripDialogBar::OnNcPaint()
{
// Let MFC draw the frame for us
// We could do it put it's a pain
// since we do not change the default
// look
Default();
// Here we will paint our own caption
// bar for our dock window
CWindowDC dc(this);
CBrush Brush;
Brush.Attach((HBRUSH) GetStockObject(LTGRAY_BRUSH));
CRect rc;
GetWindowRect(rc);
// Rect of caption and X/Y Frames
CRect rc2(0,0, rc.Width(),
GetSystemMetrics(SM_CYCAPTION)
+ GetSystemMetrics(SM_CYFRAME));
//Get Caption Rect
CRect capRect;
capRect.left = rc2.left + GetSystemMetrics(SM_CXBORDER);
capRect.top = GetSystemMetrics(SM_CYFRAME);
capRect.right = rc2.right - GetSystemMetrics(SM_CXBORDER);
capRect.bottom = GetSystemMetrics( SM_CYSIZE );
dc.FillRect(rc2, &Brush);
float gradient = 0;
float startcolor = 100;
float endcolor = 220;
// calculate the slope for color gradient
gradient = (endcolor - startcolor) / rc.Width();
// Draw Color gradient
for(int i = 0; i < rc.Width(); i++)
{
int r, g, b;
float fr, fg, fb;
CPen* oldPen;
// Higer precision use floats for calcs
// Leads to smoother gradient
fr = gradient * (float) i + startcolor;
fg = gradient * (float) i + startcolor;
fb = gradient * (float) i + startcolor;
r = (int) fr;
g = (int) fg;
b = (int) fb;
CPen pen(PS_SOLID, 1, RGB(r,g,b));
dc.MoveTo(i,0);
oldPen = dc.SelectObject(&pen);
dc.LineTo(i,rc2.bottom);
dc.SelectObject(oldPen);
}
// Draw the docking grippers
CRect rect(5,7,(5+rc.Width()) - 30, 7+3);
dc.Draw3dRect(rect,
RGB(255,255,255),
RGB(128,128,128));
CRect rect2(5,11,(5+rc.Width()) - 30, 11+3);
dc.Draw3dRect(rect2,
RGB(255,255,255),
RGB(128,128,128));
// Adjust capRect to receive
// the close button
capRect.left = capRect.right - 20;
capRect.right -= 5;
// Put the close button on the caption
dc.DrawFrameControl(capRect,
DFC_CAPTION,
DFCS_CAPTIONCLOSE);
}
Now, we have a control that has a caption that looks the way we want it to look.
The next step is to provide the docking control to the caption. If you have derived
an object at this point; Test it! Look how clicking on the caption does not cause the
caption to start the dock drag nor does double clicking dock / undock the control. By
overriding two more of WM_NC?? messages we can provide these functions quite easily.
The messages we need to override are WM_NCLBUTTONDOWN, and WM_NC_LBUTTONDBLCLK:
void CGripDialogBar::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
ASSERT(m_pDockContext != NULL);
switch(nHitTest)
{
case HTCAPTION:
{
m_pDockContext->StartDrag(point);
}
break;
default:
Default();
break;
}
}
void CGripDialogBar::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
{
ASSERT(m_pDockContext != NULL);
// start the drag
m_pDockContext->ToggleDocking();
}
Now if you derive an object and use it you will see that the docking support now works but has a
major flaw. When the window is in the floating state the caption does not disappear. We get
something that looks like this:

protected: void RecalcLayout();We will call this function before we do our painting. If the window is in a floating state then we move the control with respect to its parent up the height of the caption bar. The hides the control bars caption underneath the caption of the floating window. Implement the RecalcLayout function like this:
void CGripDialogBar::RecalcLayout()
{
// If we are floating we do not want
// our new caption to be visible,
// so we move our window up so our
// caption is underneath the CMiniFrameWnd
// caption
if(IsFloating())
{
CRect rect;
GetWindowRect(rect);
SetWindowPos(NULL,
0,
-(GetSystemMetrics(SM_CYCAPTION)
+ GetSystemMetrics(SM_CYFRAME)),
rect.Width(),
rect.Height(),
NULL);
}
}
Then override your OnPaint() function to call RecalcLayout() before it does its painting:
void CGripDialogBar::OnPaint()
{
// Notice here we break the do not call
// the base class OnPaint Rule. This is
// because we do not set up our own DC
// here so calling the base is OK and also
// required, otherwise we need to redo
// what the base already does for us
RecalcLayout();
CDialogBar::OnPaint();
}
We have now fixed the floating caption bug, but we have now introduced a new bug. We have lost double
click support. Look at how the drag frame is now drawn and I think you will see why:

class CExDockContext : public CDockContext
{
public:
CExDockContext(CControlBar* pBar);
virtual ~CExDockContext();
// Drag Operations
virtual void StartDrag(CPoint pt);
protected:
virtual void AdjustWindowForFloat(CRect& rect);
};
We will now override the start drag function. Most of it will be exactly the same as the base class.
I will put in comments where we call our AdjustWindowForFloat(). It needs to be called a total of
three times.
void CExDockContext::StartDrag(CPoint pt)
{
ASSERT_VALID(m_pBar);
m_bDragging = TRUE;
InitLoop();
if (m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
{
// get true bar size (including borders)
CRect rect;
m_pBar->GetWindowRect(rect);
// This is our added funtionality
// This overridable allows you
// to adjust the window rect so that
// you can hide controls like a caption
// bar from view
//NewCode--> AdjustWindowForFloat(rect);
m_ptLast = pt;
CSize sizeHorz = m_pBar->CalcDynamicLayout(0,
LM_HORZ | LM_HORZDOCK);
CSize sizeVert = m_pBar->CalcDynamicLayout(0,
LM_VERTDOCK);
CSize sizeFloat = m_pBar->CalcDynamicLayout(0,
LM_HORZ | LM_MRUWIDTH);
m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
// calculate frame dragging rectangle
m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat);
m_rectFrameDragVert = CRect(rect.TopLeft(), sizeFloat);
#ifdef _MAC
CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz,
WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert,
WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX);
#else
CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
#endif
m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
}
else if (m_pBar->m_dwStyle & CBRS_SIZE_FIXED)
{
// get true bar size (including borders)
CRect rect;
m_pBar->GetWindowRect(rect);
// This is our added funtionality
// This overridable allows you
// to adjust the window rect so that
// you can hide controls like a caption
// bar from view
//NewCode--> AdjustWindowForFloat(rect);
m_ptLast = pt;
CSize sizeHorz = m_pBar->CalcDynamicLayout(-1,
LM_HORZ | LM_HORZDOCK);
CSize sizeVert = m_pBar->CalcDynamicLayout(-1, LM_VERTDOCK);
// calculate frame dragging rectangle
m_rectFrameDragHorz = m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
m_rectFrameDragVert = m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
}
else
{
// get true bar size (including borders)
CRect rect;
m_pBar->GetWindowRect(rect);
// This is our added funtionality
// This overridable allows you
// to adjust the window rect so that
// you can hide controls like a caption
// bar from view
//NewCode--> AdjustWindowForFloat(rect);
m_ptLast = pt;
BOOL bHorz = HORZF(m_dwStyle);
DWORD dwMode = !bHorz ? (LM_HORZ |
LM_HORZDOCK):LM_VERTDOCK;
CSize size = m_pBar->CalcDynamicLayout(-1, dwMode);
// calculate inverted dragging rect
if (bHorz)
{
m_rectDragHorz = rect;
m_rectDragVert = CRect(CPoint(pt.x - rect.Height()/2, rect.top), size);
}
else // vertical orientation
{
m_rectDragVert = rect;
m_rectDragHorz = CRect(CPoint(rect.left, pt.y - rect.Width()/2), size);
}
// calculate frame dragging rectangle
m_rectFrameDragHorz = m_rectDragHorz;
m_rectFrameDragVert = m_rectDragVert;
CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
}
// adjust rectangles so that point is inside
AdjustRectangle(m_rectDragHorz, pt);
AdjustRectangle(m_rectDragVert, pt);
AdjustRectangle(m_rectFrameDragHorz, pt);
AdjustRectangle(m_rectFrameDragVert, pt);
// initialize tracking state and enter tracking loop
m_dwOverDockStyle = CanDock();
Move(pt); // call it here to handle special keys
Track();
}
With that complete we simply call our new AdjustWindowForFloat() to make any modifications to the
rectangle before the drag frame is drawn. Remember, that we moved our control up to hide the caption
bar so we would not see it. So in our AdjustWindowForFloat() we will undo the coordinate move and
pass the unmodified coordinates:
void CExDockContext::AdjustWindowForFloat(CRect& rect)
{
// Overridable to adjust floating frame
// size for added controls you don not
// want to see in the floating state
// Default behavior is to move window
// up enough to hide the caption bar
if(m_pBar->IsFloating())
rect.top += (GetSystemMetrics(SM_CYCAPTION)
+ GetSystemMetrics(SM_CYFRAME));
}
There is one last step. We now need to tell our CGripDialogBar to use our overridden docking support
rather than the default. This is relatively easy to do. . The m_pDockContext object is a pointer
which is setup in the call to EnableDocking(). If a pointer already exists the framework uses that
one. This means the in our OnInitDialogBar(), which gets called before EnableDocking() in OnCreate(),
we can allocate the m_pDockContext and the framework now uses our overridden docking support.
The completed OnInitDialogBar(). The new InInitDialogBar() function now looks like this:
BOOL CGripDialogBar::OnInitDialogBar()
{
// Add our caption
ModifyStyle(0, WS_CAPTION);
// Setup up the overidded context for Docking
// We will use this context to provide our own
// docking functionality.
// By doing this ourselves now instead of during
// Enable docking we are able to replace the
// original member variable with our new class
// since all our changes occur in virtual
// functions.
if (m_pDockContext == NULL)
m_pDockContext = new CExDockContext(this);
ASSERT(m_pDockContext);
// Call Base Class
CInitDialogBar::OnInitDialogBar();
return TRUE;
}
The m_pDockContext object is deleted by the base class destructor you do NOT have to delete it yourself.
That pretty much covers it. You should now have a control based on a CDialogBar that has a gripper
caption at the top like DevStudios. There is still some missing functionality like the close button.
If you are interested in a more complete version, including close button support, flicker free drawing,
and other enhancements, along with a sample of its use stop by http://avenger.mri.psu.edu/ntpage.html.
Look under the column to the right under Stupid MFC Tricks. Anyway the complete source is presented
for the control that the article describes:
// GripDialogBar.h: interface for the CGripDialogBar class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GRIPDIALOGBAR_H__E3F8F9A2_CBC9_11D1_9783_726AA5000000__INCLUDED_) #define AFX_GRIPDIALOGBAR_H__E3F8F9A2_CBC9_11D1_9783_726AA5000000__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include#include "InitDialogBar.h" class CExDockContext; class CGripDialogBar : public CInitDialogBar { DECLARE_DYNAMIC(CGripDialogBar) // Construction / Destruction public: CGripDialogBar(); virtual ~CGripDialogBar(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CInitDialogBar) //}}AFX_VIRTUAL // Implementation public: protected: virtual BOOL OnInitDialogBar(); // Generated message map functions protected: void RecalcLayout(); //{{AFX_MSG(CInitDialogBar) afx_msg void OnNcPaint(); afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point); afx_msg void OnPaint(); afx_msg void OnNcLButtonDblClk(UINT nHitTest, CPoint point); afx_msg BOOL OnNcActivate(BOOL bActive); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; // Our new dock Control that overrides // standard docking. class CExDockContext : public CDockContext { public: CExDockContext(CControlBar* pBar); virtual ~CExDockContext(); public: // Drag Operations virtual void StartDrag(CPoint pt); protected: virtual void AdjustWindowForFloat(CRect& rect); }; ////////////////////////////////////////////// #endif // !defined(AFX_GRIPDIALOGBAR_H__E3F8F9A2_CBC9_11D1_9783_726AA5000000__INCLUDED_) ////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // GripDialogBar.cpp: implementation of the CGripDialogBar class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include #include <..\src\afximpl.h> #include "GripDialogBar.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNAMIC(CGripDialogBar, CInitDialogBar) BEGIN_MESSAGE_MAP(CGripDialogBar, CInitDialogBar) //{{AFX_MSG_MAP(CInitDialogBar) ON_WM_NCPAINT() ON_WM_NCLBUTTONDOWN() ON_WM_PAINT() ON_WM_NCLBUTTONDBLCLK() ON_WM_NCACTIVATE() //}}AFX_MSG_MAP END_MESSAGE_MAP() CGripDialogBar::CGripDialogBar() { } CGripDialogBar::~CGripDialogBar() { } BOOL CGripDialogBar::OnInitDialogBar() { // Add our caption ModifyStyle(0, WS_CAPTION); // Setup up the overidded context for Docking // We will use this context to provide our own // docking functionality. // By doing this ourselves now instead of during // Enable docking we are able to replace the // original member variable with our new class // since all our changes occur in virtual // functions. if (m_pDockContext == NULL) m_pDockContext = new CExDockContext(this); ASSERT(m_pDockContext); // Call Base Class CInitDialogBar::OnInitDialogBar(); return TRUE; } void CGripDialogBar::OnNcPaint() { // Let MFC draw the frame for us // We could do it put it's a pain // since we do not change the default // look Default(); // Here we will paint our own caption // bar for our dock window CWindowDC dc(this); CBrush Brush; Brush.Attach((HBRUSH) GetStockObject(LTGRAY_BRUSH)); CRect rc; GetWindowRect(rc); // Rect of caption and X/Y Frames CRect rc2(0,0, rc.Width(), GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME)); //Get Caption Rect CRect capRect; capRect.left = rc2.left + GetSystemMetrics(SM_CXBORDER); capRect.top = GetSystemMetrics(SM_CYFRAME); capRect.right = rc2.right - GetSystemMetrics(SM_CXBORDER); capRect.bottom = GetSystemMetrics( SM_CYSIZE ); dc.FillRect(rc2, &Brush); float gradient = 0; float startcolor = 100; float endcolor = 220; // calculate the slope for color gradient gradient = (endcolor - startcolor) / rc.Width(); // Draw Color gradient for(int i = 0; i < rc.Width(); i++) { int r, g, b; float fr, fg, fb; CPen* oldPen; // Higer precision use floats for calcs // Leads to smoother gradient fr = gradient * (float) i + startcolor; fg = gradient * (float) i + startcolor; fb = gradient * (float) i + startcolor; r = (int) fr; g = (int) fg; b = (int) fb; CPen pen(PS_SOLID, 1, RGB(r,g,b)); dc.MoveTo(i,0); oldPen = dc.SelectObject(&pen); dc.LineTo(i,rc2.bottom); dc.SelectObject(oldPen); } // Draw the docking grippers CRect rect(5,7,(5+rc.Width()) - 30, 7+3); dc.Draw3dRect(rect, RGB(255,255,255), RGB(128,128,128)); CRect rect2(5,11,(5+rc.Width()) - 30, 11+3); dc.Draw3dRect(rect2, RGB(255,255,255), RGB(128,128,128)); // Adjust capRect to receive // the close button capRect.left = capRect.right - 20; capRect.right -= 5; // Put the close button on the caption dc.DrawFrameControl(capRect, DFC_CAPTION, DFCS_CAPTIONCLOSE); } void CGripDialogBar::OnNcLButtonDown(UINT nHitTest, CPoint point) { switch(nHitTest) { case HTCAPTION: { m_pDockContext->StartDrag(point); } break; default: Default(); break; } } void CGripDialogBar::OnNcLButtonDblClk(UINT nHitTest, CPoint point) { // start the drag ASSERT(m_pDockContext != NULL); m_pDockContext->ToggleDocking(); } BOOL CGripDialogBar::OnNcActivate(BOOL bActive) { // Whether active or inactive // we want the same caption OnNcPaint(); return TRUE; } void CGripDialogBar::OnPaint() { // Notice here we break the do not call // the base class OnPaint Rule. This is // because we do not set up our own DC // here so calling the base is OK ans also // required otherwise we need to redo // what the base already does for us RecalcLayout(); CDialogBar::OnPaint(); } void CGripDialogBar::RecalcLayout() { // If we are floating we do not want // our new caption to be visible, // so we move our window up so our // caption is underneath the CMiniFrameWnd // caption if(IsFloating()) { CRect rect; GetWindowRect(rect); SetWindowPos(NULL, 0, -(GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME)), rect.Width(), rect.Height(), NULL); } else { // Seems to help avoid a painting bug SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } } /////////////////////////////////////////////////////////////////// // Class CExDocContext // // Class provides new behaviour for drawing the // track frame when floating // Rem out the code inside AdjustWindowForFloat() // to see original behaviour /////////////////////////////////////////////////////////////////// // Gain Access to MFC private DATA // Could change without warning #undef AFX_DATA #define AFX_DATA AFX_CORE_DATA extern AFX_DATA AUX_DATA afxData; // Macros from orginal DockCont.cpp #define HORZF(dw) (dw & CBRS_ORIENT_HORZ) #define VERTF(dw) (dw & CBRS_ORIENT_VERT) // Function from original DockCont.cpp static void AdjustRectangle(CRect& rect, CPoint pt) { int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) : (pt.x > rect.right) ? (pt.x - rect.right) : 0; int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) : (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0; rect.OffsetRect(nXOffset, nYOffset); } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CExDockContext::CExDockContext(CControlBar* pBar) : CDockContext(pBar) { // Default constructor passes control object // to base class } CExDockContext::~CExDockContext() { } void CExDockContext::StartDrag(CPoint pt) { ASSERT_VALID(m_pBar); m_bDragging = TRUE; InitLoop(); if (m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) { // get true bar size (including borders) CRect rect; m_pBar->GetWindowRect(rect); // This is our added funtionality // This overridable allows you // to adjust the window rect so that // you can hide controls like a caption // bar from view AdjustWindowForFloat(rect); m_ptLast = pt; CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK); CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK); CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH); m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz); m_rectDragVert = CRect(rect.TopLeft(), sizeVert); // calculate frame dragging rectangle m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat); m_rectFrameDragVert = CRect(rect.TopLeft(), sizeFloat); #ifdef _MAC CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz, WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX); CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert, WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX); #else CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); #endif m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); } else if (m_pBar->m_dwStyle & CBRS_SIZE_FIXED) { // get true bar size (including borders) CRect rect; m_pBar->GetWindowRect(rect); // This is our added funtionality // This overridable allows you // to adjust the window rect so that // you can hide controls like a caption // bar from view AdjustWindowForFloat(rect); m_ptLast = pt; CSize sizeHorz = m_pBar->CalcDynamicLayout(-1, LM_HORZ | LM_HORZDOCK); CSize sizeVert = m_pBar->CalcDynamicLayout(-1, LM_VERTDOCK); // calculate frame dragging rectangle m_rectFrameDragHorz = m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz); m_rectFrameDragVert = m_rectDragVert = CRect(rect.TopLeft(), sizeVert); CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); } else { // get true bar size (including borders) CRect rect; m_pBar->GetWindowRect(rect); // This is our added funtionality // This overridable allows you // to adjust the window rect so that // you can hide controls like a caption // bar from view AdjustWindowForFloat(rect); m_ptLast = pt; BOOL bHorz = HORZF(m_dwStyle); DWORD dwMode = !bHorz ? (LM_HORZ | LM_HORZDOCK) : LM_VERTDOCK; CSize size = m_pBar->CalcDynamicLayout(-1, dwMode); // calculate inverted dragging rect if (bHorz) { m_rectDragHorz = rect; m_rectDragVert = CRect(CPoint(pt.x - rect.Height()/2, rect.top), size); } else // vertical orientation { m_rectDragVert = rect; m_rectDragHorz = CRect(CPoint(rect.left, pt.y - rect.Width()/2), size); } // calculate frame dragging rectangle m_rectFrameDragHorz = m_rectDragHorz; m_rectFrameDragVert = m_rectDragVert; CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); } // adjust rectangles so that point is inside AdjustRectangle(m_rectDragHorz, pt); AdjustRectangle(m_rectDragVert, pt); AdjustRectangle(m_rectFrameDragHorz, pt); AdjustRectangle(m_rectFrameDragVert, pt); // initialize tracking state and enter tracking loop m_dwOverDockStyle = CanDock(); Move(pt); // call it here to handle special keys Track(); } void CExDockContext::AdjustWindowForFloat(CRect& rect) { // Overridable to adjust floating frame // size for added controls you don not // want to see in the flaoting state // Default behaviour is to move window // up enough to hide the caption bar if(m_pBar->IsFloating()) rect.top += (GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME)); }
Last updated: 12 May 1998

Comments
demo please??
Posted by William Heitler on 11/15/2004 04:16amI too would like a demonstration project if possible. I have built a project from your code on the web page, but the dialog bar doesn't really like like the image you display (no default caption when docked, weird shape misalign when floating). Rather than spending a long time trying to figure out what I have done wrong, it would be easier if there was a working demo to start from. All the best.
ReplyHow to associate a toolbar with Dialog window ?
Posted by Legacy on 07/08/2003 12:00amOriginally posted by: pt
ReplyHi,
Is there any way i can associate a CToolBar control to the Dialog window just like a frame window ?
I tried but it throws exception stating it is not cframe window.
http://www.codejock.com
Posted by Legacy on 06/08/2003 12:00amOriginally posted by: The Best GUI Tools - VS.NET and Office XP/2003 Look!
http://www.codejock.com
Reply
Hey...
Posted by Legacy on 08/24/2002 12:00amOriginally posted by: hubba
ReplyFrame not resizing
Posted by Legacy on 07/25/2002 12:00amOriginally posted by: Dave
Hi,
ReplyPlease share your insight regarding the problem i am facing.
When i dock or float my CDialogbar, I need my frame to resize automatically. I tried recalclayout, but its not working. Please help.
Not taking CDockContext class
Posted by Legacy on 05/06/2002 12:00amOriginally posted by: Vikas
Sir/Madam
I tried to make use of your code to implement docking window in my project. But it is not recognizing CDockContext class. Please help me out.
Thanx.
ReplyDocking tool bars with grip bars
Posted by Legacy on 03/26/1999 12:00amOriginally posted by: dharry
I was trying the updated docking DialogBar, but it does not work for
Replyvc4 version because the CDockContext object class does not exist is there
something that can be done about this