📄 dockpagebar.cpp
字号:
/////////////////////////////////////////////////////////////////////////
//
// CDockPageBar Version 1.2
//
// Created: Mar 16, 2004
//
/////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 by Cuick. All rights reserved.
//
// This code is free for personal and commercial use, providing this
// notice remains intact in the source files and all eventual changes are
// clearly marked with comments.
//
// Send bug reports, bug fixes, enhancements, requests, flames, etc. to
// Cuick@163.net
//
// Hint: These classes are intended to be used as base classes. Do not
// simply add your code to these file - instead create a new class
// derived from CDockPageBar classes and put there what you need. See
// CTestBar classes in the demo projects for examples.
// Modify this file only to fix bugs, and don't forget to send me a copy.
/////////////////////////////////////////////////////////////////////////
// Acknowledgements:
// o 感谢Cristi Posea的CSizingControlBar
// o 借鉴了王骏的《轻松实现类VC界面》中的部分代码,在这里表示感谢。
// o 感谢hengai帮助修改了部分内存泄漏问题
// o 开发过程中遇到的问题得到了VC知识库论坛中很多人的帮助,这里一并感谢。
//
//////////////////////////////////////////////////////////////////////////
//Updates
//////////////////////////////////////////////////////////////////////////
// Author | Date | Description
//========================================================================
// Tony |2006-09-04 | Bugfixs:
//=======================| 1.add Timer TID_AUTO_HIDE_DELAY to prevent two
//tony__cb@hotmail.com | AHFloatWnds being displayed at the same time.
// | 2.focus switch problems(especially between AHFloatwnd and
// | DockPageBar).
// | 3.frequence screen flash on sizing the DockPageBar.
// | 4.resize the AHFloatWnds with the wider than the mainframe.
// | 5.link problems related with static MFC lib
// | by setting a new compile flag STATIC_MFC_LINK
// | 6.Verify the pWnd's style in CDockPageBar::AddPage function,
// | to make sure pWnd to have the WS_CHILD style, and to avoid
// | the window management disorder in clean up.
// | ------------------------------------------------
// | Improvements and new features:
// | 1.add the slide in/out animation display for AHFloatWnds
// | (the API ::AnimateWindow doesnt work for the self-draw window)
// | 2.make a lot of detail display changes(border,caption bar,...)
// | to have nicer windows
// | 3.add the new docking detection algorithm(accurate docking)
// | just as MS VC2003, but with the limitation that
// | the horizontal docking always has the higher priority.
// | 4.add the support for MDI style Frame
// | 5.rewrite the NcPaint,NcCalClient,OnNcLButtonXXXX,OnNcHitTest part
// | for CDockPageBar to draw the caption(griper),and item tab button
// | in the NcPaint.
// | 6.disable the DragShowContent mode in CSizingControlBar and
// | the OnNcPaint in CDockPageBar when sizing the bar to avoid
// | the dirty & flashy display
//=====================================================================================================
// Tony |2006-10-19 | Modification:
//=======================| 1. Improve the accurate docking feature,and now you can let the dock page bar
// tony__cb@hotmail.com | fill the entire space in the vertical direction.
// | 2. Fix the problem that the close button wrong behavior in the dock page bar.
//======================================================================================================
// DockPageBar.cpp : implementation file
//
#include "stdafx.h"
#include "DockPageBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////
// delete the line between menu bar and tool bar
// From <afximpl.h>
struct AUX_DATA
{
int _unused1, _unused2;
int _unused3, _unused4;
int cxBorder2, cyBorder2;
};
extern __declspec(dllimport) AUX_DATA afxData;
class INIT_afxData
{
public:
INIT_afxData ()
{
afxData.cxBorder2 = afxData.cyBorder2 = 0;
}
} g_afxData2;
/////////////////////////////////////////////////////////////////////////
// CMyButton
CMyButton::CMyButton()
{
bRaised = FALSE;
bPushed = FALSE;
}
void CMyButton::Paint(CDC* pDC, BOOL isActive)
{
CRect rc = GetRect();
if (bPushed)
pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNSHADOW),
::GetSysColor(COLOR_BTNHIGHLIGHT));
else
if (bRaised)
pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNHIGHLIGHT),
::GetSysColor(COLOR_BTNSHADOW));
}
// draw close button
void CCloseButton::Paint(CDC* pDC, BOOL isActive)
{
CMyButton::Paint(pDC, isActive);
COLORREF clrOldTextColor = pDC->GetTextColor();
if(TRUE == isActive)
pDC->SetTextColor(RGB(255,255,255));
else
pDC->SetTextColor(RGB(0,0,0));
int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
CFont font;
int ppi = pDC->GetDeviceCaps(LOGPIXELSX);
int pointsize = MulDiv(75, 96, ppi); // 6 points at 96 ppi
font.CreatePointFont(pointsize, _T("Marlett"));
CFont* oldfont = pDC->SelectObject(&font);
pDC->TextOut(ptOrg.x + 2, ptOrg.y + 2, CString(_T("r"))); // x-like
pDC->SelectObject(oldfont);
pDC->SetBkMode(nPrevBkMode);
pDC->SetTextColor(clrOldTextColor);
}
CStudButton::CStudButton()
{
}
// draw stud
void CStudButton::Paint(CDC* pDC, BOOL isActive)
{
CMyButton::Paint(pDC, isActive);
HPEN oldPen;
CPen pen;
if(TRUE == isActive)
pen.CreatePen (PS_SOLID, 1, RGB(255,255,255));
else
pen.CreatePen (PS_SOLID, 1, RGB(0,0,0));
oldPen = (HPEN)pDC->SelectObject (pen);
if(FALSE == bFloat)
{
pDC->MoveTo (ptOrg.x + 4, ptOrg.y + 8);
pDC->LineTo (ptOrg.x + 4, ptOrg.y + 3);
pDC->LineTo (ptOrg.x + 8, ptOrg.y + 3);
pDC->LineTo (ptOrg.x + 8, ptOrg.y + 8);
pDC->MoveTo (ptOrg.x + 7, ptOrg.y + 3);
pDC->LineTo (ptOrg.x + 7, ptOrg.y + 8);
pDC->MoveTo (ptOrg.x + 2, ptOrg.y + 8);
pDC->LineTo (ptOrg.x + 11, ptOrg.y + 8);
pDC->MoveTo (ptOrg.x + 6, ptOrg.y + 8);
pDC->LineTo (ptOrg.x + 6, ptOrg.y + 12);
}
else
{
pDC->MoveTo (ptOrg.x + 5, ptOrg.y + 4);
pDC->LineTo (ptOrg.x + 10, ptOrg.y + 4);
pDC->LineTo (ptOrg.x + 10, ptOrg.y + 8);
pDC->LineTo (ptOrg.x + 5, ptOrg.y + 8);
pDC->MoveTo (ptOrg.x + 5, ptOrg.y + 7);
pDC->LineTo (ptOrg.x + 10, ptOrg.y + 7);
pDC->MoveTo (ptOrg.x + 5, ptOrg.y + 2);
pDC->LineTo (ptOrg.x + 5, ptOrg.y + 11);
pDC->MoveTo (ptOrg.x + 1, ptOrg.y + 6);
pDC->LineTo (ptOrg.x + 5, ptOrg.y + 6);
}
pDC->SelectObject(oldPen);
}
/////////////////////////////////////////////////////////////////////////////
// CPageItem
void CPageItem::Draw(CDC *pDC, BOOL bActive)
{
CRect rect = m_rect;
COLORREF crOldText;
rect.top +=2;
if(bActive)
{
rect.bottom -= 2;
CRect rcButton=rect;
rcButton.DeflateRect(-1,0,0,-2);
CBrush brush(GetSysColor(COLOR_3DFACE));
pDC->FillRect(rcButton,&brush);
CPen pen(PS_SOLID,1,GetSysColor(COLOR_3DDKSHADOW));
HPEN oldPen = (HPEN)pDC->SelectObject (&pen);
pDC->MoveTo (rect.left-1 , rect.bottom+2 );
pDC->LineTo (rect.right ,rect.bottom+2);
pDC->MoveTo (rect.right-1, rect.top);
pDC->LineTo (rect.right-1,rect.bottom+3 );
pDC->SelectObject (oldPen);
crOldText = pDC->SetTextColor(RGB(0,0,0));
m_pWnd->ShowWindow(SW_SHOW);
}
else
{
CPen pen(PS_SOLID, 1, RGB(128,128,128));
HPEN oldPen = (HPEN)pDC->SelectObject (&pen);
pDC->MoveTo (rect.right, rect.top + 5);
pDC->LineTo (rect.right, rect.bottom -1);
pDC->SelectObject (oldPen);
crOldText = pDC->SetTextColor(RGB(128,128,128));
m_pWnd->ShowWindow(SW_HIDE);
}
rect.left += 3;
rect.right -= 2;
// draw Icon
if(rect.Width() > 16 && m_hIcon != NULL)
{
::DrawIconEx(pDC->m_hDC,rect.left,rect.top + 3,m_hIcon,16,16,0,NULL,DI_NORMAL);
rect.left += 22;
}
if (!m_sText.IsEmpty())
{
// draw text
rect.top += 2;
CString sText = m_sText;
int l = sText.GetLength();
int i;
for(i=0;i<10 && pDC->GetTextExtent(sText).cx > rect.Width();i++,l-=2)
sText = sText.Left(l-2);
if(i > 0)
{
sText = sText.Left(l-2);
sText += "...";
}
int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
pDC->DrawText(sText, &rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
pDC->SetBkMode(nPrevBkMode);
}
pDC->SetTextColor (crOldText);
}
/////////////////////////////////////////////////////////////////////////////
// CDockPageBar
IMPLEMENT_DYNAMIC(CDockPageBar, baseCDockPageBar);
CDockPageBar::CDockPageBar()
{
m_szMinHorz = CSize(50, 50);
m_szMinVert = CSize(60, 60);
m_szMinFloat = CSize(150, 150);
m_cyGripper = CAPTION_HEIGHT+4;
m_isActive = FALSE;
m_Title = "";
m_nActivePage = -1;
m_stud.bFloat = FALSE;
}
CDockPageBar::~CDockPageBar()
{
for(POSITION pos = m_PageList.GetHeadPosition(); pos;)
{
CPageItem* pItem=(CPageItem*)m_PageList.GetNext(pos);
delete pItem; pItem=NULL;
}
m_PageList.RemoveAll();
for(POSITION pos = m_pDPBContext.GetHeadPosition(); pos;)
{
CDockPageBarContext* pDPBContext = (CDockPageBarContext*)m_pDPBContext.GetNext(pos);
if(pDPBContext)
{
pDPBContext->FreeAll();
}
}
m_pDPBContext.RemoveAll();
}
BEGIN_MESSAGE_MAP(CDockPageBar, baseCDockPageBar)
//{{AFX_MSG_MAP(CDockPageBar)
ON_WM_CREATE()
ON_WM_NCPAINT()
ON_WM_SIZE()
//ON_WM_PAINT()
ON_WM_NCHITTEST()
ON_WM_NCLBUTTONUP()
ON_WM_NCLBUTTONDOWN()
ON_WM_NCLBUTTONDBLCLK()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDockPageBar message handlers
int CDockPageBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (baseCDockPageBar::OnCreate(lpCreateStruct) == -1)
return -1;
if (m_font.CreatePointFont(85, "Tahoma"))
SetFont(&m_font);
m_isActive = FALSE;
return 0;
}
void CDockPageBar::OnDestroy()
{
}
void CDockPageBar::OnUpdateCmdUI(CFrameWnd *pTarget, BOOL bDisableIfNoHndler)
{
if (!HasGripper())
return;
BOOL bNeedPaint = FALSE;
CWnd* pFocus = GetFocus();
BOOL bActiveOld = m_isActive;
m_isActive = (pFocus->GetSafeHwnd() && IsChild(pFocus));
m_isActive = m_isActive || (pFocus == this);
if (m_isActive != bActiveOld)
bNeedPaint = TRUE;
CPoint pt;
::GetCursorPos(&pt);
///////////////////////////////////////////////////////////
// hit close
BOOL bHit = (OnNcHitTest(pt) == HTHIDE);
BOOL bLButtonDown = (::GetKeyState(VK_LBUTTON) < 0);
BOOL bWasPushed = m_biHide.bPushed;
m_biHide.bPushed = bHit && bLButtonDown;
BOOL bWasRaised = m_biHide.bRaised;
m_biHide.bRaised = bHit && !bLButtonDown;
bNeedPaint |= (m_biHide.bPushed ^ bWasPushed) ||
(m_biHide.bRaised ^ bWasRaised);
////////////////////////////////////////////////////////////
// hit stud
bHit = (OnNcHitTest(pt) == HTSTUD);
bWasPushed = m_stud.bPushed;
m_stud.bPushed = bHit && bLButtonDown;
bWasRaised = m_stud.bRaised;
m_stud.bRaised = bHit && !bLButtonDown;
bNeedPaint |= (m_stud.bPushed ^ bWasPushed) ||
(m_stud.bRaised ^ bWasRaised);
if (bNeedPaint)
SendMessage(WM_NCPAINT);
}
// draw title bar
void CDockPageBar::NcPaintGripper(CDC *pDC, CRect rcClient)
{
//Note: Here the rcClient' coordinate is for NonClient painting,
// so it is referenced to the current window's topleft.
if (!HasGripper())
return;
CRect clientBorderRc,gripper;
clientBorderRc=gripper=rcClient;
CRect rcbtn = m_biHide.GetRect();
gripper.DeflateRect(-1,-1,0,0);
gripper.top -= m_cyGripper;
gripper.bottom = gripper.top + CAPTION_HEIGHT;
HFONT oldFont = (HFONT)pDC->SelectObject (m_font);
int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
COLORREF crOldText;
if(TRUE == m_isActive) // active state
{
CBrush brush(RGB(10,36,106));
pDC->FillRect(&gripper, &brush);
crOldText = pDC->SetTextColor(RGB(255,255,255));
}
else
{
CPen pen(PS_SOLID, 1, RGB(128,128,128));
HPEN poldPen = (HPEN)pDC->SelectObject (&pen);
// Draw better rect
// ------------------------------
//| |
//| |
// ------------------------------
CPoint pt=gripper.TopLeft();
pt.Offset(1,0);
pDC->MoveTo (pt);
pDC->LineTo (gripper.right ,gripper.top );
pt=gripper.TopLeft();
pt.Offset(1,gripper.Height());
pDC->MoveTo (pt);
pDC->LineTo (gripper.right ,gripper.bottom );
pt=gripper.BottomRight();
pt.Offset(0,-1);
pDC->MoveTo (pt);
pDC->LineTo (gripper.right ,gripper.top);
pt=gripper.BottomRight();
pt.Offset(-gripper.Width(),-1);
pDC->MoveTo(pt);
pDC->LineTo (gripper.left ,gripper.top);
pDC->SelectObject (poldPen);
crOldText = pDC->SetTextColor(RGB(0,0,0));
}
gripper.left += 4;
gripper.top += 2;
// draw caption
if (!m_Title.IsEmpty())
{
CString sText = m_Title;
int l = sText.GetLength();
int i;
for(i=0;i<10 && pDC->GetTextExtent(sText).cx > (gripper.Width() - 30);i++,l-=2)
sText = sText.Left(l-2);
if(i > 0)
{
sText = sText.Left(l-2);
sText += "...";
}
pDC->TextOut (gripper.left, gripper.top, sText);
}
pDC->SetTextColor (crOldText);
pDC->SetBkMode(nPrevBkMode);
pDC->SelectObject(oldFont);
CPoint ptOrgBtn;
ptOrgBtn = CPoint(gripper.right - 15, gripper.top);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -