(转)工具条研究手记(6)- 在工具条上面创建控件并响应
2011-03-08 16:29
387 查看
/*****************************************************************/
/* 工具条研究手记(6)- 在工具条上面创建控件并响应 */
/*****************************************************************/
一、工具条上面创建组合框,并响应组合框的选择消息。
通常由两种方法在工具条上面添加组合框对象,一种方法是从CToolBar派生一个工具条类,然后嵌入一个组合框,生成工具条以后,创建这个组合框,替换工具条上面的一个分割栏。另一种方法是在工具条的父窗口中(通常是框架窗口)嵌入一个组合框,创建的方法相同。下面分别举例:
1、派生工具条类
第一步:用ClassWizard从CToolBar派生一个CMyToolBar工具条类,然后添加一个public 组合框对象:
class CMyToolBar : public CToolBar
{
public:
CMyToolBar();
virtual ~CMyToolBar();
public:
CComboBox m_Combo;
DECLARE_MESSAGE_MAP()
};
不用添加任何函数。
第二步:把框架窗口类中的工具条类,改成派生类对象:
#include "mytoolbar.h"
class CMainFrame : public CFrameWnd
{
......
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CMyToolBar m_wndToolBar;
......
};
第三步:在工具条上面添加一个按钮,设置一个ID,比如 ID_MYCOMBOBOX,准备在这个按钮的位置创建组合框,而且组合框对象的ID就用这个ID。
第四步:正常创建工具条以后,创建该内嵌组合框:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
//创建这个工具条
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar/n");
return -1; // fail to create
}
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
//下面的代码开始生成工具条按钮上面的组合框。注意该组合框要代替的按钮的id是ID_MYCOMBOBOX
//-------------------------------------------------------------------------
int index = 0;
RECT rect;
//找到指定的工具项
while(m_wndToolBar.GetItemID(index)!=ID_MYCOMBOBOX) index++;
//或者使用 ?int index = m_wndToolBar.CommandToIndex(ID_MYCOMBOBOX);
//设置指定工具项的宽度并获取新的区域? 80是宽度
m_wndToolBar.SetButtonInfo(index, ID_MYCOMBOBOX, TBBS_SEPARATOR, 80);
//取得该工具条项的矩形区域
m_wndToolBar.GetItemRect(index, &rect);
//注意适当调整位置,更美观
rect.top+=2;
rect.bottom += 200;
// 创建组合框并显示
if (!m_wndToolBar.m_Combo.Create(WS_CHILD|WS_VISIBLE | CBS_AUTOHSCROLL |
CBS_DROPDOWNLIST | CBS_HASSTRINGS ,
rect, &m_wndToolBar, ID_MYCOMBOBOX))
//注意父窗口使用该工具条,ID使用 ~~~~~~~~~~~~
{
TRACE0("Failed to create combo-box/n");
return FALSE;
}
m_wndToolBar.m_Combo.ShowWindow(SW_SHOW);
//添加组合框的内容
m_wndToolBar.m_Combo.AddString("25%");
m_wndToolBar.m_Combo.AddString("50%");
m_wndToolBar.m_Combo.AddString("75%");
m_wndToolBar.m_Combo.AddString("100%");
m_wndToolBar.m_Combo.SetCurSel(3);
//-------------------------------------------------------------------------
......//其它代码
return 0;
}
第五步:添加组合框响应的代码:
响应组合框和对话框中响应一个组合框相同,可以参考对话框中的代码,如下:
(1)mainfrm.h头文件中添加一个响应函数,响应组合框的选择变化消息
void OnSelChangeMyCombo();
(2)mainfrm.cpp文件消息映射表中添加
ON_CBN_SELCHANGE(ID_MYCOMBOBOX,OnSelChangeMyCombo)
或者 ON_CONTROL(CBN_SELCHANGE,ID_MYCOMBOBOX,OnSelChangeMyCombo)
或者 ON_CBN_SELENDOK(ID_MYCOMBOBOX,OnSelChangeMyCombo)
(3)添加响应函数:
void CMainFrame::OnSelchangeCombo1()
{
CString str;
m_wndToolBar.m_Combo.GetLBText(m_Combo.GetCurSel(),str);
MessageBox(str);
}
其它组合框消息也可以响应,这些消息的映射代码是:
// Combo Box Notification Codes
#define ON_CBN_ERRSPACE(id, memberFxn) /
ON_CONTROL(CBN_ERRSPACE, id, memberFxn)
#define ON_CBN_SELCHANGE(id, memberFxn) /
ON_CONTROL(CBN_SELCHANGE, id, memberFxn)
#define ON_CBN_DBLCLK(id, memberFxn) /
ON_CONTROL(CBN_DBLCLK, id, memberFxn)
#define ON_CBN_SETFOCUS(id, memberFxn) /
ON_CONTROL(CBN_SETFOCUS, id, memberFxn)
#define ON_CBN_KILLFOCUS(id, memberFxn) /
ON_CONTROL(CBN_KILLFOCUS, id, memberFxn)
#define ON_CBN_EDITCHANGE(id, memberFxn) /
ON_CONTROL(CBN_EDITCHANGE, id, memberFxn)
#define ON_CBN_EDITUPDATE(id, memberFxn) /
ON_CONTROL(CBN_EDITUPDATE, id, memberFxn)
#define ON_CBN_DROPDOWN(id, memberFxn) /
ON_CONTROL(CBN_DROPDOWN, id, memberFxn)
#define ON_CBN_CLOSEUP(id, memberFxn) /
ON_CONTROL(CBN_CLOSEUP, id, memberFxn)
#define ON_CBN_SELENDOK(id, memberFxn) /
ON_CONTROL(CBN_SELENDOK, id, memberFxn)
#define ON_CBN_SELENDCANCEL(id, memberFxn) /
ON_CONTROL(CBN_SELENDCANCEL, id, memberFxn)
2、不派生工具条类,直接把组合框放在框架窗口类中:
省略第一步。
第二步:在框件窗口类中添加组合框对象:
class CMainFrame : public CFrameWnd
{
......
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar; ?//正常的工具条对象
CComboBox m_Combo;??//添加组合框对象
......
};
第三、四、五步和上面相同,注意不用m_wndToolBar.m_Combo,直接使用m_Combo。
3、使用组合框时,应注意的几个问题:
(1)如果工具条没有TBSTYLE_FLAT属性,则不显示分割条,组合框可以正常显示,如果工具条用CreateEx创建,或者给出TBSTYLE_FLAT,则分割条会显示出来,缺省的工具条高度和组合框的高度差不多,正常情况下看不到组合框下面的分割条。但是如果给工具条按钮设置了文字,则工具条的高度加大,就看到组合框的中间(因为分割条是画在它的rect的中央)上下都出现部分分割条,非常不好看。目前我没有找到解决办法。
(2)如果工具条是浮动的,也就是说加入了如下的代码:
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
并且添加了文字:
// 添加按钮文字
for(int i=0;i 〈m_wndToolBar.GetToolBarCtrl().GetButtonCount();i++){
UINT uButtonID = m_wndToolBar.GetItemID(i);
CString str;
if(str.LoadString(uButtonID))
{
int p = str.Find("/n");
if(p)
{
CString strText = str.Right(str.GetLength() - p - 1);
m_wndToolBar.SetButtonText( i, strText);
}
}
}
则工具条的宽度是按照按钮的尺寸和数量计算的,由于组合框占用了比较宽的位置,会造成整个工具条宽度不够,导致后面的按钮被裁剪掉而看不见。解决的方法是加大按钮的尺寸:
m_wndToolBar.SetSizes(CSize(60,40),CSize(16,16));
~~~~ 主要是这个按钮的宽度尺寸
二、工具条上面创建一个滑动条(CSliderCtrl),并响应它。
在这个例子中,我们在工具条上面创建一个滑动条,然后根据它的滑动位置,调整一个图像在视图中的显示比例。
第一步:用ClassWizard创建一个名称为tbSlider的单文档工程,全部使用缺省设置。
第二步:打开资源编辑器,找到工具条,然后添加一个按钮, ID是 IDC_SLIDER。
第三步:打开MainFrm.h,添加一个滑动条对象:
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
public:
CSliderCtrl m_Slider;
.....
第四步:打开MainFrm.cpp 添加创建代码:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
// TODO: Delete these three lines if you don't want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
//-------------------------------------------------------------------
// 下面是添加的代码
int index = m_wndToolBar.CommandToIndex(IDC_SLIDER);
m_wndToolBar.SetButtonInfo(index, IDC_SLIDER, TBBS_SEPARATOR, 80);
CRect rect;
m_wndToolBar.GetItemRect(index, &rect);
// 创建滑动条并显示
if (!m_Slider.Create(WS_CHILD|WS_VISIBLE | TBS_HORZ | TBS_AUTOTICKS |TBS_BOTTOM ,
rect, &m_wndToolBar, IDC_SLIDER))
{
TRACE0("Failed to create slider ctrl/n");
return FALSE;
}
//设置滑动的范围
m_Slider.SetRange(0,100);
m_Slider.SetPos(20);
m_Slider.ShowWindow(SW_SHOW);
//-------------------------------------------------------------------
return 0;
}
第五步:我们这次在视类响应这个滑动条的消息,打开视类的头文件添加响应函数和绘图参数:
class CTbSliderView : public CView
{
......
// Operations
public:
CBitmap m_bmp; //要绘制的位图
double r; //绘制的比例
void OnReleasedcaptureSlider(); //响应函数
......
第六步:给视类重载OnInitialUpdate函数。然后打开视类CPP文件,添加如下的代码:
......
#include "mainfrm.h" //包含框架类的头文件
......
BEGIN_MESSAGE_MAP(CTbSliderView, CView)
......
ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER, OnReleasedcaptureSlider)
END_MESSAGE_MAP()
//当用鼠标调整滑动条的位置,释放鼠标以后,滑动条会发送这个NM_RELEASEDCAPTURE消息
/////////////////////////////////////////////////////////////////////////////
// 响应函数
void CTbSliderView::OnReleasedcaptureSlider()
{
CMainFrame * pMain = (CMainFrame*)AfxGetMainWnd();
int pos = pMain->m_Slider.GetPos();
int min,max;
pMain->m_Slider.GetRange(min,max);
//计算缩放比例,最小缩放比例25%,最大比例4
r = (double)((pos - min)*3.75/(max-min) + 0.25);
//刷新窗口,重新绘制图像
Invalidate();
}
void CTbSliderView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// 加载工程目录中的一个位图,别忘了找一个大小合适的位图放在工程的目录里面
HBITMAP hbmp = 0;
hbmp = (HBITMAP)LoadImage(NULL,"02.bmp",IMAGE_BITMAP,0,0,
LR_DEFAULTSIZE | LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if(hbmp) this->m_bmp.Attach(hbmp);
}
CTbSliderView::CTbSliderView()
{
// 构造函数里面把比例系数缺省设置成1
r = 0.25;
}
CTbSliderView::~CTbSliderView()
{
}
BOOL CTbSliderView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTbSliderView drawing
void CTbSliderView::OnDraw(CDC* pDC)
{
CTbSliderDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if(m_bmp.m_hObject!=NULL)
{
//取得客户区尺寸
CRect clientRect;
GetClientRect(&clientRect);
//取得位图的尺寸,按照比例缩放
BITMAP bm;
m_bmp.GetBitmap(&bm);
int w = bm.bmWidth;
int h = bm.bmHeight;
//计算缩放以后图像的大小
int rw = (int)((double)w * r);
int rh = (int)((double)h * r);
//计算绘制图像的起始位置,图像居中显示
int sx = (clientRect.Width() - rw)/2;
int sy = (clientRect.Height() - rh)/2;
//调整,看是否位于客户区内
if(sx < 0) sx = 0;
if(sy < 0) sy = 0;
//绘制图像
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap *pOldBitmap = memDC.SelectObject(&m_bmp);
pDC->StretchBlt(sx,sy,rw,rh,&memDC,0,0,w,h,SRCCOPY);
memDC.SelectObject(pOldBitmap);
}
}
一切ok了,编译运行一下看看效果把,如果那里没有讲到,请多指正。
三、工具条上面创建一个编辑框和一个Spin控件,并且可以用Spin调整编辑框中的数字。
第一步:用ClassWizard创建一个名称为TbEditSpin的单文档工程,全部使用缺省设置。
第二步:打开资源编辑器,找到工具条,然后添加两个相邻的按钮, ID分别是 IDC_TOOLBAREDIT和
IDC_TOOLBARSPIN 。
第三步:打开mainfrm.h,添加控件
public:
CEdit m_ToolBarEdit;
CSpinButtonCtrl m_ToolBarSpin;
第四步:打开mainfrm.cpp 创建控件
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
//----------------------------------------------------------
// 下面是添加的代码
CRect rect;
int index = m_wndToolBar.CommandToIndex(IDC_TOOLBAREDIT);
//设置指定编辑框的宽度 80
m_wndToolBar.SetButtonInfo(index, IDC_TOOLBAREDIT, TBBS_SEPARATOR, 80);
m_wndToolBar.GetItemRect(index, &rect);
// 创建编辑框并显示
if (!m_ToolBarEdit.Create(WS_CHILD|WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL ,
rect, &m_wndToolBar, IDC_TOOLBAREDIT))
{
TRACE0("Failed to create Edit-box/n");
return FALSE;
}
m_ToolBarEdit.ShowWindow(SW_SHOW);
//--------------------
//创建SPIN控件
index = m_wndToolBar.CommandToIndex(IDC_TOOLBARSPIN);
//设置宽度 10
m_wndToolBar.SetButtonInfo(index, IDC_TOOLBARSPIN, TBBS_SEPARATOR, 10);
m_wndToolBar.GetItemRect(index, &rect);
if (!m_ToolBarSpin.Create(WS_CHILD|WS_VISIBLE |UDS_ARROWKEYS | UDS_SETBUDDYINT,// | UDS_ALIGNRIGHT,
rect, &m_wndToolBar, IDC_TOOLBARSPIN))
{
TRACE0("Failed to create Spin/n");
return FALSE;
}
m_ToolBarSpin.ShowWindow(SW_SHOW);
m_ToolBarSpin.SetRange(1,100);
m_ToolBarSpin.SetPos(50);
m_ToolBarSpin.SetBuddy(&m_ToolBarEdit);
m_ToolBarEdit.SetWindowText("50");
//-------------------------------------------------------------------------
return 0;
}
第五步:在视类里面响应控件,可以响应编辑框文字的变化,也可以响应Spin控件,这里给出后者:
//头文件
class CTbEditSpinView : public CView
{
......
// Operations
public:
CString strSpin; //显示信息的字符串
//响应函数,因为是通过ON_NOTIFY响应,所以带有两个参数
void OnChangeToolbarSpin(NMHDR* pNMHDR, LRESULT* pResult);
//CPP文件
#include "stdafx.h"
#include "tbEditSpin.h"
#include "tbEditSpinDoc.h"
#include "tbEditSpinView.h"
#include "mainfrm.h" //加上这个
......
BEGIN_MESSAGE_MAP(CTbEditSpinView, CView)
......
ON_NOTIFY(UDN_DELTAPOS, IDC_TOOLBARSPIN, OnChangeToolbarSpin)
// ON_EN_CHANGE(IDC_TOOLBAREDIT, OnChangeToolbarEdit) //响应编辑框
END_MESSAGE_MAP()
void CTbEditSpinView::OnChangeToolbarSpin(NMHDR* pNMHDR, LRESULT* pResult)
{
NMUPDOWN* pNMUpDown = (NMUPDOWN*)pNMHDR;
int curPos = pNMUpDown->iPos;
int direct = pNMUpDown->iDelta;
CString strPos = (direct>0)?("你按了上箭头"):("你按了下箭头");
strSpin.Format("%s, 当前位置是:%d",strPos,curPos);
Invalidate();
*pResult = 0;
}
// 显示信息
void CTbEditSpinView::OnDraw(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
pDC->DrawText(strSpin,&rect,DT_CENTER | DT_VCENTER |DT_SINGLELINE);
}
CTbEditSpinView::CTbEditSpinView()
{
strSpin = _T("");
}
//-----------------------------------------------------------------------
4、总结。
上面一共给出三个例子,大同小异,基本上给出了工具条上面添加控件并且响应控件的做法。如果以后发现更好的例子和这个做法不同的,我会继续贴出。
工具条上面使用控件还可以通过CDialogBar来做,这个话题将放在另外一篇文章里面谈。
//--------------------------------------
// End
// iwaswzq 2004/11/25
转自: http://blog.vckbase.com/iwaswzq/archive/2007/08/01/1766.html
/* 工具条研究手记(6)- 在工具条上面创建控件并响应 */
/*****************************************************************/
一、工具条上面创建组合框,并响应组合框的选择消息。
通常由两种方法在工具条上面添加组合框对象,一种方法是从CToolBar派生一个工具条类,然后嵌入一个组合框,生成工具条以后,创建这个组合框,替换工具条上面的一个分割栏。另一种方法是在工具条的父窗口中(通常是框架窗口)嵌入一个组合框,创建的方法相同。下面分别举例:
1、派生工具条类
第一步:用ClassWizard从CToolBar派生一个CMyToolBar工具条类,然后添加一个public 组合框对象:
class CMyToolBar : public CToolBar
{
public:
CMyToolBar();
virtual ~CMyToolBar();
public:
CComboBox m_Combo;
DECLARE_MESSAGE_MAP()
};
不用添加任何函数。
第二步:把框架窗口类中的工具条类,改成派生类对象:
#include "mytoolbar.h"
class CMainFrame : public CFrameWnd
{
......
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CMyToolBar m_wndToolBar;
......
};
第三步:在工具条上面添加一个按钮,设置一个ID,比如 ID_MYCOMBOBOX,准备在这个按钮的位置创建组合框,而且组合框对象的ID就用这个ID。
第四步:正常创建工具条以后,创建该内嵌组合框:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
//创建这个工具条
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar/n");
return -1; // fail to create
}
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
//下面的代码开始生成工具条按钮上面的组合框。注意该组合框要代替的按钮的id是ID_MYCOMBOBOX
//-------------------------------------------------------------------------
int index = 0;
RECT rect;
//找到指定的工具项
while(m_wndToolBar.GetItemID(index)!=ID_MYCOMBOBOX) index++;
//或者使用 ?int index = m_wndToolBar.CommandToIndex(ID_MYCOMBOBOX);
//设置指定工具项的宽度并获取新的区域? 80是宽度
m_wndToolBar.SetButtonInfo(index, ID_MYCOMBOBOX, TBBS_SEPARATOR, 80);
//取得该工具条项的矩形区域
m_wndToolBar.GetItemRect(index, &rect);
//注意适当调整位置,更美观
rect.top+=2;
rect.bottom += 200;
// 创建组合框并显示
if (!m_wndToolBar.m_Combo.Create(WS_CHILD|WS_VISIBLE | CBS_AUTOHSCROLL |
CBS_DROPDOWNLIST | CBS_HASSTRINGS ,
rect, &m_wndToolBar, ID_MYCOMBOBOX))
//注意父窗口使用该工具条,ID使用 ~~~~~~~~~~~~
{
TRACE0("Failed to create combo-box/n");
return FALSE;
}
m_wndToolBar.m_Combo.ShowWindow(SW_SHOW);
//添加组合框的内容
m_wndToolBar.m_Combo.AddString("25%");
m_wndToolBar.m_Combo.AddString("50%");
m_wndToolBar.m_Combo.AddString("75%");
m_wndToolBar.m_Combo.AddString("100%");
m_wndToolBar.m_Combo.SetCurSel(3);
//-------------------------------------------------------------------------
......//其它代码
return 0;
}
第五步:添加组合框响应的代码:
响应组合框和对话框中响应一个组合框相同,可以参考对话框中的代码,如下:
(1)mainfrm.h头文件中添加一个响应函数,响应组合框的选择变化消息
void OnSelChangeMyCombo();
(2)mainfrm.cpp文件消息映射表中添加
ON_CBN_SELCHANGE(ID_MYCOMBOBOX,OnSelChangeMyCombo)
或者 ON_CONTROL(CBN_SELCHANGE,ID_MYCOMBOBOX,OnSelChangeMyCombo)
或者 ON_CBN_SELENDOK(ID_MYCOMBOBOX,OnSelChangeMyCombo)
(3)添加响应函数:
void CMainFrame::OnSelchangeCombo1()
{
CString str;
m_wndToolBar.m_Combo.GetLBText(m_Combo.GetCurSel(),str);
MessageBox(str);
}
其它组合框消息也可以响应,这些消息的映射代码是:
// Combo Box Notification Codes
#define ON_CBN_ERRSPACE(id, memberFxn) /
ON_CONTROL(CBN_ERRSPACE, id, memberFxn)
#define ON_CBN_SELCHANGE(id, memberFxn) /
ON_CONTROL(CBN_SELCHANGE, id, memberFxn)
#define ON_CBN_DBLCLK(id, memberFxn) /
ON_CONTROL(CBN_DBLCLK, id, memberFxn)
#define ON_CBN_SETFOCUS(id, memberFxn) /
ON_CONTROL(CBN_SETFOCUS, id, memberFxn)
#define ON_CBN_KILLFOCUS(id, memberFxn) /
ON_CONTROL(CBN_KILLFOCUS, id, memberFxn)
#define ON_CBN_EDITCHANGE(id, memberFxn) /
ON_CONTROL(CBN_EDITCHANGE, id, memberFxn)
#define ON_CBN_EDITUPDATE(id, memberFxn) /
ON_CONTROL(CBN_EDITUPDATE, id, memberFxn)
#define ON_CBN_DROPDOWN(id, memberFxn) /
ON_CONTROL(CBN_DROPDOWN, id, memberFxn)
#define ON_CBN_CLOSEUP(id, memberFxn) /
ON_CONTROL(CBN_CLOSEUP, id, memberFxn)
#define ON_CBN_SELENDOK(id, memberFxn) /
ON_CONTROL(CBN_SELENDOK, id, memberFxn)
#define ON_CBN_SELENDCANCEL(id, memberFxn) /
ON_CONTROL(CBN_SELENDCANCEL, id, memberFxn)
2、不派生工具条类,直接把组合框放在框架窗口类中:
省略第一步。
第二步:在框件窗口类中添加组合框对象:
class CMainFrame : public CFrameWnd
{
......
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar; ?//正常的工具条对象
CComboBox m_Combo;??//添加组合框对象
......
};
第三、四、五步和上面相同,注意不用m_wndToolBar.m_Combo,直接使用m_Combo。
3、使用组合框时,应注意的几个问题:
(1)如果工具条没有TBSTYLE_FLAT属性,则不显示分割条,组合框可以正常显示,如果工具条用CreateEx创建,或者给出TBSTYLE_FLAT,则分割条会显示出来,缺省的工具条高度和组合框的高度差不多,正常情况下看不到组合框下面的分割条。但是如果给工具条按钮设置了文字,则工具条的高度加大,就看到组合框的中间(因为分割条是画在它的rect的中央)上下都出现部分分割条,非常不好看。目前我没有找到解决办法。
(2)如果工具条是浮动的,也就是说加入了如下的代码:
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
并且添加了文字:
// 添加按钮文字
for(int i=0;i 〈m_wndToolBar.GetToolBarCtrl().GetButtonCount();i++){
UINT uButtonID = m_wndToolBar.GetItemID(i);
CString str;
if(str.LoadString(uButtonID))
{
int p = str.Find("/n");
if(p)
{
CString strText = str.Right(str.GetLength() - p - 1);
m_wndToolBar.SetButtonText( i, strText);
}
}
}
则工具条的宽度是按照按钮的尺寸和数量计算的,由于组合框占用了比较宽的位置,会造成整个工具条宽度不够,导致后面的按钮被裁剪掉而看不见。解决的方法是加大按钮的尺寸:
m_wndToolBar.SetSizes(CSize(60,40),CSize(16,16));
~~~~ 主要是这个按钮的宽度尺寸
二、工具条上面创建一个滑动条(CSliderCtrl),并响应它。
在这个例子中,我们在工具条上面创建一个滑动条,然后根据它的滑动位置,调整一个图像在视图中的显示比例。
第一步:用ClassWizard创建一个名称为tbSlider的单文档工程,全部使用缺省设置。
第二步:打开资源编辑器,找到工具条,然后添加一个按钮, ID是 IDC_SLIDER。
第三步:打开MainFrm.h,添加一个滑动条对象:
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
public:
CSliderCtrl m_Slider;
.....
第四步:打开MainFrm.cpp 添加创建代码:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
// TODO: Delete these three lines if you don't want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
//-------------------------------------------------------------------
// 下面是添加的代码
int index = m_wndToolBar.CommandToIndex(IDC_SLIDER);
m_wndToolBar.SetButtonInfo(index, IDC_SLIDER, TBBS_SEPARATOR, 80);
CRect rect;
m_wndToolBar.GetItemRect(index, &rect);
// 创建滑动条并显示
if (!m_Slider.Create(WS_CHILD|WS_VISIBLE | TBS_HORZ | TBS_AUTOTICKS |TBS_BOTTOM ,
rect, &m_wndToolBar, IDC_SLIDER))
{
TRACE0("Failed to create slider ctrl/n");
return FALSE;
}
//设置滑动的范围
m_Slider.SetRange(0,100);
m_Slider.SetPos(20);
m_Slider.ShowWindow(SW_SHOW);
//-------------------------------------------------------------------
return 0;
}
第五步:我们这次在视类响应这个滑动条的消息,打开视类的头文件添加响应函数和绘图参数:
class CTbSliderView : public CView
{
......
// Operations
public:
CBitmap m_bmp; //要绘制的位图
double r; //绘制的比例
void OnReleasedcaptureSlider(); //响应函数
......
第六步:给视类重载OnInitialUpdate函数。然后打开视类CPP文件,添加如下的代码:
......
#include "mainfrm.h" //包含框架类的头文件
......
BEGIN_MESSAGE_MAP(CTbSliderView, CView)
......
ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_SLIDER, OnReleasedcaptureSlider)
END_MESSAGE_MAP()
//当用鼠标调整滑动条的位置,释放鼠标以后,滑动条会发送这个NM_RELEASEDCAPTURE消息
/////////////////////////////////////////////////////////////////////////////
// 响应函数
void CTbSliderView::OnReleasedcaptureSlider()
{
CMainFrame * pMain = (CMainFrame*)AfxGetMainWnd();
int pos = pMain->m_Slider.GetPos();
int min,max;
pMain->m_Slider.GetRange(min,max);
//计算缩放比例,最小缩放比例25%,最大比例4
r = (double)((pos - min)*3.75/(max-min) + 0.25);
//刷新窗口,重新绘制图像
Invalidate();
}
void CTbSliderView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// 加载工程目录中的一个位图,别忘了找一个大小合适的位图放在工程的目录里面
HBITMAP hbmp = 0;
hbmp = (HBITMAP)LoadImage(NULL,"02.bmp",IMAGE_BITMAP,0,0,
LR_DEFAULTSIZE | LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if(hbmp) this->m_bmp.Attach(hbmp);
}
CTbSliderView::CTbSliderView()
{
// 构造函数里面把比例系数缺省设置成1
r = 0.25;
}
CTbSliderView::~CTbSliderView()
{
}
BOOL CTbSliderView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTbSliderView drawing
void CTbSliderView::OnDraw(CDC* pDC)
{
CTbSliderDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if(m_bmp.m_hObject!=NULL)
{
//取得客户区尺寸
CRect clientRect;
GetClientRect(&clientRect);
//取得位图的尺寸,按照比例缩放
BITMAP bm;
m_bmp.GetBitmap(&bm);
int w = bm.bmWidth;
int h = bm.bmHeight;
//计算缩放以后图像的大小
int rw = (int)((double)w * r);
int rh = (int)((double)h * r);
//计算绘制图像的起始位置,图像居中显示
int sx = (clientRect.Width() - rw)/2;
int sy = (clientRect.Height() - rh)/2;
//调整,看是否位于客户区内
if(sx < 0) sx = 0;
if(sy < 0) sy = 0;
//绘制图像
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap *pOldBitmap = memDC.SelectObject(&m_bmp);
pDC->StretchBlt(sx,sy,rw,rh,&memDC,0,0,w,h,SRCCOPY);
memDC.SelectObject(pOldBitmap);
}
}
一切ok了,编译运行一下看看效果把,如果那里没有讲到,请多指正。
三、工具条上面创建一个编辑框和一个Spin控件,并且可以用Spin调整编辑框中的数字。
第一步:用ClassWizard创建一个名称为TbEditSpin的单文档工程,全部使用缺省设置。
第二步:打开资源编辑器,找到工具条,然后添加两个相邻的按钮, ID分别是 IDC_TOOLBAREDIT和
IDC_TOOLBARSPIN 。
第三步:打开mainfrm.h,添加控件
public:
CEdit m_ToolBarEdit;
CSpinButtonCtrl m_ToolBarSpin;
第四步:打开mainfrm.cpp 创建控件
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
//----------------------------------------------------------
// 下面是添加的代码
CRect rect;
int index = m_wndToolBar.CommandToIndex(IDC_TOOLBAREDIT);
//设置指定编辑框的宽度 80
m_wndToolBar.SetButtonInfo(index, IDC_TOOLBAREDIT, TBBS_SEPARATOR, 80);
m_wndToolBar.GetItemRect(index, &rect);
// 创建编辑框并显示
if (!m_ToolBarEdit.Create(WS_CHILD|WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL ,
rect, &m_wndToolBar, IDC_TOOLBAREDIT))
{
TRACE0("Failed to create Edit-box/n");
return FALSE;
}
m_ToolBarEdit.ShowWindow(SW_SHOW);
//--------------------
//创建SPIN控件
index = m_wndToolBar.CommandToIndex(IDC_TOOLBARSPIN);
//设置宽度 10
m_wndToolBar.SetButtonInfo(index, IDC_TOOLBARSPIN, TBBS_SEPARATOR, 10);
m_wndToolBar.GetItemRect(index, &rect);
if (!m_ToolBarSpin.Create(WS_CHILD|WS_VISIBLE |UDS_ARROWKEYS | UDS_SETBUDDYINT,// | UDS_ALIGNRIGHT,
rect, &m_wndToolBar, IDC_TOOLBARSPIN))
{
TRACE0("Failed to create Spin/n");
return FALSE;
}
m_ToolBarSpin.ShowWindow(SW_SHOW);
m_ToolBarSpin.SetRange(1,100);
m_ToolBarSpin.SetPos(50);
m_ToolBarSpin.SetBuddy(&m_ToolBarEdit);
m_ToolBarEdit.SetWindowText("50");
//-------------------------------------------------------------------------
return 0;
}
第五步:在视类里面响应控件,可以响应编辑框文字的变化,也可以响应Spin控件,这里给出后者:
//头文件
class CTbEditSpinView : public CView
{
......
// Operations
public:
CString strSpin; //显示信息的字符串
//响应函数,因为是通过ON_NOTIFY响应,所以带有两个参数
void OnChangeToolbarSpin(NMHDR* pNMHDR, LRESULT* pResult);
//CPP文件
#include "stdafx.h"
#include "tbEditSpin.h"
#include "tbEditSpinDoc.h"
#include "tbEditSpinView.h"
#include "mainfrm.h" //加上这个
......
BEGIN_MESSAGE_MAP(CTbEditSpinView, CView)
......
ON_NOTIFY(UDN_DELTAPOS, IDC_TOOLBARSPIN, OnChangeToolbarSpin)
// ON_EN_CHANGE(IDC_TOOLBAREDIT, OnChangeToolbarEdit) //响应编辑框
END_MESSAGE_MAP()
void CTbEditSpinView::OnChangeToolbarSpin(NMHDR* pNMHDR, LRESULT* pResult)
{
NMUPDOWN* pNMUpDown = (NMUPDOWN*)pNMHDR;
int curPos = pNMUpDown->iPos;
int direct = pNMUpDown->iDelta;
CString strPos = (direct>0)?("你按了上箭头"):("你按了下箭头");
strSpin.Format("%s, 当前位置是:%d",strPos,curPos);
Invalidate();
*pResult = 0;
}
// 显示信息
void CTbEditSpinView::OnDraw(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
pDC->DrawText(strSpin,&rect,DT_CENTER | DT_VCENTER |DT_SINGLELINE);
}
CTbEditSpinView::CTbEditSpinView()
{
strSpin = _T("");
}
//-----------------------------------------------------------------------
4、总结。
上面一共给出三个例子,大同小异,基本上给出了工具条上面添加控件并且响应控件的做法。如果以后发现更好的例子和这个做法不同的,我会继续贴出。
工具条上面使用控件还可以通过CDialogBar来做,这个话题将放在另外一篇文章里面谈。
//--------------------------------------
// End
// iwaswzq 2004/11/25
转自: http://blog.vckbase.com/iwaswzq/archive/2007/08/01/1766.html
相关文章推荐
- 自定义的cell上面点击不同的控件,不同的响应
- 动态创建控件支持事件响应并可保存与读取
- 在MFC中动态创建控件以及事件响应
- MFC动态创建控件及其消息响应函数
- 在MFC中动态创建控件以及事件响应(静态控件)
- 在MFC中动态创建控件以及消息响应
- 在MFC中创建动态控件的生成与响应
- 在MFC中创建动态控件的生成与响应
- 工具条研究手记(3)- 工具条源代码剖析
- c#创建窗体,向窗体添加控件,设置控件大小位置等属性,写控件的响应
- 在MFC中动态创建控件以及事件响应
- 工具条研究手记1
- 用wx.CheckBox创建复选框控件并响应鼠标点击事件
- 动态创建控件的消息响应添加
- MFC动态创建控件及添加消息响应
- MFC动态创建控件及添加消息响应
- 在MFC中动态创建控件以及事件响应
- 动态创建控件支持事件响应并可保存与读取
- MFC小程序003------MFC使用WebBrowser组件,在对话框中创建滚动视图,动态创建一个静态文本控件并设置鼠标单击的消息响应
- 动态创建控件支持事件响应并可保存与读取