当前位置:编程学堂 > vs2010中mfc按钮颜色_VS2010 MFC TreeControl控件子项的增、删、改、图标、节点选中、控件背...

vs2010中mfc按钮颜色_VS2010 MFC TreeControl控件子项的增、删、改、图标、节点选中、控件背...

  • 发布:2023-09-16 10:01

一、准备一个对话框程序

初始化代码:

BOOL CUserManual::OnInitDialog()

{

CDialogEx::OnInitDialog();

// TODO: 在此处添加初始化树形控件的项

HTREEITEM Hhead = m_tree.InsertItem(_T("[DamoguUserManual]"), 1, 0, TVI_ROOT);//添加一级结点

HTREEITEM subH1 = m_tree.InsertItem(_T("H86文件"), 1, 0, Hhead);//添加二级结点

HTREEITEM subH2 = m_tree.InsertItem(_T("Hex文件"), 1, 0, Hhead);//添加二级结点

HTREEITEM subH3 = m_tree.InsertItem(_T("H86转换"), 1, 0, Hhead);//添加二级结点

HTREEITEM subH11 = m_tree.InsertItem(_T("校验规则"), 1, 0, subH1);//添加三级结点

HTREEITEM subH12 = m_tree.InsertItem(_T("合成步骤"), 1, 0, subH1);//添加三级结点

HTREEITEM subH13 = m_tree.InsertItem(_T("校验规则"), 1, 0, subH2);//添加三级结点

HTREEITEM subH21 = m_tree.InsertItem(_T("合成步骤"), 1, 0, subH2);//添加三级结点

HTREEITEM subH22 = m_tree.InsertItem(_T("转换需知"), 1, 0, subH3);//添加三级结点

m_tree.SetBkColor(RGB(255, 255, 255)); //设置树形控件的背景色

m_tree.SetTextColor(RGB(127, 0, 0)); //设置文本颜色

m_tree.SetLineColor(RGB(0, 150, 220)); //设置线的颜色

m_www.sychzs.cn(subH1, TVGN_CARET); //子项subH1为选定项

// TODO: 结束TreeControl代码

return TRUE; // return TRUE unless you set the focus to a control

}

效果如下: 现在为界面添加: 头文件引入变量: CTreeCtrl m_tree;

增加按钮代码

void CUserManual::OnBnClickedBtnTreeadd()

{

// TODO: 在此添加控件通知处理程序代码

CString strInput;

GetDlgItemTextW(IDC_TreeEdit1, strInput);

HTREEITEM hItem = m_tree.GetSelectedItem();

if (!hItem)

hItem = TVI_ROOT;

TVINSERTSTRUCTW ts = { 0 };

ts.hParent = hItem;

ts.itemex.pszText = (LPWSTR)(LPCTSTR)strInput; // 转换

// Long Point Width String

// Long Point Const Type String

ts.item.mask = TVIF_TEXT;

ts.hInsertAfter = TVI_LAST;

HTREEITEM hNewItem = m_tree.InsertItem(&ts);

m_www.sychzs.cnItem(hNewItem);

m_tree.EnsureVisible(hNewItem);

}

二 、删除代码按钮

void CUserManual::OnBnClickedBtnTreedel()

{

// TODO: 在此添加控件通知处理程序代码

HTREEITEM hItem = m_tree.GetSelectedItem();

if (!hItem)

return;

//HTREEITEM hParentItem = m_tree.GetParentItem(hItem);

m_tree.DeleteItem(hItem); // 在vs2015环境下,这一行代码就可以,在删除一个节点之后,会自动选中下一个节点

// 但是,如果在比较老的编译器下,可能还需要上一行和下一行的代码,来保证删除后

// 选择下一个节点的功能

//m_www.sychzs.cnItem(hParentItem);

}

三、修改按钮代码

void CUserManual::OnBnClickedBtnTreeedit()

{

// TODO: 在此添加控件通知处理程序代码

HTREEITEM hItem = m_tree.GetSelectedItem();

if (!hItem)

return;

CString strInput;

GetDlgItemTextW(IDC_TreeEdit1, strInput);

m_tree.SetItemText(hItem, strInput);

}

类向导加入 代码如下:

void CUserManual::OnSelchangedTreemanual(NMHDR *pNMHDR, LRESULT *pResult)

{

LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR);

// TODO: 在此添加控件通知处理程序代码

HTREEITEM hItem = m_tree.GetSelectedItem();

if (hItem)

{

CString strInput = m_tree.GetItemText(hItem);

SetDlgItemTextW(IDC_TreeEdit1, strInput);

}

*pResult = 0;

}

Tree属性设置如下

效果如下: 四、展开所有节点

//.h

void CUserManual::ExpandAllNode(HTREEITEM hItem, CTreeCtrl& treeShow);

//.cpp

//OnInitDialog

ExpandAllNode(m_tree.GetRootItem(), m_tree); // 展开所有节点

//Function API

void CUserManual::ExpandAllNode(HTREEITEM hItem, CTreeCtrl& treeShow)

{

HTREEITEM hChild = treeShow.GetChildItem(hItem);

while(hChild)

{

treeShow.Expand(hItem, TVE_EXPAND);

ExpandAllNode(hChild, treeShow);

hChild = treeShow.GetNextSiblingItem(hChild);

}

}

效果如下: 打开窗口后全部展开

五、载入图标,设置指定名称的节点的图标 在上述基础上,增加

//.h

void SetTreeNodeIcon(HTREEITEM hStartItem, CTreeCtrl& treeCtrl, CString csNodeName);

//.init

HICON hIcon[1]; // 图标句柄

hIcon[1] = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

SetTreeNodeIcon(m_tree.GetRootItem(), m_tree, _T("H86文件"));

void CUserManual::SetTreeNodeIcon(HTREEITEM hStartItem, CTreeCtrl& treeCtrl, CString csNodeName)

{

HTREEITEM hChild = treeCtrl.GetChildItem(hStartItem);

while(hChild)

{

if(csNodeName == treeCtrl.GetItemText(hChild))

{

treeCtrl.SetItemImage(hChild, 1, 1);

return ;

} else {

SetTreeNodeIcon(hChild, treeCtrl, csNodeName);

hChild = treeCtrl.GetNextSiblingItem(hChild);

}

}

}

效果如下:

六、Tree控件列表前加图标 四个步骤

//加载三个图标,并将它们的句柄保存到数组

HICON Icon[4];

Icon[0]=AfxGetApp()->LoadIcon(IDI_ICON1);

Icon[1]=AfxGetApp()->LoadIcon(IDI_ICON2);

Icon[2]=AfxGetApp()->LoadIcon(IDI_ICON3);

Icon[3]=AfxGetApp()->LoadIcon(IDI_ICON4);

// 创建图像序列CImageList对象

CImageList *m_imageList;

m_imageList.Create(20, 20, ILC_COLOR32, 3, 3);

// 将三个图标添加到图像序列

for(int i=0;i<4;i++)

{

m_imageList->Add(Icon[i]); //读入图标

}

// 为树形控件设置图像序列

CTreeCtrl m_tree;

m_tree.SetImageList(&m_imageList, TVSIL_NORMAL);

函数原型

HTREEITEM InsertItem(LPCTSTR lpszItem,

int nImage,

int nSelectedImage,

HTREEITEM hParent = TVI_ROOT,

HTREEITEM hInsertAfter = TVI_LAST);

//lpszItem为新节点的标签文本字符串的指针

//nImage为新节点的图标在树形控件图像序列中的索引

//nSelectedImage为新节点被选中时的图标在图像序列中的索引

//hParent为插入节点的父节点的句柄

//hInsertAfter为新节点的前一个节点的句柄,

//即新节点将被插入到hInsertAfter节点之后

函数原型

BOOL Create(

int cx,

int cy,

UINT nFlags,

int nInitial,

int nGrow

//图片的实际像素宽与高

//图片的实际像素宽与高

//创建图像列表的类型,包括4/8/16/24/32/位色

//创建ImageList初始包括的图像个数

//当初始分配的图像个数不够的时候,新增一个图片时,指定图象列表

//能增加的新图象个数,图像列表空间不够而继续添加image时,将按

//照nGrow继续分配空间,设计时根据具体情况设置合适的值,避免内

//存频繁的改变图像列表而過度頻繁而使系統记忆体碎片化

);

例如 nInitial = 2,nGrow=3 当你添加了两个图像元素以后,还想添加第三个的时候,初始创建分配的nInitial已经使用完了,此时,系统会根据nGrow,为自动增大Imagelist3个元素容量,此时我们的Imagelist就可以容纳5个图像元素了,如果5个使用完毕后,会继续按照nGrow进行再分配,类似于一个可变数组,但参数到底设置多少,还是要根据实际的情况设置合理的值,一要避免浪费空间,又要避免频繁的对Image容器进行resize操作

函数原型 如果树节点需要显示图标时,则必须先创建一个CImageList类的对象,并为其添加多个图像组成一个图像序列,然后调用SetImageList函数为树形控件设置图像序列,在用InsertItem插入节点时传入所需图像在图像序列中的索引即可。

CImageList* SetImageList(CImageList * pImageList,

int nImageListType);

//pImageList为指向图像序列类CImageList的对象的指针,

//若为NULL则删除树形控件的所有图像。

//nImageListType指定图像序列的类型,可以是TVSIL_NORMAL(普通图像序列)

//或TVSIL_STATE(状态图像序列,用图像表示节点的状态)。

相关控件解释,这篇文章写得比较详细,可以参考 >| 传送门

通过类向导,或者手动添加消息:WM_CTLCOLOR,其消息响应函数为:

afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

12

在每个控件开始绘制之前,都会向其父窗口发送WM_CTLCOLOR通告消息,在该消息的处理函数中,可以设置控件显示文本的前景色、背景色以及字体。该消息处理函数还要求返回一个画刷的句柄,用于在控件具体的绘制之前擦除其客户区。当窗口重绘时,也会重新绘制每个控件,从而分别调用该函数,这就给了动态修改控件相关颜色特性的机会。

比如在对应的控件下的OnCtrColor函数中写入:

?

pDC->SetTextColor(RGB(255, 0, 0)); //设置文本前景色 pDC->SetBkColor(RGB(255, 255, 255)); //设置文本背景色 pDC->SetBkMode(TRANSPARENT); //TRANSPARENT或OPAQUE pDC->SelectObject(...)

12345

就可以实现修改某个控件的绘制属性。具体的实现可以参考下面的一段代码:

?

// //m_font1与m_font2为CTestDlg的成员,类型为CFont // BOOL CTestDlg::OnInitDialog() { ...... // TODO: Add extra initialization here m_font1.CreatePointFont(120, TEXT("Impact")); m_font2.CreatePointFont(120, TEXT("Arial")); ...... } ? HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); ? // TODO: Change any attributes of the DC here if (nCtlColor == CTLCOLOR_STATIC) { switch (pWnd->GetDlgCtrlID()) { case IDC_STATIC_1: pDC->SetTextColor(RGB(255, 0, 0)); pDC->SetBkColor(RGB(255, 255, 255)); pDC->SetBkMode(TRANSPARENT); pDC->SelectObject(&m_font1); return (HBRUSH)::GetStockObject(BLACK_BRUSH); break; case IDC_STATIC_2: pDC->SetTextColor(RGB(255, 255, 0)); pDC->SetBkColor(RGB(255, 255, 255)); pDC->SelectObject(&m_font2); return (HBRUSH)::GetStockObject(BLACK_BRUSH); break; default: break; } } ? // TODO: Return a different brush if the default is not desired return hbr; }

?

当然如果是修改dialog的属性,可以直接在最后的return上返回一个画刷,填充dialog的背景颜色。

上面这种方法只是一种静态的修改,因为所有的属性都是一次性设定好了,似乎没有根据情况进行改变的可能。这个是时候就要用到上面所提到的一种方法:强迫窗口重绘,可用的函数有Invalidate()和UpdateWindow(),两者的区别如下:

Invalidate在消息队列中加入一条WM_PAINT消息,其无效区为整个客户区。而UpdateWindow直接发送一个WM_PAINT消息,其无效区范围就是消息队列中WM_PAINT消息(最多只有一条)的无效区。效果很明显,调用Invalidate之后,屏幕不一定马上更新,因为WM_PAINT消息不一定在队列头部,而调用UpdateWindow会使WM_PAINT消息马上执行的,绕过了消息队列。如果你调用Invalidate之后想马上更新屏幕,那就加上UpdateWindow()这条语句。

那么剩下的事情就比较简单了,可以通过设置一个COLORREF m_BrushColor;的成员变量,在调用窗口重绘的函数之前,修改m_BrushColor,然后在OnCtlColor函数中将画刷的颜色创建为该m_BrushColor:

?

m_bkBrush.DeleteObject(); m_bkBrush.CreateSolidBrush(m_BrushColor); //创建一把黄色的背景刷子 ? 下面是我所修改的函数: ? HBRUSH ChandControllerDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); ? // TODO: 在此更改 DC 的任何特性 if((CTLCOLOR_SCROLLBAR)&&(pWnd->GetDlgCtrlID()==IDC_SLIDER1 || pWnd->GetDlgCtrlID()==IDC_SLIDER2)) { ? //此处设置背景的颜色 m_bkBrush.DeleteObject(); m_bkBrush.CreateSolidBrush(RGB(0,255,0)); //创建一把黄色的背景刷子 return m_bkBrush; } ? if((CTLCOLOR_BTN)&&(pWnd->GetDlgCtrlID()==IDOK)) { m_bkBrush.DeleteObject(); m_bkBrush.CreateSolidBrush(RGB(0,255,0)); //创建一把黄色的背景刷子 return m_bkBrush; } m_bkBrush.DeleteObject(); m_bkBrush.CreateSolidBrush(m_BrushColor); //创建一把黄色的背景刷子 ? // TODO: 如果默认的不是所需画笔,则返回另一个画笔 return m_bkBrush; } 通过上面的函数,可以实现对对话框中的控件或者对话框的背景颜色进行动态修改

从VC2008的SP1开始,新加入了很多MFC控件,其界面效果虽然比不上WPF,但与之前的控件相比,也已经是飞越了。无奈目前大家对它的研究还是比较少,虽然自带了一些示例程序,仍然不能满足开发的方方面面。貌似C++的高手更喜欢旧版的MFC控件,这也难怪,新版的控件效果,用旧版的也能实现,只是有些麻烦,也可能高手们都不用MFC吧。我是刚从.net转入C++的新兵,用惯了framework提供的简单控件,再用这MFC,别提多别扭了,唉,没办法,工作嘛。

?

好了,言归正传,这段时间用C++开发应用,使用了最新的VS2010,向导自动生成的MFC框架里便自动应用了新版MFC控件,想实现大尺寸+24位真彩色的工具栏,从网上查到的多是使用CToolbarCtrl实现,在经过了几天的沉淀后,终于找到了一条捷径(估计是目前比较简单就能实现这个功能的方法了),知识碎片都是从网上获得的,成果也应跟大家分享。

?

第一步:准备图片

不知道大家是如何制作工具栏图片的,我使用的方法是,使用Photoshop将几个32×32的图标横向排成一排,图标之间不需要留间隙,确保背景是透明的,然后保存成png文件。为了让VS能够把该图片做为资源导入,需要转为bmp文件:用画图程序打开png文件,另存为24位位图文件。最后,把bmp文件拷贝到项目的res文件夹中,接下来就可以导入资源了,这里假设导入的资源ID为IDB_BITMAP1(这也是默认的图片资源ID),因为下面会用到。

?

第二步:修改工具栏按钮大小

这个最简单,只需要选中按钮,在属性栏中输入需要的尺寸即可,尺寸要与图标大小相同,这里是32×32。然后根据需要创建按钮、设置按钮的ID。

(附:工具栏上会一直有一个按钮,你修改它,就又会跑出来一个新的,这也就是创建按钮的操作;删除按钮的方法是:将按钮拖离工具栏,用Delete键不管用,Delete只是删除了按钮上的图像;插入分隔符的方法也很简单:横向右拖动按钮一定距离,就会插入分隔符,反方向再拖一下,就删除分隔符了)

?

第三步:修改工具栏创建代码

在MainFrame.cpp的OnCreate函数中找到下面的代码:

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(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME))

将其改为:

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_256, 0, 0, TRUE, 0, 0, IDB_BITMAP1))

?

好了,这三步做完,如果中间没出现什么差错,运行程序应该可以看到效果了,祝大家好运! ---------------------? 作者:fxfeixue? 来源:CSDN? 原文:https://www.sychzs.cn/fxfeixue/article/details/6696400? 版权声明:本文为博主原创文章,转载请附上博文链接!

相关文章