VC动态创建控件
- 格式:doc
- 大小:65.50 KB
- 文档页数:11
VC6.0中控件及按钮的设置和使用VC学习笔记1:按钮的使能与禁止用ClassWizard的Member Variables为按钮定义变量,如:m_Button1;则m_Button1.EnableWindow(true); 使按钮处于允许状态m_Button1.EnableWindow(false); 使按钮被禁止,并变灰显示VC学习笔记2:控件的隐藏与显示用CWnd类的函数BOOL ShowWindow(int nCmdShow)可以隐藏或显示一个控件。
例1:CWnd *pWnd;pWnd = GetDlgItem( IDC_EDIT1 ); //获取控件指针,IDC_EDIT为控件ID号pWnd->ShowWindow( SW_HIDE ); //隐藏控件例2:CWnd *pWnd;pWnd = GetDlgItem( IDC_EDIT1 ); //获取控件指针,IDC_EDIT为控件ID号pWnd->ShowWindow( SW_SHOW ); //显示控件以上方法常用于动态生成控件,虽说用控件的Create函数可以动态生成控件,但这种控件很不好控制,所以用隐藏、显示方法不失为一种替代手段。
VC学习笔记3:改变控件的大小和位置用CWnd类的函数MoveWindow()或SetWindowPos()可以改变控件的大小和位置。
void MoveWindow(int x,int y,int nWidth,int nHeight);void MoveWindow(LPCRECT lpRect);第一种用法需给出控件新的坐标和宽度、高度;第二种用法给出存放位置的CRect对象;例:CWnd *pWnd;pWnd = GetDlgItem( IDC_EDIT1 ); //获取控件指针,IDC_EDIT1为控件ID号pWnd->MoveWindow( CRect(0,0,100,100) ); //在窗口左上角显示一个宽100、高100的编辑控件SetWindowPos()函数使用更灵活,多用于只修改控件位置而大小不变或只修改大小而位置不变的情况:BOOL SetWindowPos(const CWnd* pWndInsertAfter,int x,int y,int cx,int cy,UINT nFlags);第一个参数我不会用,一般设为NULL;x、y控件位置;cx、cy控件宽度和高度;nFlags常用取值:SWP_NOZORDER:忽略第一个参数;SWP_NOMOVE:忽略x、y,维持位置不变;SWP_NOSIZE:忽略cx、cy,维持大小不变;例:CWnd *pWnd;pWnd = GetDlgItem( IDC_BUTTON1 ); //获取控件指针,IDC_BUTTON1为控件ID号pWnd->SetWindowPos( NULL,50,80,0,0,SWP_NOZORDER | SWP_NOSIZE ); //把按钮移到窗口的(50,80)处pWnd = GetDlgItem( IDC_EDIT1 );pWnd->SetWindowPos( NULL,0,0,100,80,SWP_NOZORDER | SWP_NOMOVE ); //把编辑控件的大小设为(100,80),位置不变pWnd = GetDlgItem( IDC_EDIT1 );pWnd->SetWindowPos( NULL,0,0,100,80,SWP_NOZORDER ) ; //编辑控件的大小和位置都改变以上方法也适用于各种窗口。
VC中Windows常用控件的创建和使用引言本文将要介绍的Windows控件指的是Windows系统预定义的标准控件,如按钮控件、编辑控件和列表控件等。
这些预定义控件实际是一种特殊的子窗口,主要供用户同应用程序的交互之用。
和普通窗口类一样,每一个预定义控件也都是由所属的窗口类规定了自身的外观属性和具有的功能。
Windows系统通过预定义的方式提供了一些标准控件的窗口类名,在程序设计时只需通过调用CreateWindow()函数或CreateWindowEx()函数并将预定义的窗口类名作为参数传入即可创建出相应的控件。
当用户通过屏幕对象同控件进行交互操作时,控件将以"通知消息"的形式向父窗口发送WM_COMMAND通知消息,消息的wParam参数含有控制标识,在lPamam参数的高位字和低位字中分别含有通知码和控制句柄,由父窗口完成对消息的响应处理。
按钮类控件按钮类控件是窗口类名被系统预定义为BUTTON的一类控件,该类控件具有十余种不同的窗口风格,包含了普通的下压式按钮、单选按钮、复选按钮和分组框等多种常用的按钮形式。
具体情况列表如下:以上按钮风格通常需要同窗口风格共同使用,由CreateWindow()函数或MFC的CButton类成员函数Create()完成对按钮的创建:如果需要处理按钮发送给其父窗口的消息,可以在进行消息响应的类实现中添加一个如下形式的消息映射入口和相应的消息处理函数:ON_Notification(id, memberFxn )其中,id为发送通知消息的按钮ID号,memberFxn为消息处理函数。
如果按钮是以new操作符的方式在堆(heap)内创建一个CButton对象,那么就必须确保在关闭窗口前能调用delete销毁该对象。
如果CButton对象是在栈上创建的就不必显式销毁对象了,应用程序在退出时会自动予以销毁。
编辑类控件以窗口类名"EDIT"创建的编辑类控件是一个可以用来接受用户键盘字符输入的矩形区域,可以在其内进行编辑操作。
1.概论先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量、函数或类。
在仓库的发展史上经历了“无库-静态链接库-动态链接库”的时代。
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了。
但是若使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。
静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
对动态链接库,我们还需建立如下概念:(1)DLL 的编制与具体的编程语言及编译器无关只要遵循约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以相互调用。
譬如Windows提供的系统DLL(其中包括了Windows的API),在任何开发环境中都能被调用,不在乎其是Visual Basic、Visual C++还是Delphi。
(2)动态链接库随处可见我们在Windows目录下的system32文件夹中会看到kernel32.dll、user32.dll和gdi32.dll,windows的大多数API都包含在这些DLL中。
kernel32.dll中的函数主要处理内存管理和进程调度;user32.dll中的函数主要控制用户界面;gdi32.dll中的函数则负责图形方面的操作。
一般的程序员都用过类似MessageBox的函数,其实它就包含在user32.dll这个动态链接库中。
由此可见DLL对我们来说其实并不陌生。
(3)VC动态链接库的分类Visual C++支持三种DLL,它们分别是Non-MFC DLL(非MFC动态库)、MFC Regular DLL(MFC规则DLL)、MFC Extension DLL(MFC扩展DLL)。
VC 编写ActiveX控件VC++编写ActiveX控件2010-12-23 10:16前言:暑假在做一个项目的时候,本来是用C#.NET来写的一个港口进出闸的流程控制程序,里面涉及一个响应用PLC的采集信息的问题(PLC用串口和工控机相连接),然后思考如何用C#写串口通讯程序,结果师兄在一旁直接用VC++写了一个"*.ocx控件",并在自己的电脑上进行了测试,完工后就把生成的"*.ocx"控件注册文件复制到了我们的电脑上。
我们就在C#.NET程序里面将此控件拖入到主窗口中,然后就能直接利用此控件的事件来捕捉PLC的命令了,感觉好神奇。
然后,我对C++的态度有了极大的转变,以前只知道C++写窗口程序是多么麻烦啊(远不如C#.NET来得快和直接),而它的所谓"比较底层,和底层操作系统的关系比C#这些高级语言要密切很多"的好处一直都没有体会到,现在才知道,正是因为C++比较底层,比较基础,所以它可以开发出很多和语言无关的公用程序块,如dll动态链接库和COM组件,原则上,只要你的Windows的系统,用VC++开发出来的这些公用程序块就能被任何语言调用(如果不用MFC框架,而用ATL框架来编写,甚至还可以脱离Windwos系统,不仅仅实现跨语言,甚至跨平台调用,这个笔者就没有仔细研究了)。
本人大学本科所学本来是电子技术的工业自动化,结果中途做的几次项目都是"纯软件",这次暑假的经历,终于让我在"硬件"和"软件"之前找到一个连接交汇点了。
以前做电子产品只是为了实现功能,现在发现这远远不够,按照目前的时代潮流,一个系统除了要功能完备化,还要信息化,信息化就涉及到数据采集、存储、分析和显示。
当然如果你不是做系统的,那么你也不必去用全局的眼光去看待这个问题,但你做了电子产品后,却不能让它的功能仅仅局限于在现场完成一些自动控制,而应该开发出和设备相关的上层API,供广大的非电子专业的上层程序员进行二次开发,在PC上层平台上对数据信息进行更好的组织和处理。
Visual studio c++ 2017 动态链接库的创建和使用总结一动态链接库的创建两种方式:1、只有从文件->新建->项目->Windows桌面-> Windows桌面向导->选择“动态链接库(.dll)->生成解决方案,才会生成.dll和.lib文件。
(1)在头文件声明中(注意要在头文件变量和函数声明中,而不是在变量和函数的定义中声明),不加extern “C”修饰,编译成DLL后,用depends.exe查看导出函数名。
可以看出,导出的函数名都被编译器篡改了。
(2)在头文件声明中,变量和函数名前加extern “C”修饰后,编译成DLL后,再用depends.exe查看导出函数名。
可以看出,用extern “C”修饰的函数名,编译后函数名保持不变。
类及成员函数不能用extern “C”修饰,编译成DLL后,成员函数名发生了改变。
2、如果从文件->新建->项目->动态链接库(DLL)->生成解决方案,就只生成.dll,不生成.lib。
二动态链接库的调用两种方式:1、显式调用(1)使用显式调用的前提:创建的DLL,编译时不要篡改函数名称,定义函数名时,可用extern “C”修饰函数名,保证编译时,函数名不被篡改。
否则GetProcAddress( )不能正确地获取dll中的函数名。
但是导出的类不能使用extern “C”修饰。
(2)使用显式调用的优点:不用动态链接库的.h和.lib文件,只要有.dll文件就可调用库函数,使用LoadLibrary(),在需要调用.dll中的库函数时,才动态加载到内存中,使用完毕后,可以用FreeLibrary()释放内存中的dll;使用GetProcAddress( )获取dll中的函数名。
必须事先知道dll中的函数名和形式参数。
(3)使用显式调用缺点:调用每个函数时,都必须使用 GetProcAddress( )获取dll中的函数名,并转换成原来的函数,比较麻烦。
C#动态添加控件(数组控件)中秋吃了⽉饼,还是想把问题解决,所以研究了⼀个下午.研究参考了好多⽹上的资料如何动态添加数组控件,终于可以成功实现了,先在设计页⾯上添加⼀个label控件,然后就在对应的代码输⼊:如button_click 事件中Label [] mypic_inf=new Label [10];int i= 1while (reader.Read()) //{ if (i == 1){mypic_inf[1] = Label1;}else{ mypic_inf[i] = new Label();mypic_inf[i].ID = "Label" + i;this.Controls.Add(mypic_inf[i]);mypic_inf[i].Height = 100;mypic_inf[i].Width = 150;}mypic_inf[i].Text="ok"+i; //这⾥是测试⽤,其实可以有很⼴泛的⽤途,慢慢研究吧i++;}然⽽,在当天晚上经过再三修改的测试,发现了问题,就是因为添加了⼀个label控件,当你要查询或需要该数据的时候,它能正确\正常,但当你要查询,或者不需要该控件出现的时候,它就驻留在内存中,不能正确显⽰,最后还是不要添加⼀个label控件为好,就⽤代码ok了,如下Label [] mypic_inf=new Label [10];int i= 1while (reader.Read()) //{mypic_inf[i] = new Label();mypic_inf[i].ID = "Label" + i;this.Controls.Add(mypic_inf[i]);mypic_inf[i].Height = 100;mypic_inf[i].Width = 150;mypic_inf[i].Text="ok"+i; //这⾥是测试应⽤,其实可以有很⼴泛的⽤途,慢慢研究吧i++;}reader.close;connetion.close;最后不要忘记关闭对象和数据连接哦。
c#winform怎样实现动态⽣成控件?Microsoft Visual Studio 2010 窗体设计中,需要什么控件就从⼯具箱⾥拖出⼀个控件“挂”在窗体上。
其实,窗体上的控件,不但可以“拖”,还可以⽤代码动态⽣成。
动态⽣成控件,对需要相同的⼤量的控件还是⽐较有⽤的。
下⾯⼩编介绍⼀下实现的⽅法,希望对⼴⼤编程爱好者有所帮助,并籍以抛砖引⽟。
⼯具/原料Microsoft Visual Studio 2010⽅法/步骤1.打开Microsoft Visual Studio 2010新建解决⽅案,添加项⽬——动态⽣成控件2.窗体布局把窗体设置合适的⼤⼩3.确定控件的基本属性1、假设要添加15个button按钮;2、基本属性如下:Name:名称 myButtonText:显⽰⽂本按钮(i)Size:⼤⼩ 50*50Location:窗体位置4.Location属性如何动态变化?(分析如图)假设要把15个按钮,每5个⼀⾏⽣成,那么就需要让Location属性动态变化?怎么办?经过分析,确定X的坐标为:50+i%5*1005.Y的坐标如何动态确定?1、定义⼀个⾏变量;2、Y的坐标为:50+row*1003、增加判断换⾏条件:i % 5 == 0 && i != 06.输⼊代码试试看?ok!运⾏效果如图7.完整代码:namespace 设计{public partial class form1 : Form{public form1(){InitializeComponent();}private void form1_Load(object sender, EventArgs e){int row = 0;for (int i = 0; i < 15; i++){if (i % 5 == 0 && i != 0){row++;}Button btn = new Button();//控件名称 = "mybutton" + i.ToString();//控件显⽰⽂本btn.Text = string.Format("按钮{0}", i + 1);//控件⼤⼩btn.Size = new Size(50,50);//控件位置【动态变化】btn.Location = new Point(50+i%5*100,50+row*100); //添加到窗体this.Controls.Add(btn);}}}}。
VC动态创建工具栏及工具栏上的按钮及为按钮添加消息响应函数// OnInitDialog函数中//向列表中添加图标m_imagelist.Create(32,32,ILC_COLOR24|ILC_MASK,1,1);m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON12));m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON13));m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON9));m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON10));//m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON5));// m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON6));UINT arry[10];for(int i=0;i<5;i++){if(i==2) //第四个按钮为分割条;arry[i]=ID_SEPARATOR;elsearry[i]=i+1001;}m_toolbar.Create(this);m_toolbar.SetButtons(arry,5);m_toolbar.SetButtonText(0,"增加"); //图片下面添加文字;m_toolbar.SetButtonText(1,"修改");m_toolbar.SetButtonText(3,"删除");m_toolbar.SetButtonText(4,"关闭");//m_toolbar.SetButtonText(5,"学生管理");// m_toolbar.SetButtonText(6,"远程连接");m_toolbar.GetT oolBarCtrl().SetButtonWidth(20,30);m_toolbar.GetT oolBarCtrl().SetImageList(&m_imagelist);m_toolbar.SetSizes(CSize(50,50),CSize(32,32));//设置大小;RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CO NTROLBAR_LAST,0);//窗口类h头文件中//工具栏上的按钮的ID是连续的,如果不连续,一个按钮一个响应,或者修改为连续的,视情况而定afx_msg void OnBnClickedToolBar(UINT nID);//消息映射部分ON_COMMAND_RANGE(ID_BUTTON_1, ID_BUTTON_N, OnBnClickedToolBar)//工具栏上按钮的消息响应void CXXXDlg::OnBnClickedToolBar(UINT nID){int nIndex = nID - ID_BUTTON_1;CString strText(_T(""));strText.Format(_T("You select index: %d"), nIndex + 1);AfxMessageBox(strText);}。
VCMFC之ListCtrl控件使用经验总结本文将从创建ListCtrl控件、数据的插入、删除和修改、列表项的选择和排序等方面,总结一些经验和注意事项。
一、创建ListCtrl控件创建ListCtrl控件的方法有很多,下面介绍两种常用的方法。
2. 动态创建ListCtrl控件:可以通过CListCtrl类的Create函数来动态创建ListCtrl控件。
例如:```cppCListCtrl m_listCtrl;m_listCtrl.Create(WS_CHILD , WS_VISIBLE , LVS_REPORT, CRect(0, 0, 500, 300), this, IDC_LIST_CTRL);```此外,还可以通过控件向导创建ListCtrl控件,控件向导在创建ListCtrl控件时会生成相关的代码。
二、数据的插入、删除和修改1.插入数据:可以使用InsertItem函数向ListCtrl控件中插入新的项。
例如:```cppm_listCtrl.InsertItem(0, _T("Item 1"));2.删除数据:可以使用DeleteItem函数删除ListCtrl控件中的其中一项。
例如:```cppm_listCtrl.DeleteItem(0);```3.修改数据:可以通过SetItemText函数修改ListCtrl控件中其中一项的文字。
例如:```cppm_listCtrl.SetItemText(0, 1, _T("Modified Item"));```三、列表项的选择和排序1.列表项的选择:可以使用GetNextItem函数和SetItemState函数来获取和设置ListCtrl控件中的选中项。
例如:```cppint nItem = m_listCtrl.GetNextItem(-1, LVNI_SELECTED);m_listCtrl.SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED);2.列表项的排序:可以使用SortItems函数对ListCtrl控件中的数据进行排序。
VC动态创建控件动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的。
一、创建动态控件:为了对照,我们先来看一下静态控件的创建。
放置静态控件时必须先建立一个容器,一般是对话框,这时我们在对话框编辑窗口中,从工具窗口中拖出所需控件放在对话框中即可,再适当修改控件ID,设置控件属性,一个静态控件就创建好了,当对话框被显示时,其上的控件也会显示。
静态控件不需要调用Create()函数来创建。
而创建动态控件有很大不同,以下以按钮为例,看一下动态控件的创建过程:1.建立控件ID号:ID号是控件的标识,创建控件前必须先为它设置一个ID号。
打开资源中的“String Table”,在空白行上双击鼠标,这时会弹出一个ID属性对话框,在其中的ID编辑框中输入ID,如:IDC_MYBUTTON,在Caption中输入控件标题或注解(注:Caption框不能为空,为空会导致创建失败),这里我输入的是按钮上要显示的文字--动态按钮。
2.建立控件对象:不同种类的控件应创建不同的类对象:·按钮控件CButton (包括普通按钮、单选按钮和复选按钮)·编辑控件CEdit·静态文本控件CStatic·标签控件CTabCtrl·旋转控件CSpinButtonCtrl·滑标控件CSliderCtrl·多信息编辑控件CRichEditCtrl·进度条控件CProgressCtrl·滚动条控件CSrcollBar·组合框控件CComboBox·列表框控件CListBox·图像列表控件CImageCtrl·树状控件CTreeCtrl·动画控件CAnimateCtrl本例中我们创建一个CButton类的普通按钮。
注意不能直接定义CButton对象,如:CButton m_MyBut;这种定义只能用来给静态控件定义控制变量,不能用于动态控件。
正确做法是用new调用CButton构造函数生成一个实例:lpszCaption是按钮上显示的文本;dwStyle指定按钮风格,可以是按钮风格与窗口风格的组合,取值有:窗口风格:·WS_CHILD 子窗口,必须有·WS_VISIBLE 窗口可见,一般都有·WS_DISABLED 禁用窗口,创建初始状态为灰色不可用的按钮时使用·WS_TABSTOP 可用Tab键选择·WS_GROUP 成组,用于成组的单选按钮中的第一个按钮按钮风格:·BS_PUSHBUTTON 下压式按钮,也即普通按钮·BS_AUTORADIOBUTTON 含自动选中状态的单选按钮·BS_RADIOBUTTON 单选按钮,不常用·BS_AUTOCHECKBOX 含自动选中状态的复选按钮·BS_CHECKBOX 复选按钮,不常用·BS_AUTO3STATE 含自动选中状态的三态复选按钮·BS_3STATE 三态复选按钮,不常用以上风格指定了创建的按钮类型,不能同时使用,但必须有其一。
·BS_BITMAP 按钮上将显示位图·BS_DEFPUSHBUTTON 设置为默认按钮,只用于下压式按钮,一个对话框中只能指定一个默认按钮·rect指定按钮的大小和位置;·pParentWnd指示拥有按钮的父窗口,不能为NULL;·nID指定与按钮关联的ID号,用上一步创建的ID号。
不同控件类的Create()函数略有不同,可参考相关资料。
例:p_MyBut->Create( "动态按钮", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(20,10,80,40), this, IDC_MYBUTTON );这样,我们就在当前对话框中的(20,10)处创建了宽60,高30,按钮文字为“动态按钮”的下压式按钮。
为了使创建过程更方便易用,我定义了如下函数:其中m_Caption.LoadString( nID )是从字符串表中读取按钮文本,这样在创建按钮ID时,应该把文本设置好,参数nStyle为除必须风格外的额外风格。
以下,调用该函数在ONINIATIAL中创建三个按钮,并指定第一个按钮为默认按钮,按钮的ID在STRING TABLE中已预先设置好了:二、动态控件的响应:动态控件的响应函数不能用ClassWizard添加,只能手动添加。
仍以上面的按钮为例,我们制作按钮的单击响应函数。
1.在MESSAGE_MAP中添加响应函数:MESSAGE_MAP表中定义了消息响应函数,其格式为:消息名(ID,函数名),当我们用ClassWizard添加函数时,会自动添加在AFX_MSG_MAP括起的区间内,如:手工添加时不要添加到AFX_MSG_MAP区间内,以防ClassWizard不能正常工作,如:其中ON_BN_CLICKED是按钮单击消息。
2.在头文件中添加函数定义:用ClassWizard添加函数时,会在头文件的AFX_MSG区间内添加函数定义,如:我们模仿这种形式,只是把函数定义添加到AFX_MSG区间外就行了:3.编写消息响应函数:以上是把消息和函数关联起来了,具体在单击按钮后应做的工作在函数中完成:除了按钮的响应函数外,你还可以用上面获得的指针访问按钮,如:修改按钮的大小和位置:p_MyBtn[0]->MoveWindow(……);修改按钮文本:p_MyBtn[0]->SetWindowText(……);显示/隐藏按钮:p_MyBtn[0]->ShowWin dow(……);等等。
三、回收资源:由于动态控件对象是由new生成的,它不会被程序自动释放,所以需手工释放。
在控件不再使用时可以删除它,在对话框中的析构函数中销毁(析构函数没有手动添加):以上就是按钮控件动态生成的方法。
//////////////////////////////////////////////////////////////////////////////////////////////VC改变对话框按钮字体颜色和背景的解决方案(转载于:/wangguang246/blog/item/9c6e988a7b2de8769f2fb412.html)要想修改CButton类按钮背景颜色和文字颜色,必须利用自绘方法对按钮进行重新绘制。
这可以通过定义一个以CButton为基类的新按钮类来实现。
以下为具体的实现方法:方法一:加入一个新类,类名:CMyButton,基类:CButton。
在头文件MyButton.h 中加入以下变量和函数定义:private:int m_Style; //按钮形状(0-正常,1-当前,2-按下,3-锁定)BOOL b_InRect; //鼠标进入标志CString m_strText; //按钮文字COLORREF m_ForeColor; //文本颜色COLORREF m_BackColor; //背景色COLORREF m_LockForeColor; //锁定按钮的文字颜色CRect m_ButRect; //按钮尺寸CFont* p_Font; //字体void DrawButton(CDC *pDC); //画正常的按钮// 接口函数public:void SetText(CString str);void SetForeColor(COLORREF color); //设置文本颜色void SetBkColor(COLORREF color); //设置背景颜色void SetTextFont(int FontHight,LPCTSTR FontName); //设置字体在MyButton.cpp 的构造函数中初始化变量:CMyButton::CMyButton(){m_Style = 0; //按钮形状风格b_InRect = false; //鼠标进入标志m_strText = _T(""); //按钮文字(使用默认文字)m_ForeColor = RGB(0,0,0); //文字颜色(黑色)m_BackColor = RGB(243,243,243); //背景色(灰白色)m_LockForeColor = GetSysColor(COLOR_GRAYTEXT); //锁定按钮的文字颜色 p_Font = NULL; //字体指针}用ClassWizard添加下列消息函数:PreSubclassWindow();DrawItem();onMouse Move();OnLButtonDown();OnLButtonUp();在各函数内加入代码:void CMyButton::PreSubclassWindow(){ModifyStyle( 0, BS_OWNERDRAW ); //设置按钮属性为自画式CButton::PreSubclassWindow();PreSubclassWindow()在按钮创建前自动执行,所以我们可以在其中做一些初始工作。
这里我只做了一项工作,就是为按钮设置属性为“自绘”式,这样,用户在添加按钮后,就不需设置“Owner draw”属性了。
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){CDC *pDC = CDC::FromHandle( lpDrawItemStruct->hDC );m_ButRect = lpDrawItemStruct->rcItem; //获取按钮尺寸if( m_strText.IsEmpty() )GetWindowText( m_strText ); //获取按钮文本int nSavedDC = pDC->SaveDC();VERIFY( pDC );DrawButton( pDC ); //绘制按钮pDC->RestoreDC( nSavedDC );}DrawItem()函数是一个关键函数,按钮的绘制工作就在这里进行,它的作用相当于对话框中的OnPaint()函数和视图中的OnDraw()函数。
这里我做了三项工作:获取按钮尺寸、获取按钮文本、绘制按钮。
其中绘制工作在自定义函数DrawButton()中完成。
以下就是绘制过程:void CMyButton::DrawButton(CDC *pDC){//调整状态if( m_Style==3 ) m_Style = 0;if( GetStyle() & WS_DISABLED )m_Style = 3; //禁止状态//根据状态调整边框颜色和文字颜色COLORREF bColor, fColor; //bColor为边框颜色,fColor为文字颜色switch( m_Style ){case 0: bColor = RGB(192,192,192); fColor = m_ForeColor; break; //正常按钮case 1: bColor = RGB(255,255,255); fColor = m_ForeColor; break; //鼠标进入时按钮case 2: bColor = RGB(192,192,192); fColor = m_ForeColor; break; //按下的按钮case 3: bColor = m_BackColor; fColor = m_LockForeColor; break; //锁定的按钮}//绘制按钮背景CBrush Brush;Brush.CreateSolidBrush( m_BackColor ); //背景刷pDC->SelectObject( &Brush );CPen Pen;Pen.CreatePen(PS_SOLID, 1, bColor );pDC->SelectObject( &Pen );pDC->RoundRect(&m_ButRect,CPoint(5,5)); //画圆角矩形//绘制按钮按下时的边框if( m_Style!=2 )CRect Rect;Rect.SetRect( m_ButRect.left+2, m_ButRect.top+1, m_ButRect.right, m_ButRect.bottom ); pDC->DrawEdge( &Rect, BDR_RAISEDINNER, BF_RECT ); //画边框}//绘制按钮文字pDC->SetTextColor( fColor ); //画文字pDC->SetBkMode( TRANSPARENT );pDC->DrawText( m_strText, &m_ButRect, DT_SINGLELINE | DT_CENTER| DT_VCENTER | DT_END_ELLIPSIS);//绘制拥有焦点按钮的虚线框if( GetFocus()==this ){CRect Rect;Rect.SetRect( m_ButRect.left+3, m_ButRect.top+2, m_ButRect.right-3, m_ButRect.bottom-2 );pDC->DrawFocusRect( &Rect ); //画拥有焦点的虚线框}}变量m_Style 表征当前按钮状态,它的取值为:0-正常,1-当前,2-按下,3-锁定。