How to handle chevron button using CToolBarCtrl object?
来源:互联网 发布:花千骨器灵进阶数据 编辑:程序博客网 时间:2024/05/22 10:52
Most of the developers work with CToolBarCtrl but they get stuck when it comes to display chevron button. This article is all about how to get chevron button displayed on CToolBarCtrl control while resizing its content window.
There is a good MSDN article on handling chevrons but no good sample implementation on it. I wrote a small sample using CDialog, CToolBarCtrl and CReBarCtrl classes to illustrate the same.
Since the main focus would be on handling chevron button, I am not going to cover tool bar control implementation details. Following are the steps to achieve chevron button on CToolBarCtrl.
1. Using class wizard, create a new class CCustReBarCtrl deriving it from CReBarCtrl MFC class. Add m_wndReBar and m_wndToolBar of type CCustReBarCtrl and CToolBarCtrl respectively in dialog class. Create rebar and tool bar controls in OnInitDialog() dialog method as shown below.
m_wndReBar.CreateEx(WS_EX_TOOLWINDOW, WS_CHILD | WS_BORDER | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NOPARENTALIGN | CCS_NODIVIDER | RBS_VARHEIGHT | RBS_BANDBORDERS, CRect(0, 0, 0, 0),this, 10);
m_wndToolBar.Create(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NOPARENTALIGN | CCS_NODIVIDER | CCS_NORESIZE | TBSTYLE_TRANSPARENT | TBSTYLE_FLAT, CRect(0,0,0,0), &m_wndReBar, IDR_MAINFRAME); //Note that rebar control is parent for tool bar control.
/*Make sure that tool bar resource is loaded here*/
m_wndToolBar.AutoSize();
Rebar control provides chevron control when RBBS_USECHEVRON flag in the fStyle member of the band's REBARBANDINFOstructure is set. Before defining the band info, define the following macro in stdafx.h file.
#define REBARBANDINFO_SIZE CCSIZEOF_STRUCT(REBARBANDINFO, cxHeader)
SIZE sizeButtons;
m_wndToolBar.GetMaxSize(&sizeButtons);
REBARBANDINFO rbi;
ZeroMemory((void*)&rbi, sizeof(rbi));
rbi.cbSize = REBARBANDINFO_SIZE; // V5 structure size. Insert fails if the struct is too big
rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE;
rbi.fStyle = RBBS_GRIPPERALWAYS | RBBS_USECHEVRON;
rbi.cyMaxChild = rbi.cyMinChild = rbi.cyChild = sizeButtons.cy;
rbi.cxIdeal = rbi.cx = sizeButtons.cx;
rbi.hwndChild = (HWND)m_wndToolBar;
m_wndReBar.InsertBand(-1, &rbi);
RECT rcWindow;
GetClientRect(&rcWindow);
m_wndReBar.MoveWindow(0, 0, rcWindow.right - rcWindow.left, sizeButtons.cy);
2. It’s very important to size the rebar control accordingly when dialog is resized otherwise chevron button will not be displayed. So handle WM_SIZE message (OnSize() method) in the dialog class and add the following code as shown below.
if (m_wndReBar.GetSafeHwnd())
{
RECT rcRebar;
m_wndReBar.GetWindowRect(&rcRebar);
m_wndReBar.MoveWindow(0, 0, cx, rcRebar.bottom - rcRebar.top);
}
3. Now if you run the code and resize the dialog, chevron will be displayed for tools that have been covered. When a user clicks a chevron, the rebar control sends RBN_CHEVRONPUSHED notification. The NMREBARCHEVRON structure that is passed with the notification contains the band's identifier and a RECT structure with the rectangle occupied by the chevron. Your handler must determine which buttons are hidden and display the associated commands on a pop-up menu.
Add RBN_CHEVRONPUSHED notification in CCustReBarCtrl, after adding the message map should look like as shown below
BEGIN_MESSAGE_MAP(CCustRebarCtrl, CReBarCtrl)
ON_NOTIFY_REFLECT(RBN_CHEVRONPUSHED, & CCustRebarCtrl::OnRbnChevronPushed)
END_MESSAGE_MAP()
Following is the code that goes into the chevron handler 'void CCustRebar::OnRbnChevronPushed(NMHDR *pNMHDR, LRESULT *pResult)' method
LPNMREBARCHEVRON pnmrc = reinterpret_cast<LPNMREBARCHEVRON>(pNMHDR);
RECT rcBand;
RECT rcButton;
RECT rcIntersect;
REBARBANDINFO rbi;
TBBUTTON tbb;
UINT cButtons;
UINT iButton;
UINT iMenu;
HMENU hmenuPopup;
MENUITEMINFO mii;
TCHAR szText[200];
HRESULT hr;
CImageList* pimlToolbar;
//
// Get the child window for this band.
ZeroMemory((void*)&rbi, sizeof(rbi));
rbi.cbSize = REBARBANDINFO_SIZE;
rbi.fMask = RBBIM_CHILD;
GetBandInfo(pnmrc->uBand, &rbi);
CToolBarCtrl *pTBarCtrl = (CToolBarCtrl *)CToolBarCtrl::FromHandle ( rbi.hwndChild );
ASSERT(pTBarCtrl);
ASSERT(pTBarCtrl->IsKindOf(RUNTIME_CLASS(CToolBarCtrl)));
//
// Get the client rectangle of the child window
pTBarCtrl->GetClientRect(&rcBand);
//
// Get the number of buttons in the toolbar. This should fail when the
// child window is not a toolbar.
if ((cButtons = pTBarCtrl->GetButtonCount()) == 0)
return;
//
// Starting from the leftmost button, retrieve each button's bounding
// rectangle until we find a button that is at least partially hidden
for (iButton = 1; iButton < cButtons; iButton++)
{
//
// Get the button's rectangle
ZeroMemory((void*)&rcButton, sizeof(rcButton));
pTBarCtrl->GetItemRect(iButton, &rcButton);
CRect rtTabButton(rcButton);
CRect rtToolBarCtr(rcBand);
CPoint ptCenter = rtTabButton.CenterPoint();
if(!rtToolBarCtr.PtInRect(ptCenter))
break;
}
//
// Nothing to do if we didn't find a hidden button
if (iButton == cButtons)
return;
//
// Allocate an array of bitmaps to hold the images used in menu items. An
// alternate approach is to ownerdraw the menu
UINT cImages = cButtons - iButton;
size_t cb = sizeof(HBITMAP) * cImages;
HBITMAP* ahbmpImages = (HBITMAP*)malloc(cb);
if (!ahbmpImages)
return;
ZeroMemory((void*)ahbmpImages, cb);
//
// Create a memory DC that we use to render the toolbar images
HDC hdcMem = NULL;
HDC hdcWindow = ::GetDC(m_hWnd);
if (hdcWindow)
{
hdcMem = CreateCompatibleDC(hdcWindow);
}
//
// Create a popup menu for the hidden toolbar items
hmenuPopup = CreatePopupMenu();
//
// Get the image list for the toolbar
int cxImage = 0;
int cyImage = 0;
pimlToolbar = pTBarCtrl->GetImageList();
if (pimlToolbar)
{
ImageList_GetIconSize(*pimlToolbar, &cxImage, &cyImage);
}
//
// Create a menu item for each hidden toolbar item
iMenu = 0;
for ( ; iButton < cButtons; iButton++)
{
ZeroMemory((void*)szText, sizeof(szText));
ZeroMemory((void*)&tbb, sizeof(tbb));
if (pTBarCtrl->GetButton(iButton, &tbb))
{
if(tbb.idCommand != 0)
{
LoadString(GetModuleHandle(NULL), tbb.idCommand, szText, sizeof(szText)-1);
int cch = strlen(szText);
szText[cch+1] = '/0';
}
//
// Create a bitmap for the toolbar icon and draw the icon into the bitmap
if (hdcMem && pimlToolbar->GetSafeHandle() && ahbmpImages)
{
ahbmpImages[iMenu] = CreateCompatibleBitmap(hdcWindow, cxImage, cyImage);
if (ahbmpImages[iMenu])
{
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, ahbmpImages[iMenu]);
RECT rcImage = {0, 0, cxImage, cyImage};
//
// First, fill the background with the menu background
FillRect(hdcMem, &rcImage, GetSysColorBrush(COLOR_MENU));
//
// Then draw the icon
ImageList_Draw(pimlToolbar->GetSafeHandle(), tbb.iBitmap, hdcMem, 0, 0, ILD_NORMAL);
SelectObject(hdcMem, hbmpOld);
}
}
//
// Add a menu item for this toolbar item
ZeroMemory((void*)&mii, sizeof(mii));
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STRING;
mii.dwTypeData = szText;
mii.wID = tbb.idCommand;
if (ahbmpImages[iMenu])
{
mii.fMask |= MIIM_BITMAP;
mii.hbmpItem = ahbmpImages[iMenu];
}
InsertMenuItem(hmenuPopup, iMenu++, TRUE, &mii);
}
}
//
// Display the popup menu if it has menu items
if (0 < GetMenuItemCount(hmenuPopup))
{
::MapWindowPoints(pnmrc->hdr.hwndFrom, NULL, (LPPOINT)&pnmrc->rc, 2);
TrackPopupMenu(hmenuPopup,
TPM_LEFTALIGN | TPM_TOPALIGN,
pnmrc->rc.left, pnmrc->rc.bottom,
0, m_hWnd, NULL);
}
//
// Destroy the popup menu
DestroyMenu(hmenuPopup);
//
// Cleanup the bitmaps
if (ahbmpImages)
{
while (cImages)
{
cImages--;
if (ahbmpImages[cImages])
DeleteObject(ahbmpImages[cImages]);
}
free(ahbmpImages);
}
//
// Release the DCs used to handle the bitmaps
if (hdcMem)
{
DeleteDC(hdcMem);
}
if (hdcWindow)
{
::ReleaseDC(m_hWnd, hdcWindow);
}
// TODO: Add your control notification handler code here
*pResult = 0;
http://blogs.msdn.com/dsvc/archive/2009/07/02/how-to-handle-chevron-button-using-ctoolbarctrl-object.aspx
http://www.codeproject.com/KB/splitter/zsplitter.aspx
- How to handle chevron button using CToolBarCtrl object?
- How can I display the chevron button for toolbar?
- Using auto_ptr to Handle Memory
- How to handle crash problem?(2.Finding crash information using the MAP file 2)
- How to Handle Javascript Alert, Prompt, Confirmation dialog using selenium webdriver?
- How to handle blocking clicks
- Chevron
- How to Using exploits.
- How to using TOR
- HOW TO: Using CVS
- How to Using Theano
- Using PreTranslateMessage to handle dialog keystrokes
- How to execute an ADF button's action method using javascript
- How to find indexPath for tapped button in tableView Using Seque
- How to handle the pressure job
- MFC how to handle ocx event
- how to handle the office politics
- How to handle jQuery.ajax(..) JSON request ?
- Zw函数与Nt函数的分别与联系
- jdbc连接oracle两种方式
- 打开手机系统界面总结(转)
- 开心农场给我们的人生启示~~~太经典了!!!
- 在SQL Server 2005数据库中实现自动备份
- How to handle chevron button using CToolBarCtrl object?
- 对第六章实验任务(6)的修正
- 解决SQL Server触发器滥用问题
- 我的又一个窝
- Eclipse下CVS的配置
- struts的struts-config中validator代码,validator.xml
- SQL Server数据库备份过程中经常遇到的九种情况
- 微软视频格式的研究
- Windows上建立AndRoid开发环境