📄 rollupctrl.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
//
// RollupCtrl.cpp
//
// Code Johann Nadalutti
// Mail: jnadalutti@worldonline.fr
//
//////////////////////////////////////////////////////////////////////////////
//
// 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.
//
// 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.
//
//////////////////////////////////////////////////////////////////////////////
//
// History
// --------
// #v1.0
// 31/03/01: Created
//
// #v1.01
// 13/04/01: Added ScrollToPage() method
// Added automatic page visibility to ExpandPage() method
// Added Mousewheel support
// 15/04/01: Added mouse capture checking on WM_MOUSEMOVE dialog msg
// Added SetCursor() on Dialog WM_SETCURSOR
// Added MovePageAt() method
// 17/04/01: Fixed Group Boxes displayed over Buttons
// 20/04/01: Added IsPageExpanded() and IsPageExpanded() methods
// Added PopupMenu
// Added Button subclassing (now button's focus not drawn)
//
// Note
// -----
// Dialog box width is
// RollupCtrlClientRect.Width() - RC_SCROLLBARWIDTH - (RC_GRPBOXINDENT*2)
//
//
// Thanks to
// ----------
// PJ Arends, Ramon Smits, Uwe Keim, Daniel Madden, Do Quyet Tien,
// Ravi Bhavnani, Masaaki Onishi, ...
// and all others users for their comments.
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CRollupCtrl Includes
#include "stdafx.h"
#include "RollupCtrl.h"
/////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CRollupCtrl Message Map
BEGIN_MESSAGE_MAP(CRollupCtrl, CWnd)
//{{AFX_MSG_MAP(CRollupCtrl)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_MOUSEWHEEL()
ON_WM_MOUSEACTIVATE()
ON_WM_CONTEXTMENU()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRollupCtrl Implementation
IMPLEMENT_DYNCREATE(CRollupCtrl, CWnd)
//---------------------------------------------------------------------------
// Constructor
//---------------------------------------------------------------------------
CRollupCtrl::CRollupCtrl()
{
m_strMyClass = AfxRegisterWndClass(
CS_VREDRAW | CS_HREDRAW,
(HCURSOR)::LoadCursor(NULL, IDC_ARROW),
(HBRUSH)COLOR_WINDOW,
NULL);
m_nStartYPos = m_nPageHeight = 0;
}
//---------------------------------------------------------------------------
// Destructor
//---------------------------------------------------------------------------
CRollupCtrl::~CRollupCtrl()
{
//Remove all pages allocations
for (int i=0; i<m_PageList.GetSize(); i++) {
if (m_PageList[i]->pwndButton) delete m_PageList[i]->pwndButton;
if (m_PageList[i]->pwndGroupBox) delete m_PageList[i]->pwndGroupBox;
if (m_PageList[i]->pwndTemplate && m_PageList[i]->bAutoDestroyTpl) {
m_PageList[i]->pwndTemplate->DestroyWindow();
delete m_PageList[i]->pwndTemplate;
}
delete m_PageList[i];
}
}
//---------------------------------------------------------------------------
// Create
//---------------------------------------------------------------------------
BOOL CRollupCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
return CWnd::Create(m_strMyClass, "RollupCtrl", dwStyle, rect, pParentWnd, nID);
}
//---------------------------------------------------------------------------
// Function name : InsertPage
// Description : Return -1 if an error occurs
// Make sure template had WS_CHILD style
//---------------------------------------------------------------------------
int CRollupCtrl::InsertPage(LPCTSTR caption, UINT nIDTemplate, CRuntimeClass* rtc, int idx)
{
if (idx>0 && idx>=m_PageList.GetSize()) idx=-1;
//Create Template
ASSERT(rtc!=NULL);
CDialog* pwndTemplate = (CDialog*)rtc->CreateObject();
BOOL b = pwndTemplate->Create(nIDTemplate, this);
if (!b) { delete pwndTemplate; return -1; }
//Insert Page
return _InsertPage(caption, pwndTemplate, idx, TRUE);
}
//---------------------------------------------------------------------------
// Function name : InsertPage
// Description : return -1 if an error occurs
// Make sure template had WS_CHILD style
//---------------------------------------------------------------------------
int CRollupCtrl::InsertPage(LPCTSTR caption, CDialog* pwndTemplate, BOOL bAutoDestroyTpl, int idx)
{
if (!pwndTemplate) return -1;
if (idx>0 && idx>=m_PageList.GetSize()) idx=-1;
//Insert Page
return _InsertPage(caption, pwndTemplate, idx, bAutoDestroyTpl);
}
//---------------------------------------------------------------------------
// Function name : InsertPage
// Description : Called by InsertPage(...) methods
// Return -1 if an error occurs
// Make sure template had WS_CHILD style
//---------------------------------------------------------------------------
int CRollupCtrl::_InsertPage(LPCTSTR caption, CDialog* pwndTemplate, int idx, BOOL bAutoDestroyTpl)
{
ASSERT(pwndTemplate!=NULL);
ASSERT(pwndTemplate->m_hWnd!=NULL);
//Get client rect
CRect r; GetClientRect(r);
//Create GroupBox
CButton* groupbox = new CButton;
groupbox->Create("", WS_CHILD|BS_GROUPBOX, r, this, 0 );
//Create Button
CButton* but = new CButton;
but->Create(caption, WS_CHILD|BS_AUTOCHECKBOX|BS_PUSHLIKE|BS_FLAT, r, this, 0 );
//Change Button's font
HFONT hfont= (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
CFont* font = CFont::FromHandle(hfont);
but->SetFont(font);
//Add page at pagelist
RC_PAGEINFO* pi = new RC_PAGEINFO;
pi->bExpanded = FALSE;
pi->bEnable = TRUE;
pi->pwndTemplate = pwndTemplate;
pi->pwndButton = but;
pi->pwndGroupBox = groupbox;
pi->pOldDlgProc = (WNDPROC)::GetWindowLong(pwndTemplate->m_hWnd, DWL_DLGPROC);
pi->pOldButProc = (WNDPROC)::GetWindowLong(but->m_hWnd, GWL_WNDPROC);
pi->bAutoDestroyTpl = bAutoDestroyTpl;
int newidx;
if (idx<0) newidx = m_PageList.Add(pi);
else { m_PageList.InsertAt(idx, pi); newidx=idx; }
//Set Dlg Window datas
::SetWindowLong(pwndTemplate->m_hWnd, GWL_USERDATA, (LONG)m_PageList[newidx]);
::SetWindowLong(pwndTemplate->m_hWnd, DWL_USER, (LONG)this);
//Set But Window data
::SetWindowLong(but->m_hWnd, GWL_USERDATA, (LONG)m_PageList[newidx]);
//SubClass Template window proc
::SetWindowLong(pwndTemplate->m_hWnd, DWL_DLGPROC, (LONG)CRollupCtrl::DlgWindowProc);
//SubClass Button window proc
::SetWindowLong(but->m_hWnd, GWL_WNDPROC, (LONG)CRollupCtrl::ButWindowProc);
//Update
m_nPageHeight+=RC_PGBUTTONHEIGHT+(RC_GRPBOXINDENT/2);
RecalLayout();
return newidx;
}
//---------------------------------------------------------------------------
// Function name : RemovePage
// Description :
//---------------------------------------------------------------------------
void CRollupCtrl::RemovePage(int idx)
{
if (idx>=m_PageList.GetSize() || idx<0) return;
//Remove
_RemovePage(idx);
//Update
RecalLayout();
}
//---------------------------------------------------------------------------
// Function name : RemoveAllPages
// Description :
//---------------------------------------------------------------------------
void CRollupCtrl::RemoveAllPages()
{
//Remove all
for (; m_PageList.GetSize();)
_RemovePage(0);
//Update
RecalLayout();
}
//---------------------------------------------------------------------------
// Function name : _RemovePage
// Description : Called by RemovePage or RemoveAllPages methods
//---------------------------------------------------------------------------
void CRollupCtrl::_RemovePage(int idx)
{
RC_PAGEINFO* pi = m_PageList[idx];
//Get Page Rect
CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
//Update PageHeight
m_nPageHeight-=RC_PGBUTTONHEIGHT+(RC_GRPBOXINDENT/2);
if (pi->bExpanded) m_nPageHeight-=tr.Height();
//Remove wnds
if (pi->pwndButton) delete pi->pwndButton;
if (pi->pwndGroupBox) delete pi->pwndGroupBox;
if (pi->pwndTemplate && pi->bAutoDestroyTpl) {
pi->pwndTemplate->DestroyWindow();
delete pi->pwndTemplate;
}
//Remove page from array
m_PageList.RemoveAt(idx);
//Delete pageinfo
delete pi;
}
//---------------------------------------------------------------------------
// Function name : ExpandPage
// Description :
//---------------------------------------------------------------------------
void CRollupCtrl::ExpandPage(int idx, BOOL bExpand)
{
if (idx>=m_PageList.GetSize() || idx<0) return;
//Expand-collapse
_ExpandPage(m_PageList[idx], bExpand);
//Update
RecalLayout();
//Scroll to this page (Automatic page visibility)
if (bExpand) ScrollToPage(idx, FALSE);
}
//---------------------------------------------------------------------------
// Function name : ExpandAllPages
// Description :
//---------------------------------------------------------------------------
void CRollupCtrl::ExpandAllPages(BOOL bExpand)
{
//Expand-collapse All
for (int i=0; i<m_PageList.GetSize(); i++)
_ExpandPage(m_PageList[i], bExpand);
//Update
RecalLayout();
}
//---------------------------------------------------------------------------
// Function name : _ExpandPage
// Description : Called by ExpandPage or ExpandAllPages methods
//---------------------------------------------------------------------------
void CRollupCtrl::_ExpandPage(RC_PAGEINFO* pi, BOOL bExpand)
{
//Check if we need to change state
if (pi->bExpanded==bExpand) return;
if (!pi->bEnable) return;
//Get Page Rect
CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
//Expand-collapse
pi->bExpanded = bExpand;
if (bExpand) m_nPageHeight+=tr.Height();
else m_nPageHeight-=tr.Height();
}
//---------------------------------------------------------------------------
// Function name : EnablePage
// Description :
//---------------------------------------------------------------------------
void CRollupCtrl::EnablePage(int idx, BOOL bEnable)
{
if (idx>=m_PageList.GetSize() || idx<0) return;
//Enable-Disable
_EnablePage(m_PageList[idx], bEnable);
//Update
RecalLayout();
}
//---------------------------------------------------------------------------
// Function name : EnableAllPages
// Description :
//---------------------------------------------------------------------------
void CRollupCtrl::EnableAllPages(BOOL bEnable)
{
//Enable-disable All
for (int i=0; i<m_PageList.GetSize(); i++)
_EnablePage(m_PageList[i], bEnable);
//Update
RecalLayout();
}
//---------------------------------------------------------------------------
// Function name : _EnablePage
// Description : Called by EnablePage or EnableAllPages methods
//---------------------------------------------------------------------------
void CRollupCtrl::_EnablePage(RC_PAGEINFO* pi, BOOL bEnable)
{
//Check if we need to change state
if (pi->bEnable==bEnable) return;
//Get Page Rect
CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
//Change state
pi->bEnable = bEnable;
if (pi->bExpanded) { m_nPageHeight-=tr.Height(); pi->bExpanded=FALSE; }
}
//---------------------------------------------------------------------------
// Function name : ScrollToPage
// Description : Scroll a page at the top of the RollupCtrl if bAtTheTop=TRUE
// or just ensure page visibility into view if bAtTheTop=FALSE
//---------------------------------------------------------------------------
void CRollupCtrl::ScrollToPage(int idx, BOOL bAtTheTop)
{
if (idx>=m_PageList.GetSize() || idx<0) return;
//Get page infos
RC_PAGEINFO* pi = m_PageList[idx];
//Get windows rect
CRect r; GetWindowRect(&r);
CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
//Check page visibility
if (bAtTheTop || ((tr.bottom>r.bottom) || (tr.top<r.top)))
{
//Compute new m_nStartYPos
pi->pwndButton->GetWindowRect(&tr);
m_nStartYPos-= (tr.top-r.top);
//Update
RecalLayout();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -