?? sizecbar.cpp
字號:
/////////////////////////////////////////////////////////////////////////
// Copyright (C) 1998 by Cristi Posea
// All rights reserved
//
// Distribute freely, except: don't remove my name from the source or
// documentation (don't take credit for my work), mark your changes
// (don't get me blamed for your possible bugs), don't alter or remove
// this notice.
// No warrantee of any kind, express or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.
//
// Send bug reports, bug fixes, enhancements, requests, flames, etc.,
// and I'll try to keep a version up to date. I can be reached at:
// cristi@gds.ro
/////////////////////////////////////////////////////////////////////////
//
// Acknowledgements:
// o Thanks to Harlan R. Seymour (harlan@hcube.com) for motivating me
// to update this code. Also he prompted me to a bug durring
// the developement phase.
// o Thanks to Zafir Anjum (zafir@codeguru.com) for publishing this
// code on his cool site (www.codeguru.com).
// o Some ideeas for the gripper came from the CToolBarEx flat toolbar
// by Joerg Koenig (Joerg.Koenig@rhein-neckar.de). Also he inspired
// me on writting this notice:) . Thanks, Joerg!
// o Thanks to Jakawan Ratiwanich (jack@alpha.fsec.ucf.edu) and to
// Udo Schaefer(Udo.Schaefer@vcase.de) for the dwStyle bug fix under
// VC++ 6.0.
// o Thanks to Microsoft developers for the MFC source code. After
// all, most of this class code came from there.
//
/////////////////////////////////////////////////////////////////////////
//
// Usage:
// o Derive your class from CSizingControlBar. Then create your child
// controls/windows on it.
// o Include your class header in Mainfrm.cpp and add a member
// variable to CMainFrame. In CMainFrame::OnCreate(), create the
// control bar, enable it to dock, and so on... like a toolbar or
// any control bar.
// o More details at
// http://www.codeguru.com/docking/docking_window.shtml or search
// http://www.codeguru.com for my name if the article has moved.
//
/////////////////////////////////////////////////////////////////////////
// SizingControlBar.cpp : implementation file
//
#include "stdafx.h"
#include "afxpriv.h" // for CDockContext
#include "sizecbar.h"
//#include "afximpl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////
// CSizingControlBar
CSizingControlBar::CSizingControlBar()
{
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 = 5;
m_bDragShowContent = FALSE;
}
CSizingControlBar::~CSizingControlBar()
{
}
BEGIN_MESSAGE_MAP(CSizingControlBar, CControlBar)
//{{AFX_MSG_MAP(CSizingControlBar)
ON_WM_PAINT()
ON_WM_NCPAINT()
ON_WM_WINDOWPOSCHANGED()
ON_WM_NCCALCSIZE()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_NCLBUTTONDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_CAPTURECHANGED()
ON_WM_NCHITTEST()
ON_WM_SETCURSOR()
ON_WM_NCLBUTTONUP()
ON_WM_NCMOUSEMOVE()
ON_WM_SIZE()
//}}AFX_MSG_MAP
ON_NOTIFY_EX(TTN_NEEDTEXT,0,OnTipNotify)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////
// CSizingControlBar message handlers
BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
CSize sizeDefault, BOOL bHasGripper,
UINT nID, DWORD dwStyle)
{
ASSERT_VALID(pParentWnd); // must have a parent
ASSERT (!((dwStyle & CBRS_SIZE_FIXED)
&& (dwStyle & CBRS_SIZE_DYNAMIC)));
// save the style
SetBarStyle(dwStyle & CBRS_ALL);
CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW),
::GetSysColorBrush(COLOR_BTNFACE), 0);
dwStyle &= ~CBRS_ALL;
dwStyle &= WS_VISIBLE | WS_CHILD;
if (!CWnd::Create(wndclass, lpszWindowName, dwStyle, CRect(0,0,0,0),
pParentWnd, nID))
return FALSE;
m_sizeHorz = sizeDefault;
m_sizeVert = sizeDefault;
m_sizeFloat = sizeDefault;
m_bHasGripper = bHasGripper;
m_cyGripper = m_bHasGripper ? 12 : 0;
//允許ToolTips
EnableToolTips(TRUE);
return TRUE;
}
BOOL CSizingControlBar::IsHorzDocked() const
{
return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
}
BOOL CSizingControlBar::IsVertDocked() const
{
return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
}
CSize CSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
CRect rc;
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 (bHorz)
return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
else
return CSize(m_sizeVert.cx, nVertDockBarHeight);
}
CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
if (dwMode & (LM_HORZDOCK | LM_VERTDOCK))
{
if (nLength == -1)
GetDockingFrame()->DelayRecalcLayout();
return CControlBar::CalcDynamicLayout(nLength,dwMode);
}
if (dwMode & LM_MRUWIDTH)
return m_sizeFloat;
if (dwMode & LM_COMMIT)
{
m_sizeFloat.cx = nLength;
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 CSizingControlBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
{
CControlBar::OnWindowPosChanged(lpwndpos);
// Find on which side are we docked
m_nDockBarID = GetParent()->GetDlgCtrlID();
if (!m_bInRecalcNC)
{
m_bInRecalcNC = TRUE;
// Force recalc the non-client area
SetWindowPos(NULL, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE |
SWP_NOACTIVATE | SWP_NOZORDER |
SWP_FRAMECHANGED);
m_bInRecalcNC = FALSE;
}
}
// cache of last needed cursor
AFX_STATIC_DATA HCURSOR _afx_hcurLast = NULL;
AFX_STATIC_DATA HCURSOR _afx_hcurDestroy = NULL;
AFX_STATIC_DATA UINT _afx_idcPrimaryLast = 0; // store the primary IDC
BOOL CSizingControlBar::OnSetCursor(CWnd* pWnd, UINT nHitTest,
UINT message)
{
/*if((nHitTest == HTSYSMENU) && !IsFloating())
{
// MessageBox("aa");
TOOLTIPTEXT m_psttt;
m_psttt.hdr.hwndFrom=m_hWnd;
m_psttt.hdr.idFrom=pWnd->GetDlgCtrlID();
m_psttt.hdr.code=TTN_NEEDTEXT;
m_psttt.uFlags= TTF_IDISHWND;
SetStatusText(ID_DIALAGBAR_FLOAT);
// SendMessage(WM_NOTIFY);
}
else if ((nHitTest == HTMINBUTTON) && !IsFloating())
MessageBox("bb");
*/
if ((nHitTest != HTSIZE) || m_bTracking)
return CControlBar::OnSetCursor(pWnd, nHitTest, message);
UINT idcPrimary; // app supplied cursor
LPCTSTR idcSecondary; // system supplied cursor (MAKEINTRESOURCE)
/*if (IsHorzDocked())
::SetCursor(::LoadCursor(NULL, IDC_SIZENS));
else
::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));*/
// ------- change by syx
if(IsHorzDocked())
{
idcPrimary = AFX_IDC_VSPLITBAR;
idcSecondary = IDC_SIZENS;
}
else
{
idcPrimary = AFX_IDC_HSPLITBAR;
idcSecondary = IDC_SIZEWE;
}
HCURSOR hcurToDestroy = NULL;
if(idcPrimary != _afx_idcPrimaryLast)
{
HINSTANCE hInst = AfxFindResourceHandle(
MAKEINTRESOURCE(idcPrimary), RT_GROUP_CURSOR);
// load in another cursor
hcurToDestroy = _afx_hcurDestroy;
// Note: If this LoadCursor call fails, it is likely that
// _AFX_NO_SPLITTER_RESOURCES is defined in your .RC file.
// To correct the situation, remove the following line from your
// resource script:
// #define _AFX_NO_SPLITTER_RESOURCES
// This should be done using the Resource.Set Includes... command.
if((_afx_hcurDestroy = _afx_hcurLast =
::LoadCursor(hInst, MAKEINTRESOURCE(idcPrimary))) == NULL)
{
// will not look as good
TRACE0("Warning: Could not find splitter cursor - using system provided alternative.\n");
ASSERT(_afx_hcurDestroy == NULL); // will not get destroyed
_afx_hcurLast = ::LoadCursor(NULL, idcSecondary);
ASSERT(_afx_hcurLast != NULL);
}
_afx_idcPrimaryLast = idcPrimary;
}
ASSERT(_afx_hcurLast != NULL);
::SetCursor(_afx_hcurLast);
ASSERT(_afx_hcurLast != hcurToDestroy);
if (hcurToDestroy != NULL)
::DestroyCursor(hcurToDestroy); // destroy after being set
// ------- change by syx
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// Mouse Handling
//
void CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point)
{
if (m_pDockBar != NULL)
{
// start the drag
ASSERT(m_pDockContext != NULL);
ClientToScreen(&point);
m_pDockContext->StartDrag(point);
}
else
CWnd::OnLButtonDown(nFlags, point);
}
void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if (m_pDockBar != NULL)
{
// toggle docking
ASSERT(m_pDockContext != NULL);
m_pDockContext->ToggleDocking();
}
else
CWnd::OnLButtonDblClk(nFlags, point);
}
void CSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
CWindowDC dc(this);
if (m_bTracking) return;
if((nHitTest == HTSYSMENU) && !IsFloating())
{
dc.DrawEdge(m_rectClose,EDGE_SUNKEN,BF_RECT);
}
else if ((nHitTest == HTMINBUTTON) && !IsFloating())
dc.DrawEdge(m_rectUndock,EDGE_SUNKEN,BF_RECT);
else if ((nHitTest == HTSIZE) && !IsFloating())
StartTracking();
else
CControlBar::OnNcLButtonDown(nHitTest, point);
}
void CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bTracking)
StopTracking(TRUE);
CControlBar::OnLButtonUp(nFlags, point);
}
void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point)
{
if (m_bTracking)
StopTracking(FALSE);
CControlBar::OnRButtonDown(nFlags, point);
}
void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bTracking)
{
ASSERT (!IsFloating());
CPoint pt = point;
ClientToScreen(&pt);
OnTrackUpdateSize(pt);
}
CControlBar::OnMouseMove(nFlags, point);
}
void CSizingControlBar::OnCaptureChanged(CWnd *pWnd)
{
if (m_bTracking && pWnd != this)
StopTracking(FALSE); // cancel tracking
CControlBar::OnCaptureChanged(pWnd);
}
void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects,
NCCALCSIZE_PARAMS FAR* lpncsp)
{
// Compute the rectangle of the mobile edge
GetWindowRect(m_rectBorder);
m_rectBorder.OffsetRect(-m_rectBorder.left, -m_rectBorder.top);
m_rectBorder.DeflateRect(1, 1);
m_rectGripper = m_rectBorder;
m_rectGripper.DeflateRect(5, 5);
m_rectGripper.right -= m_cxEdge;
m_rectGripper.bottom -= m_cxEdge;
CRect rc = lpncsp->rgrc[0];
DWORD dwBorderStyle = m_dwStyle | CBRS_BORDER_ANY;
switch(m_nDockBarID)
{
case AFX_IDW_DOCKBAR_TOP:
dwBorderStyle &= ~CBRS_BORDER_BOTTOM;
rc.DeflateRect(m_cyGripper + 2, 2, 2, m_cxEdge + 2);
m_rectBorder.top = m_rectBorder.bottom - m_cxEdge;
break;
case AFX_IDW_DOCKBAR_BOTTOM:
dwBorderStyle &= ~CBRS_BORDER_TOP;
rc.DeflateRect(m_cyGripper + 2, m_cxEdge + 2, 2, 2);
m_rectBorder.bottom = m_rectBorder.top + m_cxEdge;
m_rectGripper.OffsetRect(0, m_cxEdge);
break;
case AFX_IDW_DOCKBAR_LEFT:
dwBorderStyle &= ~CBRS_BORDER_RIGHT;
rc.DeflateRect(2, m_cyGripper + 2, m_cxEdge + 2, 6);
m_rectBorder.left = m_rectBorder.right - m_cxEdge;
break;
case AFX_IDW_DOCKBAR_RIGHT:
dwBorderStyle &= ~CBRS_BORDER_LEFT;
rc.DeflateRect(m_cxEdge + 2, m_cyGripper + 2, 2, 6);
m_rectBorder.right = m_rectBorder.left + m_cxEdge;
m_rectGripper.OffsetRect(m_cxEdge, 0);
break;
default:
m_rectBorder.SetRectEmpty();
break;
}
lpncsp->rgrc[0] = rc;
SetBarStyle(dwBorderStyle);
}
void CSizingControlBar::OnNcPaint()
{
// get window DC that is clipped to the non-client area
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -