Saturday, May 15, 2004

 

Some notes on Toolbar

1.
Setting the row count of a toolbar

如何动态的改变Toolbar每行的元素个数是我一直没有解决的一个问题。今天碰巧看见了jiangsheng的一段代码才知道了如何做。

如果toolbar处于Floating状态的话,问题已经由Thomas Blenkers解决,参见"Setting the row count of a tool bar"
http://www.codeproject.com/docking/floatsetsize.asp

又或者如下的方法
假定我们的工具条资源号为IDR_PAINTTOOL;
我们从CToolBar类派生出一个CPaintToolbar类,添加一个受保护的成员变量:
protected:UIN m_nColumns; file://排/m_nColumns行
public:
void SetColumns(UINT nColumns);//设置行数
UINT GetColumns() {return m_nColumns;}//获得行数
下面开始添加函数:
void CPaintToolbar::SetColumns(UINT nColumns)
{
m_nColumns=nColums;
int nCount=GetToolBarCtrl().GetButtonCount();

for(int i=0;i {
UINT nStyle=GetButtonStyle(i);
bool bWrap=(((i+1)%nColumns)==0);
if(bWrap) nStyle|=TBBS_WRAPPED;
else nStyle&=~TBBS_WRAPPED;
SetButtonStyle(i,nStyle);
}
Invalidate();
GetParentFrame()->RecalcLayout();//关键在这里
}
好了,一切就这么简单。可这也是当时怎么都想不到的解法

而如果已经dock啦呢,看下面的代码

void g_DockControlBarOn(CFrameWnd*pFrame,CControlBar* pBarToDock,CControlBar* pBarOn,CSize sizeOffset)
{
CRect rect;
DWORD dw;
UINT n;

// get MFC to adjust the dimensions of all docked ToolBars
// so that GetWindowRect will be accurate

pFrame->RecalcLayout();
pBarOn->GetWindowRect(&rect);
rect.OffsetRect(sizeOffset);
dw=pBarOn->GetBarStyle();

n = 0;
n = (dw&CBRS_ALIGN_TOP) ? AFX_IDW_DOCKBAR_TOP : n;
n = (dw&CBRS_ALIGN_BOTTOM && n==0) ? AFX_IDW_DOCKBAR_BOTTOM : n;
n = (dw&CBRS_ALIGN_LEFT && n==0) ? AFX_IDW_DOCKBAR_LEFT : n;
n = (dw&CBRS_ALIGN_RIGHT && n==0) ? AFX_IDW_DOCKBAR_RIGHT : n;

// When we take the default parameters on rect, DockControlBar will dock
// each Toolbar on a seperate line. By calculating a rectangle, we in effect
// are simulating a Toolbar being dragged to that location and docked.

pFrame->DockControlBar(pBarToDock,n,&rect);
}

居然是这种玩法,呜呼,换我自己来,还不知到什么时候才能想到呢

2.
How to lock the toolbar in order to prevent it from floating

By Paul DiLascia
From http://msdn.microsoft.com/msdnmag/issues/04/09/cqa/default.aspx

The only thing you have to do in order to prevent the user from dragging the toolbar is block any mouse message that would trigger dragging. This is what the CLockBar class does: if the toolbar is locked, it blocks mouse messages that would drag the toolbar. You don't want to block the mouse messages if the user is pressing one of the buttons, only when the user tries to drag the toolbar by its gripper or non-client area.

It turns out MFC already has a function to determine when the mouse is in the "draggable" area of the toolbar: OnToolHitTest. If you look inside MFC at the source code for CControlBar::OnLButtonDown (the base class for CToolBar and all control bars), you'll see where MFC initiates dragging:

void CControlBar::OnLButtonDown(...)
{
// only start dragging if clicked in "void" space
if (m_pDockBar != NULL && OnToolHitTest(pt, NULL) == -1) {
// start the drag
} else {
// ignore—pass to base class CWnd
CWnd::OnLButtonDown(...);
}
}


OnToolHitTest is the function MFC uses to determine whether to display a tooltip and when. For toolbars, this is precisely when the mouse is over a button. If the mouse is not over a button, it's in "dead" space such as the gripper or edge where the user can drag. So all you have to do to prevent dragging is eat the mouse message when OnToolHitTest returns -1. This is precisely what CLockBar does, as shown in the following code:

// in CLockBar::WindowProc
if ((msg==WM_LBUTTONDOWN ||
msg==WM_LBUTTONDBLCLK) && m_bLocked) {
CPoint pt(lp);
if (m_pBar->OnToolHitTest(pt, NULL) == -1)
return 0; // eat it
}



<< Home

This page is powered by Blogger. Isn't yours?