You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1023 lines
26 KiB
1023 lines
26 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.
|
|
// Copyright (c) 2002 OSR Open Systems Resources, Inc.
|
|
//
|
|
// DockDialogBar.cpp - implementation of the CDockDialogBar class
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "DockDialogBar.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDockDialogBar
|
|
|
|
IMPLEMENT_DYNAMIC(CDockDialogBar, CControlBar);
|
|
|
|
CDockDialogBar::CDockDialogBar() :
|
|
m_clrBtnHilight(::GetSysColor(COLOR_BTNHILIGHT)),
|
|
m_clrBtnShadow(::GetSysColor(COLOR_BTNSHADOW))
|
|
{
|
|
m_sizeMin = CSize(32, 32);
|
|
m_sizeHorz = CSize(200, 200);
|
|
m_sizeVert = CSize(200, 200);
|
|
m_sizeFloat = CSize(200, 200);
|
|
m_bTracking = FALSE;
|
|
m_bInRecalcNC = FALSE;
|
|
m_cxEdge = 6;
|
|
m_cxBorder = 3;
|
|
m_cxGripper = 15;
|
|
m_pDialog = NULL;
|
|
m_brushBkgd.CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
|
|
|
|
m_cyBorder = 3;
|
|
m_cCaptionSize = GetSystemMetrics(SM_CYSMCAPTION);
|
|
m_cMinWidth = GetSystemMetrics(SM_CXMIN);
|
|
m_cMinHeight = GetSystemMetrics(SM_CYMIN);
|
|
m_bKeepSize = TRUE;
|
|
m_bShowTitleInGripper = FALSE;
|
|
}
|
|
|
|
CDockDialogBar::~CDockDialogBar()
|
|
{
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CDockDialogBar, CControlBar)
|
|
//{{AFX_MSG_MAP(CDockDialogBar)
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_SETCURSOR()
|
|
ON_WM_WINDOWPOSCHANGING()
|
|
ON_WM_WINDOWPOSCHANGED()
|
|
ON_WM_NCPAINT()
|
|
ON_WM_NCLBUTTONDOWN()
|
|
ON_WM_NCHITTEST()
|
|
ON_WM_NCCALCSIZE()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_CAPTURECHANGED()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_WM_NCLBUTTONDBLCLK()
|
|
ON_WM_SIZE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDockDialogBar message handlers
|
|
|
|
void CDockDialogBar::OnUpdateCmdUI(class CFrameWnd *pTarget, int bDisableIfNoHndler)
|
|
{
|
|
UpdateDialogControls(pTarget, bDisableIfNoHndler);
|
|
}
|
|
|
|
BOOL CDockDialogBar::Create(CWnd *pParentWnd,
|
|
CDialog *pDialog,
|
|
CString &pTitle,
|
|
UINT nID,
|
|
DWORD dwStyle,
|
|
BOOL bShowTitleInGripper)
|
|
{
|
|
ASSERT_VALID(pParentWnd); // must have a parent
|
|
ASSERT (!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC)));
|
|
|
|
//
|
|
// save the style
|
|
//
|
|
m_dwStyle = dwStyle & CBRS_ALL;
|
|
|
|
//
|
|
// Determine whether or not to display the title
|
|
// in the gripper bar
|
|
//
|
|
m_bShowTitleInGripper = bShowTitleInGripper;
|
|
|
|
//
|
|
// Adjust the gripper width if necessary
|
|
//
|
|
if(m_bShowTitleInGripper) {
|
|
m_cxGripper = 25;
|
|
}
|
|
|
|
//
|
|
// create the base window
|
|
//
|
|
CString wndclass = AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(NULL, IDC_ARROW),
|
|
m_brushBkgd, 0);
|
|
if (!CWnd::Create(wndclass, pTitle, dwStyle, CRect(0,0,0,0),
|
|
pParentWnd, 0)) {
|
|
return FALSE;
|
|
}
|
|
|
|
m_pTitle = (LPCTSTR)pTitle;
|
|
|
|
//
|
|
// create the child dialog
|
|
//
|
|
m_pDialog = pDialog;
|
|
m_pDialog->Create(nID, this);
|
|
|
|
//
|
|
// use the dialog dimensions as default base dimensions
|
|
//
|
|
CRect rc;
|
|
|
|
m_pDialog->GetWindowRect(rc);
|
|
|
|
m_sizeHorz = m_sizeVert = m_sizeFloat = rc.Size();
|
|
|
|
m_sizeHorz.cy += m_cxEdge + m_cxBorder;
|
|
m_sizeVert.cx += m_cxEdge + m_cxBorder;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CSize CDockDialogBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
|
|
{
|
|
CRect rc;
|
|
LONG availableHeight;
|
|
LONG actualHeight;
|
|
LONG rowHeight;
|
|
LONG diff;
|
|
LONG oldDiff;
|
|
LONG adjustment;
|
|
CString str;
|
|
LONG ii;
|
|
BOOL bFound;
|
|
BOOL bIsMinimum;
|
|
CDockBar *pDockBar;
|
|
CDockDialogBar *pBar;
|
|
CPtrArray barArray;
|
|
|
|
m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP)->GetWindowRect(rc);
|
|
|
|
int nHorzDockBarWidth = bStretch ? 32767 : rc.Width() + 4;
|
|
|
|
m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_LEFT)->GetWindowRect(rc);
|
|
|
|
int nVertDockBarHeight = bStretch ? 32767 : rc.Height() + 4;
|
|
|
|
if(IsFloating()) {
|
|
return m_sizeFloat;
|
|
}
|
|
|
|
CFrameWnd *pFrame = GetParentFrame();
|
|
|
|
if(pFrame == NULL) {
|
|
if (bHorz)
|
|
return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
|
|
else
|
|
return CSize(m_sizeVert.cx, nVertDockBarHeight);
|
|
}
|
|
|
|
//
|
|
// Get the available screen height
|
|
//
|
|
pFrame->GetClientRect(rc);
|
|
|
|
ScreenToClient(rc);
|
|
|
|
//
|
|
// Client rect height minus the status bar height
|
|
//
|
|
availableHeight = rc.Height() - 18;
|
|
|
|
actualHeight = 0;
|
|
|
|
pDockBar = (CDockBar *)m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP);
|
|
|
|
if(pDockBar == NULL) {
|
|
if (bHorz)
|
|
return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
|
|
else
|
|
return CSize(m_sizeVert.cx, nVertDockBarHeight);
|
|
}
|
|
|
|
bFound = FALSE;
|
|
|
|
rowHeight = 0;
|
|
|
|
//
|
|
// Walk the top rows
|
|
//
|
|
for(ii = 0; ii < pDockBar->m_arrBars.GetSize(); ii++) {
|
|
|
|
pBar = (CDockDialogBar *)pDockBar->m_arrBars[ii];
|
|
|
|
if(pBar == NULL) {
|
|
if(!bFound) {
|
|
availableHeight -= rowHeight;
|
|
}
|
|
rowHeight = 0;
|
|
continue;
|
|
}
|
|
|
|
if(pBar->IsKindOf(RUNTIME_CLASS(CDockDialogBar))) {
|
|
if(!bFound && pBar != this) {
|
|
if (bHorz)
|
|
return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
|
|
else
|
|
return CSize(m_sizeVert.cx, nVertDockBarHeight);
|
|
}
|
|
|
|
bFound = TRUE;
|
|
|
|
barArray.Add(pBar);
|
|
|
|
//
|
|
// We position these with one border overlapping
|
|
// so subtract one part of a border width from the size
|
|
//
|
|
actualHeight += (pBar->m_sizeHorz.cy - 2);
|
|
|
|
continue;
|
|
}
|
|
|
|
pBar->GetWindowRect(rc);
|
|
|
|
rowHeight = max(rowHeight, rc.Height());
|
|
}
|
|
|
|
|
|
pDockBar = (CDockBar *)m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_BOTTOM);
|
|
|
|
if(pDockBar == NULL) {
|
|
if (bHorz)
|
|
return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
|
|
else
|
|
return CSize(m_sizeVert.cx, nVertDockBarHeight);
|
|
}
|
|
|
|
bFound = FALSE;
|
|
|
|
rowHeight = 0;
|
|
|
|
//
|
|
// Walk the bottom rows
|
|
//
|
|
for(ii = 0; ii < pDockBar->m_arrBars.GetSize(); ii++) {
|
|
pBar = (CDockDialogBar *)pDockBar->m_arrBars[ii];
|
|
|
|
if(pBar == NULL) {
|
|
if(!bFound) {
|
|
availableHeight -= rowHeight;
|
|
}
|
|
rowHeight = 0;
|
|
continue;
|
|
}
|
|
|
|
if(pBar->IsKindOf(RUNTIME_CLASS(CDockDialogBar))) {
|
|
bFound = TRUE;
|
|
|
|
barArray.Add(pBar);
|
|
|
|
//
|
|
// We position these with one border overlapping
|
|
// so subtract one part of a border width from the size
|
|
//
|
|
actualHeight += (pBar->m_sizeHorz.cy - 2);
|
|
|
|
continue;
|
|
}
|
|
|
|
pBar->GetWindowRect(rc);
|
|
|
|
rowHeight = max(rowHeight, rc.Height());
|
|
}
|
|
|
|
diff = availableHeight - actualHeight;
|
|
|
|
if(diff == 0) {
|
|
if (bHorz)
|
|
return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
|
|
else
|
|
return CSize(m_sizeVert.cx, nVertDockBarHeight);
|
|
}
|
|
|
|
adjustment = (diff > 0) ? 1 : -1;
|
|
|
|
//
|
|
// walk through our array and adjust the heights
|
|
//
|
|
while(diff != 0) {
|
|
oldDiff = diff;
|
|
for(ii = 0; ii < barArray.GetSize(); ii++) {
|
|
pBar = (CDockDialogBar *)barArray[ii];
|
|
|
|
if(pBar->m_bKeepSize) {
|
|
continue;
|
|
}
|
|
if((pBar->m_sizeHorz.cy + adjustment) >= pBar->m_sizeMin.cy) {
|
|
pBar->m_sizeHorz.cy += adjustment;
|
|
diff -= adjustment;
|
|
if(diff == 0) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(oldDiff == diff) {
|
|
bIsMinimum = TRUE;
|
|
for(ii = 0; ii < barArray.GetSize(); ii++) {
|
|
pBar = (CDockDialogBar *)barArray[ii];
|
|
|
|
if(pBar->m_bKeepSize == TRUE) {
|
|
bIsMinimum = FALSE;
|
|
}
|
|
|
|
pBar->m_bKeepSize = FALSE;
|
|
}
|
|
if(bIsMinimum) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(ii = 0; ii < barArray.GetSize(); ii++) {
|
|
pBar = (CDockDialogBar *)barArray[ii];
|
|
|
|
pBar->m_bKeepSize = FALSE;
|
|
}
|
|
|
|
if (bHorz)
|
|
return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
|
|
else
|
|
return CSize(m_sizeVert.cx, nVertDockBarHeight);
|
|
}
|
|
|
|
CSize CDockDialogBar::CalcDynamicLayout(int nLength, DWORD dwMode)
|
|
{
|
|
if (IsFloating())
|
|
{
|
|
//
|
|
// Get the frame window for this dock dialog bar
|
|
// It better not be the main window
|
|
//
|
|
CFrameWnd* pFrameWnd = GetParentFrame();
|
|
|
|
if ( pFrameWnd != AfxGetMainWnd() )
|
|
{
|
|
//
|
|
// Disable the SC_CLOSE Control for floating window
|
|
//
|
|
EnableMenuItem(::GetSystemMenu(pFrameWnd->m_hWnd, FALSE),
|
|
SC_CLOSE,
|
|
MF_BYCOMMAND | MF_GRAYED);
|
|
}
|
|
|
|
//
|
|
// Enable diagonal arrow cursor for resizing
|
|
//
|
|
GetParent()->GetParent()->ModifyStyle(0, MFS_4THICKFRAME);
|
|
}
|
|
|
|
if (dwMode & (LM_HORZDOCK | LM_VERTDOCK))
|
|
{
|
|
SetWindowPos(NULL, 0, 0, 0, 0,
|
|
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
|
|
SWP_NOACTIVATE | SWP_FRAMECHANGED);
|
|
m_pDockSite->RecalcLayout();
|
|
|
|
return CControlBar::CalcDynamicLayout(nLength,dwMode);
|
|
}
|
|
|
|
if (dwMode & LM_MRUWIDTH)
|
|
return m_sizeFloat;
|
|
|
|
if (dwMode & LM_COMMIT)
|
|
{
|
|
m_sizeFloat.cx = nLength;
|
|
return m_sizeFloat;
|
|
}
|
|
|
|
if (IsFloating())
|
|
{
|
|
RECT window_rect;
|
|
POINT cursor_pt;
|
|
|
|
GetCursorPos(&cursor_pt);
|
|
GetParent()->GetParent()->GetWindowRect(&window_rect);
|
|
|
|
switch (m_pDockContext->m_nHitTest)
|
|
{
|
|
case HTTOPLEFT:
|
|
m_sizeFloat.cx = max(window_rect.right - cursor_pt.x,
|
|
m_cMinWidth) - m_cxBorder;
|
|
m_sizeFloat.cy = max(window_rect.bottom - m_cCaptionSize -
|
|
cursor_pt.y,m_cMinHeight) - 1;
|
|
m_pDockContext->m_rectFrameDragHorz.top = min(cursor_pt.y,
|
|
window_rect.bottom - m_cCaptionSize - m_cMinHeight) -
|
|
m_cyBorder;
|
|
m_pDockContext->m_rectFrameDragHorz.left = min(cursor_pt.x,
|
|
window_rect.right - m_cMinWidth) - 1;
|
|
return m_sizeFloat;
|
|
|
|
case HTTOPRIGHT:
|
|
m_sizeFloat.cx = max(cursor_pt.x - window_rect.left,
|
|
m_cMinWidth);
|
|
m_sizeFloat.cy = max(window_rect.bottom - m_cCaptionSize -
|
|
cursor_pt.y,m_cMinHeight) - 1;
|
|
m_pDockContext->m_rectFrameDragHorz.top = min(cursor_pt.y,
|
|
window_rect.bottom - m_cCaptionSize - m_cMinHeight) -
|
|
m_cyBorder;
|
|
return m_sizeFloat;
|
|
|
|
case HTBOTTOMLEFT:
|
|
m_sizeFloat.cx = max(window_rect.right - cursor_pt.x,
|
|
m_cMinWidth) - m_cxBorder;
|
|
m_sizeFloat.cy = max(cursor_pt.y - window_rect.top -
|
|
m_cCaptionSize,m_cMinHeight);
|
|
m_pDockContext->m_rectFrameDragHorz.left = min(cursor_pt.x,
|
|
window_rect.right - m_cMinWidth) - 1;
|
|
return m_sizeFloat;
|
|
|
|
case HTBOTTOMRIGHT:
|
|
m_sizeFloat.cx = max(cursor_pt.x - window_rect.left,
|
|
m_cMinWidth);
|
|
m_sizeFloat.cy = max(cursor_pt.y - window_rect.top -
|
|
m_cCaptionSize,m_cMinHeight);
|
|
return m_sizeFloat;
|
|
}
|
|
}
|
|
|
|
if (dwMode & LM_LENGTHY)
|
|
return CSize(m_sizeFloat.cx,
|
|
m_sizeFloat.cy = max(m_sizeMin.cy, nLength));
|
|
else
|
|
return CSize(max(m_sizeMin.cx, nLength), m_sizeFloat.cy);
|
|
}
|
|
|
|
void CDockDialogBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
|
|
{
|
|
CControlBar::OnWindowPosChanging(lpwndpos);
|
|
}
|
|
|
|
void CDockDialogBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
|
|
{
|
|
CControlBar::OnWindowPosChanged(lpwndpos);
|
|
|
|
if(!::IsWindow(m_hWnd) || m_pDialog==NULL)
|
|
return;
|
|
if(!::IsWindow(m_pDialog->m_hWnd))
|
|
return;
|
|
if (m_bInRecalcNC)
|
|
{
|
|
CRect rc;
|
|
GetClientRect(rc);
|
|
m_pDialog->MoveWindow(rc);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Find on which side are we docked
|
|
//
|
|
UINT nDockBarID = GetParent()->GetDlgCtrlID();
|
|
|
|
//
|
|
// Return if dropped at same location
|
|
//
|
|
if (nDockBarID == m_nDockBarID // no docking side change
|
|
&& (lpwndpos->flags & SWP_NOSIZE) // no size change
|
|
&& ((m_dwStyle & CBRS_BORDER_ANY) != CBRS_BORDER_ANY))
|
|
return;
|
|
|
|
m_nDockBarID = nDockBarID;
|
|
|
|
//
|
|
// Force recalc the non-client area
|
|
//
|
|
m_bInRecalcNC = TRUE;
|
|
SetWindowPos(NULL, 0,0,0,0,
|
|
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
m_bInRecalcNC = FALSE;
|
|
}
|
|
|
|
BOOL CDockDialogBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
if ((nHitTest != HTSIZE) || m_bTracking)
|
|
return CControlBar::OnSetCursor(pWnd, nHitTest, message);
|
|
|
|
if (IsHorz())
|
|
SetCursor(LoadCursor(NULL, IDC_SIZENS));
|
|
else
|
|
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// Mouse Handling
|
|
//
|
|
void CDockDialogBar::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (!m_bTracking)
|
|
CControlBar::OnLButtonUp(nFlags, point);
|
|
else
|
|
{
|
|
ClientToWnd(point);
|
|
StopTracking(TRUE);
|
|
}
|
|
}
|
|
|
|
void CDockDialogBar::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (IsFloating() || !m_bTracking)
|
|
{
|
|
CControlBar::OnMouseMove(nFlags, point);
|
|
return;
|
|
}
|
|
|
|
CPoint cpt = m_rectTracker.CenterPoint();
|
|
|
|
ClientToWnd(point);
|
|
|
|
if (IsHorz())
|
|
{
|
|
if (cpt.y != point.y)
|
|
{
|
|
OnInvertTracker(m_rectTracker);
|
|
m_rectTracker.OffsetRect(0, point.y - cpt.y);
|
|
OnInvertTracker(m_rectTracker);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cpt.x != point.x)
|
|
{
|
|
OnInvertTracker(m_rectTracker);
|
|
m_rectTracker.OffsetRect(point.x - cpt.x, 0);
|
|
OnInvertTracker(m_rectTracker);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDockDialogBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
|
|
{
|
|
//
|
|
// Compute the rectangle of the mobile edge
|
|
//
|
|
GetWindowRect(m_rectBorder);
|
|
m_rectBorder = CRect(0, 0, m_rectBorder.Width(), m_rectBorder.Height());
|
|
|
|
DWORD dwBorderStyle = m_dwStyle | CBRS_BORDER_ANY;
|
|
|
|
switch(m_nDockBarID)
|
|
{
|
|
case AFX_IDW_DOCKBAR_TOP:
|
|
dwBorderStyle &= ~CBRS_BORDER_BOTTOM;
|
|
lpncsp->rgrc[0].left += m_cxGripper;
|
|
lpncsp->rgrc[0].bottom += -m_cxEdge;
|
|
lpncsp->rgrc[0].top += m_cxBorder;
|
|
lpncsp->rgrc[0].right += -m_cxBorder;
|
|
m_rectBorder.top = m_rectBorder.bottom - m_cxEdge;
|
|
break;
|
|
case AFX_IDW_DOCKBAR_BOTTOM:
|
|
dwBorderStyle &= ~CBRS_BORDER_TOP;
|
|
lpncsp->rgrc[0].left += m_cxGripper;
|
|
lpncsp->rgrc[0].top += m_cxEdge;
|
|
lpncsp->rgrc[0].bottom += -m_cxBorder;
|
|
lpncsp->rgrc[0].right += -m_cxBorder;
|
|
m_rectBorder.bottom = m_rectBorder.top + m_cxEdge;
|
|
break;
|
|
case AFX_IDW_DOCKBAR_LEFT:
|
|
dwBorderStyle &= ~CBRS_BORDER_RIGHT;
|
|
lpncsp->rgrc[0].right += -m_cxEdge;
|
|
lpncsp->rgrc[0].left += m_cxBorder;
|
|
lpncsp->rgrc[0].bottom += -m_cxBorder;
|
|
lpncsp->rgrc[0].top += m_cxGripper;
|
|
m_rectBorder.left = m_rectBorder.right - m_cxEdge;
|
|
break;
|
|
case AFX_IDW_DOCKBAR_RIGHT:
|
|
dwBorderStyle &= ~CBRS_BORDER_LEFT;
|
|
lpncsp->rgrc[0].left += m_cxEdge;
|
|
lpncsp->rgrc[0].right += -m_cxBorder;
|
|
lpncsp->rgrc[0].bottom += -m_cxBorder;
|
|
lpncsp->rgrc[0].top += m_cxGripper;
|
|
m_rectBorder.right = m_rectBorder.left + m_cxEdge;
|
|
break;
|
|
default:
|
|
m_rectBorder.SetRectEmpty();
|
|
break;
|
|
}
|
|
|
|
SetBarStyle(dwBorderStyle);
|
|
}
|
|
|
|
void CDockDialogBar::OnNcPaint()
|
|
{
|
|
EraseNonClient();
|
|
|
|
CWindowDC dc(this);
|
|
dc.Draw3dRect(m_rectBorder, GetSysColor(COLOR_BTNHIGHLIGHT),
|
|
GetSysColor(COLOR_BTNSHADOW));
|
|
|
|
DrawGripper(dc);
|
|
|
|
CRect pRect;
|
|
GetClientRect( &pRect );
|
|
InvalidateRect( &pRect, TRUE );
|
|
}
|
|
|
|
void CDockDialogBar::OnNcLButtonDown(UINT nHitTest, CPoint point)
|
|
{
|
|
if (m_bTracking) return;
|
|
|
|
if((nHitTest == HTSYSMENU) && !IsFloating())
|
|
GetDockingFrame()->ShowControlBar(this, FALSE, FALSE);
|
|
else if ((nHitTest == HTMINBUTTON) && !IsFloating())
|
|
m_pDockContext->ToggleDocking();
|
|
else if ((nHitTest == HTCAPTION) && !IsFloating() && (m_pDockBar != NULL))
|
|
{
|
|
// start the drag
|
|
ASSERT(m_pDockContext != NULL);
|
|
m_pDockContext->StartDrag(point);
|
|
}
|
|
else if ((nHitTest == HTSIZE) && !IsFloating()) {
|
|
m_bKeepSize = TRUE;
|
|
|
|
StartTracking();
|
|
} else {
|
|
CControlBar::OnNcLButtonDown(nHitTest, point);
|
|
}
|
|
}
|
|
|
|
UINT CDockDialogBar::OnNcHitTest(CPoint point)
|
|
{
|
|
if (IsFloating())
|
|
return CControlBar::OnNcHitTest(point);
|
|
|
|
CRect rc;
|
|
GetWindowRect(rc);
|
|
point.Offset(-rc.left, -rc.top);
|
|
if(m_rectClose.PtInRect(point))
|
|
return HTSYSMENU;
|
|
else if (m_rectUndock.PtInRect(point))
|
|
return HTMINBUTTON;
|
|
else if (m_rectGripper.PtInRect(point))
|
|
return HTCAPTION;
|
|
else if (m_rectBorder.PtInRect(point))
|
|
return HTSIZE;
|
|
else
|
|
return CControlBar::OnNcHitTest(point);
|
|
}
|
|
|
|
void CDockDialogBar::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
//
|
|
// only start dragging if clicked in "void" space
|
|
//
|
|
if (m_pDockBar != NULL)
|
|
{
|
|
//
|
|
// start the drag
|
|
//
|
|
ASSERT(m_pDockContext != NULL);
|
|
ClientToScreen(&point);
|
|
m_pDockContext->StartDrag(point);
|
|
}
|
|
else
|
|
{
|
|
CWnd::OnLButtonDown(nFlags, point);
|
|
}
|
|
}
|
|
|
|
void CDockDialogBar::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
//
|
|
// only toggle docking if clicked in "void" space
|
|
//
|
|
if (m_pDockBar != NULL)
|
|
{
|
|
//
|
|
// toggle docking
|
|
//
|
|
ASSERT(m_pDockContext != NULL);
|
|
m_pDockContext->ToggleDocking();
|
|
}
|
|
else
|
|
{
|
|
CWnd::OnLButtonDblClk(nFlags, point);
|
|
}
|
|
}
|
|
|
|
void CDockDialogBar::StartTracking()
|
|
{
|
|
SetCapture();
|
|
|
|
//
|
|
// make sure no updates are pending
|
|
//
|
|
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
|
|
m_pDockSite->LockWindowUpdate();
|
|
|
|
m_ptOld = m_rectBorder.CenterPoint();
|
|
m_bTracking = TRUE;
|
|
|
|
m_rectTracker = m_rectBorder;
|
|
if (!IsHorz()) m_rectTracker.bottom -= 4;
|
|
|
|
OnInvertTracker(m_rectTracker);
|
|
}
|
|
|
|
void CDockDialogBar::OnCaptureChanged(CWnd *pWnd)
|
|
{
|
|
if (m_bTracking && pWnd != this)
|
|
//
|
|
// cancel tracking
|
|
//
|
|
StopTracking(FALSE);
|
|
|
|
CControlBar::OnCaptureChanged(pWnd);
|
|
}
|
|
|
|
void CDockDialogBar::StopTracking(BOOL bAccept)
|
|
{
|
|
CDockDialogBar *pBar;
|
|
CDockBar *pDockBar;
|
|
LONG beforeIndex;
|
|
LONG afterIndex;
|
|
LONG ii;
|
|
BOOL bFound = FALSE;
|
|
|
|
OnInvertTracker(m_rectTracker);
|
|
m_pDockSite->UnlockWindowUpdate();
|
|
m_bTracking = FALSE;
|
|
ReleaseCapture();
|
|
|
|
if (!bAccept) return;
|
|
|
|
int maxsize, minsize, newsize;
|
|
CRect rcc;
|
|
m_pDockSite->GetWindowRect(rcc);
|
|
|
|
newsize = IsHorz() ? m_sizeHorz.cy : m_sizeVert.cx;
|
|
maxsize = newsize + (IsHorz() ? rcc.Height() : rcc.Width());
|
|
minsize = IsHorz() ? m_sizeMin.cy : m_sizeMin.cx;
|
|
|
|
CPoint point = m_rectTracker.CenterPoint();
|
|
switch (m_nDockBarID)
|
|
{
|
|
case AFX_IDW_DOCKBAR_TOP:
|
|
newsize += point.y - m_ptOld.y; break;
|
|
case AFX_IDW_DOCKBAR_BOTTOM:
|
|
newsize += -point.y + m_ptOld.y; break;
|
|
case AFX_IDW_DOCKBAR_LEFT:
|
|
newsize += point.x - m_ptOld.x; break;
|
|
case AFX_IDW_DOCKBAR_RIGHT:
|
|
newsize += -point.x + m_ptOld.x; break;
|
|
}
|
|
|
|
pDockBar = (CDockBar *)m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP);
|
|
|
|
//
|
|
// Mark all bars to keep their size
|
|
//
|
|
for(ii = 0; ii < pDockBar->m_arrBars.GetSize(); ii++) {
|
|
|
|
pBar = (CDockDialogBar *)pDockBar->m_arrBars[ii];
|
|
|
|
if(pBar == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if(pBar->IsKindOf(RUNTIME_CLASS(CDockDialogBar))) {
|
|
//
|
|
// Mark all bars to keep their size for now
|
|
//
|
|
pBar->m_bKeepSize = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Have all windows keep there size except those directly next
|
|
// to the window changing size if possible. Normally only the
|
|
// window below, or after, the window changing size will need
|
|
// to change size as well, unless the user attempted to resize
|
|
// the window to smaller than its minimum. Then both the window
|
|
// above and below will need to change size.
|
|
//
|
|
for(ii = 0; ii < pDockBar->m_arrBars.GetSize(); ii++) {
|
|
|
|
pBar = (CDockDialogBar *)pDockBar->m_arrBars[ii];
|
|
|
|
if(pBar == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if(pBar->IsKindOf(RUNTIME_CLASS(CDockDialogBar))) {
|
|
//
|
|
// Mark all bars to keep their size for now
|
|
//
|
|
pBar->m_bKeepSize = TRUE;
|
|
|
|
if(pBar == this) {
|
|
bFound = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if(bFound) {
|
|
afterIndex = ii;
|
|
break;
|
|
}
|
|
|
|
if(!bFound) {
|
|
beforeIndex = ii;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// The window below, or after the one being modified will
|
|
// alway need to change size
|
|
//
|
|
pBar = (CDockDialogBar *)pDockBar->m_arrBars[afterIndex];
|
|
|
|
pBar->m_bKeepSize = FALSE;
|
|
|
|
//
|
|
// If the modified window is being shrunk past its minimum
|
|
// then the window above, or before this one needs to change
|
|
// as well
|
|
//
|
|
if(newsize < minsize) {
|
|
pBar = (CDockDialogBar *)pDockBar->m_arrBars[beforeIndex];
|
|
|
|
pBar->m_bKeepSize = FALSE;
|
|
}
|
|
|
|
newsize = max(minsize, min(maxsize, newsize));
|
|
|
|
if (IsHorz())
|
|
m_sizeHorz.cy = newsize;
|
|
else
|
|
m_sizeVert.cx = newsize;
|
|
|
|
m_pDockSite->RecalcLayout();
|
|
}
|
|
|
|
void CDockDialogBar::OnInvertTracker(const CRect& rect)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(!rect.IsRectEmpty());
|
|
ASSERT(m_bTracking);
|
|
|
|
CRect rct = rect, rcc, rcf;
|
|
GetWindowRect(rcc);
|
|
m_pDockSite->GetWindowRect(rcf);
|
|
|
|
rct.OffsetRect(rcc.left - rcf.left, rcc.top - rcf.top);
|
|
rct.DeflateRect(1, 1);
|
|
|
|
CDC *pDC = m_pDockSite->GetDCEx(NULL,
|
|
DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
|
|
|
|
CBrush* pBrush = CDC::GetHalftoneBrush();
|
|
HBRUSH hOldBrush = NULL;
|
|
if (pBrush != NULL)
|
|
hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);
|
|
|
|
pDC->PatBlt(rct.left, rct.top, rct.Width(), rct.Height(), PATINVERT);
|
|
|
|
if (hOldBrush != NULL)
|
|
SelectObject(pDC->m_hDC, hOldBrush);
|
|
|
|
m_pDockSite->ReleaseDC(pDC);
|
|
}
|
|
|
|
BOOL CDockDialogBar::IsHorz() const
|
|
{
|
|
return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
|
|
m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
|
|
}
|
|
|
|
CPoint& CDockDialogBar::ClientToWnd(CPoint& point)
|
|
{
|
|
if (m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM)
|
|
point.y += m_cxEdge;
|
|
else if (m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT)
|
|
point.x += m_cxEdge;
|
|
|
|
return point;
|
|
}
|
|
|
|
void CDockDialogBar::DrawGripper(CDC & dc)
|
|
{
|
|
CString groupNumber;
|
|
|
|
//
|
|
// no gripper if floating
|
|
//
|
|
if( m_dwStyle & CBRS_FLOATING ) {
|
|
return;
|
|
}
|
|
|
|
m_pDockSite->RecalcLayout();
|
|
CRect gripper;
|
|
GetWindowRect( gripper );
|
|
ScreenToClient( gripper );
|
|
gripper.OffsetRect( -gripper.left, -gripper.top );
|
|
|
|
if( m_dwStyle & CBRS_ORIENT_HORZ ) {
|
|
|
|
//
|
|
// gripper at left
|
|
//
|
|
m_rectGripper.top = gripper.top;
|
|
m_rectGripper.bottom = gripper.bottom;
|
|
m_rectGripper.left = gripper.left;
|
|
|
|
m_rectGripper.right = gripper.left + 15;
|
|
|
|
gripper.top += 10;
|
|
gripper.bottom -= 10;
|
|
gripper.left += 5;
|
|
gripper.right = gripper.left + 3;
|
|
|
|
//
|
|
// Draw first bar
|
|
//
|
|
dc.Draw3dRect(gripper, m_clrBtnHilight, m_clrBtnShadow);
|
|
|
|
gripper.OffsetRect(4, 0);
|
|
|
|
//
|
|
// Draw second bar
|
|
//
|
|
dc.Draw3dRect(gripper, m_clrBtnHilight, m_clrBtnShadow);
|
|
|
|
//
|
|
// Display title if requested
|
|
//
|
|
if(m_bShowTitleInGripper) {
|
|
gripper.OffsetRect(8, 0);
|
|
|
|
gripper.DeflateRect(-4, 0);
|
|
|
|
dc.SelectStockObject(SYSTEM_FONT);
|
|
dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
|
|
dc.SetTextColor(GetSysColor(COLOR_3DSHADOW));
|
|
|
|
//
|
|
// Gripper title format -- ID #
|
|
//
|
|
dc.DrawText('I', gripper, DT_CENTER);
|
|
gripper.OffsetRect(0, 8);
|
|
gripper.DeflateRect(0, 8);
|
|
|
|
dc.DrawText('D', gripper, DT_CENTER);
|
|
gripper.OffsetRect(0, 8);
|
|
gripper.DeflateRect(0, 8);
|
|
|
|
dc.DrawText(' ', gripper, DT_CENTER);
|
|
gripper.OffsetRect(0, 4);
|
|
gripper.DeflateRect(0, 4);
|
|
|
|
groupNumber = m_pTitle.Right(m_pTitle.GetLength() - m_pTitle.ReverseFind(' ') - 1);
|
|
|
|
for(int ii = 0; ii < groupNumber.GetLength(); ii++) {
|
|
dc.DrawText(groupNumber[ii], gripper, DT_CENTER);
|
|
gripper.OffsetRect(0, 8);
|
|
gripper.DeflateRect(0, 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
else {
|
|
|
|
//
|
|
// gripper at top
|
|
//
|
|
m_rectGripper.top = gripper.top;
|
|
m_rectGripper.bottom = gripper.top + 20;
|
|
m_rectGripper.left = gripper.left;
|
|
m_rectGripper.right = gripper.right - 10;
|
|
|
|
gripper.right -= 38;
|
|
gripper.left += 5;
|
|
gripper.top += 10;
|
|
gripper.bottom = gripper.top + 3;
|
|
dc.Draw3dRect( gripper, RGB(0, 255, 0), RGB(0, 255, 255));
|
|
|
|
gripper.OffsetRect(0, 4);
|
|
dc.Draw3dRect( gripper, RGB(255, 255, 0), RGB(255, 0, 0));
|
|
}
|
|
|
|
}
|
|
|
|
void CDockDialogBar::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
|
|
{
|
|
if ((m_pDockBar != NULL) && (nHitTest == HTCAPTION))
|
|
{
|
|
//
|
|
// toggle docking
|
|
//
|
|
ASSERT(m_pDockContext != NULL);
|
|
m_pDockContext->ToggleDocking();
|
|
}
|
|
else
|
|
{
|
|
CWnd::OnNcLButtonDblClk(nHitTest, point);
|
|
}
|
|
}
|