📄 headerbar.cpp
字号:
// HeaderBarCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "resource.h"
#include "HeaderBar.h"
#include <afxpriv.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CHeaderBarCtrl, CWnd)
#define CMD_SEPERATOR_COMMANDID 0
// helper function to get the number of buttons in the toolbar
static int GetButtonCount(HWND hwnd)
{
ASSERT(IsWindow(hwnd));
return SendMessage(hwnd, TB_BUTTONCOUNT,0,0);
}
// helper function to get the command id at the specified index.
static int CmdAtIndex(HWND hwnd, const int iIndex)
{
ASSERT(IsWindow(hwnd));
ASSERT(iIndex >= 0 && iIndex < GetButtonCount(hwnd));
TBBUTTON tbb;
VERIFY(SendMessage(hwnd, TB_GETBUTTON, (WPARAM)iIndex, (LPARAM)&tbb));
return tbb.idCommand;
}
// Helper function to get the width of the button at the specified
// index.
static int GetButtonWidthAtIndex(HWND hwnd, const int iIndex)
{
ASSERT(IsWindow(hwnd));
CRect rc;
VERIFY(SendMessage(hwnd, TB_GETITEMRECT, iIndex, (LPARAM)&rc));
return rc.Width();
}
static void FillInBtnStruct(TBBUTTON* pBtn, const int iBmpIndex, const int iStrIndex, const int iIdCmd, const int iStyle, const DWORD dwData)
{
ZeroMemory(pBtn, sizeof(TBBUTTON));
pBtn->iBitmap = iBmpIndex;
pBtn->iString = iStrIndex;
pBtn->idCommand = iIdCmd;
pBtn->fsState = TBSTATE_ENABLED;
pBtn->fsStyle = iStyle;
pBtn->dwData = dwData;
}
/////////////////////////////////////////////////////////////////////////////
// CHeaderBarCtrl
CHeaderBarCtrl::CHeaderBarCtrl()
{
}
CHeaderBarCtrl::~CHeaderBarCtrl()
{
DestroyWindow();
}
// helper function to calculate the width
// of the seperator button and then set it
// so the left and right buttons are correctly
// aligned to the left and right of the client
// window
void CHeaderBarCtrl::AdjustSeperatorButtonSize()
{
const int iSeperatorIndex = CmdAtIndex(m_hWnd, 0) == CMD_SEPERATOR_COMMANDID ? 0 : 1;
// just some logic checking to show any problems
#ifdef _DEBUG
// we have two or three buttons only
// seperator and left or right dropdown
// or seperator and left and right dropdown
ASSERT(GetButtonCount(m_hWnd) == 2 || GetButtonCount(m_hWnd) == 3);
switch (iSeperatorIndex)
{
case 0:
{
// we know we have two buttons and know we second one must be the seperator, there is no third one
// that is to say there is no left dropdown, only a right dropdown
ASSERT(CmdAtIndex(m_hWnd, 1) != -1);
}
break;
case 1:
{
// we know we have two or three buttons and definatly a left button.
// that is to say there is a left dropdown and possibly a right dropdown, though its not guaranteed
ASSERT(CmdAtIndex(m_hWnd, 0) != -1);
}
break;
default:
{
ASSERT(FALSE); // the seperator button is neither on the left nor the middle so problem
}
}
#endif
// if the seperator button is the second button (at index 1) then get the width of the first button
// otherwise the left button is missing so make it zero
const int iLeftWidth = (iSeperatorIndex == 1) ? GetButtonWidthAtIndex(m_hWnd,0) : 0;
// if the seperator button is the first button then the left button is missing so get the width of
// the second dropdown (which is the right button),
// so if we have three buttons we know we have a left and right, otherwise we must have
// two buttons, in which case the second button is a drop down
const int iRightWidth = (GetButtonCount(m_hWnd) == 3) ? GetButtonWidthAtIndex(m_hWnd, 2) : GetButtonWidthAtIndex(m_hWnd, 1);
CRect rc;
GetClientRect(&rc);
const int iSeparatorWidth = rc.Width() - iLeftWidth - iRightWidth;
// Set its size to be the width of the bar less the width of the left and right buttons
TBBUTTONINFO tbiMiddle;
tbiMiddle.cbSize = sizeof(TBBUTTONINFO);
tbiMiddle.dwMask = TBIF_SIZE;
tbiMiddle.cx = iSeparatorWidth;
VERIFY(SendMessage(TB_SETBUTTONINFO, (WPARAM)CMD_SEPERATOR_COMMANDID, (LPARAM)&tbiMiddle));
}
// Adds a toolbar button to the left of the toolbar main window
BOOL CHeaderBarCtrl::AddLeftButton(const TBBUTTON& button)
{
ASSERT(::IsWindow(m_hWnd));
ASSERT(button.idCommand != CMD_SEPERATOR_COMMANDID);
// There should be no buttons added or if there
// is a button added it must be the right button
// so implicitly the button at index 0 is the seperator button
ASSERT(GetButtonCount(m_hWnd) == 1 || (GetButtonCount(m_hWnd) == 2 && CmdAtIndex(m_hWnd, 0) == CMD_SEPERATOR_COMMANDID));
const BOOL bRet = SendMessage(TB_INSERTBUTTON, 0, (LPARAM)&button);
if (bRet)
AdjustSeperatorButtonSize();
else
ASSERT(FALSE); // failed to insert button so assert
return bRet;
}
// Adds a toolbar button to the right of the toolbar main window
BOOL CHeaderBarCtrl::AddRightButton(const TBBUTTON& button)
{
ASSERT(::IsWindow(m_hWnd));
ASSERT(button.idCommand != CMD_SEPERATOR_COMMANDID);
// There should be no buttons added or if there
// is a button added it must be the left button
// so implicitly the button at index 1 is the seperator button
ASSERT(GetButtonCount(m_hWnd) == 1 || (GetButtonCount(m_hWnd) == 2 && CmdAtIndex(m_hWnd, 1) == CMD_SEPERATOR_COMMANDID));
const BOOL bRet = SendMessage(TB_INSERTBUTTON, CmdAtIndex(m_hWnd, 0) == 0 ? 1 : 2, (LPARAM)&button);
if (bRet)
AdjustSeperatorButtonSize();
else
ASSERT(FALSE);
return bRet;
}
// Adds a button to the left of the main toolbar window but the user specifies
// all the fields in the parameters
BOOL CHeaderBarCtrl::AddLeftButton(const int iBmpIndex, const int iStrIndex, const int iIdCmd, const int iStyle, const DWORD dwData)
{
ASSERT(::IsWindow(m_hWnd));
TBBUTTON btn;
FillInBtnStruct(&btn, iBmpIndex, iStrIndex, iIdCmd, iStyle, dwData);
return AddLeftButton(btn);
}
// Adds a button to the right of the main toolbar window but the user specifies
// all the fields in the parameters
BOOL CHeaderBarCtrl::AddRightButton(const int iBmpIndex, const int iStrIndex, const int iIdCmd, const int iStyle, const DWORD dwData)
{
ASSERT(::IsWindow(m_hWnd));
TBBUTTON btn;
FillInBtnStruct(&btn, iBmpIndex, iStrIndex, iIdCmd, iStyle, dwData);
return AddRightButton(btn);
}
BEGIN_MESSAGE_MAP(CHeaderBarCtrl, CWnd)
//{{AFX_MSG_MAP(CHeaderBarCtrl)
ON_WM_CREATE()
ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
ON_NOTIFY_REFLECT(TBN_DROPDOWN, OnDropDown)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CHeaderBarCtrl::OnDropDown( NMHDR * pNotifyStruct, LRESULT* result )
{
LPNMTOOLBAR lpnmtb = (LPNMTOOLBAR)pNotifyStruct;
GetParent()->PostMessage(WM_COMMAND, MAKEWPARAM(lpnmtb->iItem,0), 0);
*result = 0;
}
void CHeaderBarCtrl::OnCustomDraw( NMHDR * pNotifyStruct, LRESULT* result )
{
// The most useful command, this removes the divider line
// in the dropdowns.
LPNMCUSTOMDRAW lplvcd = (LPNMCUSTOMDRAW)pNotifyStruct;
switch(lplvcd->dwDrawStage)
{
case CDDS_PREPAINT :
{
(*result) = CDRF_NOTIFYITEMDRAW;
return;
}
case CDDS_ITEMPREPAINT:
{
(*result) = CDRF_NOVERTBAR;
return;
}
}
*result = TRUE;
}
// Function to create the new toolb
BOOL CHeaderBarCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
// The style must be set to custom erase and no top divider space,
// anthing else is optional.
dwStyle |= (CCS_NODIVIDER | TBSTYLE_CUSTOMERASE);
// initialize common controls
CWnd* pWnd = this;
return pWnd->Create(TOOLBARCLASSNAME, _T("Header Bar Control"), dwStyle, rect, pParentWnd, nID);
}
// This helper function is called whenever windows needs to layuout
// windows in the main frame that are not part of the view.
// it uses this to reserve space for the control and tell
// the frame how much space is left for the view.
// This also moves the window if neccessary
LRESULT CHeaderBarCtrl::OnSizeParent(WPARAM, LPARAM lParam)
{
AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
// get the size of our header bar control
CRect rc;
GetClientRect(&rc);
// shrink the size of the main view to accomodate the
// header bar control.
lpLayout->rect.top += rc.Height();
lpLayout->rect.right = rc.Width();
lpLayout->sizeTotal.cy += rc.Height();
lpLayout->sizeTotal.cx = rc.Width();
lpLayout->bStretch = FALSE;
// If we are laying out the window
// then we move the header bar window
// to its new position. This is actually done
// in a defer window pos call so the changes are done
// once only when all the child windows have been
// laid out.
if (lpLayout->hDWP != NULL)
{
AfxRepositionWindow(lpLayout, m_hWnd, &rc);
}
return 0;
}
// function to add a bitmap to the toolbar.
// note that this also calculates the size of the bitmap assuming
// the the width of the bitmap divided by the number of buttons
// is the width. Note that GetBitmpSize does not work
// on CE, so we need to call GetObject to get the actual size
// of the bitmap.
int CHeaderBarCtrl::AddBitmap(int nNumButtons, CBitmap* pBitmap)
{
ASSERT(::IsWindow(m_hWnd));
ASSERT(nNumButtons > 0);
TBADDBITMAP tbab;
tbab.hInst = NULL;
tbab.nID = (UINT)pBitmap->GetSafeHandle();
int ret = (int) ::SendMessage(m_hWnd, TB_ADDBITMAP, (WPARAM)nNumButtons, (LPARAM)&tbab);
ASSERT(ret != -1);
// once we have added the bitmap, set the bitmap dimensions
BITMAP bmp;
VERIFY(pBitmap->GetObject(sizeof(bmp), &bmp));
const CSize sizeBmp(bmp.bmWidth / nNumButtons, bmp.bmHeight);
VERIFY(SetBitmapSize(sizeBmp));
return ret;
}
// The remaining functions are copies of the toolbar
// control functions from MFC and are just provided for
// completeness.
int CHeaderBarCtrl::AddBitmap(int nNumButtons, UINT nBitmapID)
{
ASSERT(::IsWindow(m_hWnd));
CBitmap bmp;
VERIFY(bmp.LoadBitmap(nBitmapID));
const int ret = AddBitmap(nNumButtons, &bmp);
bmp.Detach();
return ret;
}
int CHeaderBarCtrl::AddString(UINT nStringID)
{
ASSERT(::IsWindow(m_hWnd));
HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE((nStringID>>4)+1),
RT_STRING);
ASSERT(hInst != NULL);
return (int)::SendMessage(m_hWnd, TB_ADDSTRING, (WPARAM)hInst, nStringID);
}
int CHeaderBarCtrl::OnCreate(LPCREATESTRUCT lpcs)
{
if (CWnd::OnCreate(lpcs) == -1)
return -1;
SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON),0);
TBBUTTON btnEmpty = { -1 /*bitmap*/,CMD_SEPERATOR_COMMANDID /*command*/,TBSTATE_INDETERMINATE, TBSTYLE_AUTOSIZE, {0,0} /*reserved*/, 0 /*data*/,-1 /*string*/};
VERIFY(SendMessage(TB_ADDBUTTONS, 1, (LPARAM)&btnEmpty));
return 0;
}
BOOL CHeaderBarCtrl::EnableButton(int nID, BOOL bEnable)
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_ENABLEBUTTON, nID, MAKELPARAM(bEnable, 0));
}
BOOL CHeaderBarCtrl::PressButton(int nID, BOOL bPress)
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_PRESSBUTTON, nID, MAKELPARAM(bPress, 0));
}
BOOL CHeaderBarCtrl::HideButton(int nID, BOOL bHide)
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_HIDEBUTTON, nID, MAKELPARAM(bHide, 0));
}
BOOL CHeaderBarCtrl::IsButtonEnabled(int nID) const
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_ISBUTTONENABLED, nID, 0);
}
BOOL CHeaderBarCtrl::IsButtonPressed(int nID) const
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_ISBUTTONPRESSED, nID, 0);
}
BOOL CHeaderBarCtrl::IsButtonHidden(int nID) const
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_ISBUTTONHIDDEN, nID, 0);
}
BOOL CHeaderBarCtrl::SetState(int nID, UINT nState)
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_SETSTATE, nID, MAKELPARAM(nState, 0));
}
int CHeaderBarCtrl::GetState(int nID) const
{
ASSERT(::IsWindow(m_hWnd));
return (int) ::SendMessage(m_hWnd, TB_GETSTATE, nID, 0L);
}
// lpszStrings are separated by zeroes, last one is marked by two zeroes
int CHeaderBarCtrl::AddStrings(LPCTSTR lpszStrings)
{
ASSERT(::IsWindow(m_hWnd));
return (int) ::SendMessage(m_hWnd, TB_ADDSTRING, 0, (LPARAM)lpszStrings);
}
BOOL CHeaderBarCtrl::SetButtonSize(CSize size)
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(size.cx, size.cy));
}
BOOL CHeaderBarCtrl::SetBitmapSize(CSize size)
{
ASSERT(::IsWindow(m_hWnd));
return (BOOL) ::SendMessage(m_hWnd, TB_SETBITMAPSIZE, 0, MAKELPARAM(size.cx, size.cy));
}
void CHeaderBarCtrl::SetOwner(CWnd* pWnd)
{
ASSERT(::IsWindow(m_hWnd));
::SendMessage(m_hWnd, TB_SETPARENT, (WPARAM)pWnd->GetSafeHwnd(), 0L);
}
UINT CHeaderBarCtrl::GetBitmapFlags() const
{
ASSERT(::IsWindow(m_hWnd));
return (UINT) ::SendMessage(m_hWnd, TB_GETBITMAPFLAGS, 0, 0L);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -