(一)、在头文件中定义消息的值
例:#define WM_自定义名字 WM_USER+1.
(二)、在该头文件中编写该消息响应函数原型的声明:
例:
//}}AFX_MSG
afx_msg void On自定义函数名(自定义形参);
DECLARE_MESSAGE_MAP()
注:定义消息函数可以不带参数。
(三)、在该类源文件中添加消息映射
BEGIN_MESSAGE_MAP(CChatDlg, CDialog)
//{{AFX_MSG_MAP(CChatDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_SEND, OnBtnSend)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_名字,On函数名)
END_MESSAGE_MAP()
(四)、该消息响应函数
void C类名::On函数名(形参)
{
}
介绍函数:CButtonST类应用
void CButtonST::SetTooltipText(CString* spText, BOOL bActivate) //文字输出
{
if (spText == NULL) return;
// Initialize ToolTip
InitToolTip();
// If there is no tooltip defined then add it
if (m_ToolTip.GetToolCount() == 0) // CToolTipCtrl m_ToolTip全局变量
{
CRect rectBtn;
GetClientRect(rectBtn);
m_ToolTip.AddTool(this, (LPCTSTR)*spText, rectBtn, 1);
}
// Set text for tooltip
m_ToolTip.UpdateTipText((LPCTSTR)*spText, this, 1);
m_ToolTip.Activate(bActivate);
} // End of SetTooltipText
void CButtonST::InitToolTip()
{
if (m_ToolTip.m_hWnd == NULL)
{
// Create ToolTip control
m_ToolTip.Create(this);
// Create inactive
m_ToolTip.Activate(FALSE);
}
} // End of InitToolTip
程序:
头文件:
CButtonST m_btn; 定义一CButtonST 对象
CString strName;
源文件:
strName="输入文字";
m_btn.SetTooltipText(&strName);
可以在OnInitDialog()函数中定义,也可以在其他函数中重新定义。
DDX_Control(pDX,IDC_BUTTON1,m_btn); //输出,DoDataExchange(CDataExchange* pDX)函数中
介绍函数:
void AFXAPI DDX_Control( CDataExchange* pDX, int nIDC, CWnd& rControl );
参数一:指向CDataExchange的指针,用于建立资料交换设备上下文;
参数二:控件IDC;
参数三:控件变量。
重写SetIcon()函数:
头文件:
void SetIcon(int nIconInId, int nIconOutId = NULL); //带参数的成员函数
源文件:
void CButtonST::SetIcon(int nIconInId, int nIconOutId)
{
HICON hIconIn; //定义HICON 变量,用于保存图片
HICON hIconOut;
HINSTANCE hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nIconInId), RT_GROUP_ICON);
//鼠标点击时获得应用资源句柄
hIconIn = (HICON)::LoadImage(hInstResource/*AfxGetApp()->m_hInstance*/, MAKEINTRESOURCE(nIconInId), IMAGE_ICON, 0, 0, 0);
// 鼠标移开时加载图片
hIconOut = (nIconOutId == NULL) ? NULL : (HICON)::LoadImage(hInstResource/*AfxGetApp()->m_hInstance*/, MAKEINTRESOURCE(nIconOutId), IMAGE_ICON, 0, 0, 0);
SetIcon(hIconIn, hIconOut); //调用
}
void CButtonST::SetIcon(HICON hIconIn, HICON hIconOut)
{
// Note: the following two lines MUST be here! even if
// BoundChecker says they are unnecessary!
if (m_hIconIn != NULL) ::DestroyIcon(m_hIconIn); //判定是否与图片相关联
if (m_hIconOut != NULL) ::DestroyIcon(m_hIconOut);
// Set icon when the mouse is IN the button
m_hIconIn = hIconIn;
// Set icon when the mouse is OUT the button
m_hIconOut = (hIconOut == NULL) ? m_hIconIn : hIconOut;
ICONINFO ii; //ICONINFO 结构体
// Get icon dimension
ZeroMemory(&ii, sizeof(ICONINFO)); //ii内存设0
::GetIconInfo(m_hIconIn, &ii); //设置自定义图标
m_cxIcon = (BYTE)(ii.xHotspot * 2);
m_cyIcon = (BYTE)(ii.yHotspot * 2);
::DeleteObject(ii.hbmMask);
::DeleteObject(ii.hbmColor);
RedrawWindow();
} // End of SetIcon
程序流程:
a)添加头文件
CButton m_btn;定义一对象
b)在新建框架类中初始化
BOOL CMy5Dlg::OnInitDialog()
{
m_btn.SetIcon(IDI_ICON1,IDI_ICON2); //设置两幅图标
}
c)鼠标点击交换图片
void CMy5Dlg::DoDataExchange(CDataExchange* pDX)
{
DDX_Control(pDX,IDC_BUTTON1,m_btn);
}
#include <assert.h> //设定插入点
#include <ctype.h>//字符处理
#include <errno.h>//定义错误码
#include <float.h>//浮点数处理
#include <fstream.h>//文件输入/输出
#include <iomanip.h>//参数化输入/输出
#include <iostream.h> //数据流输入/输出
#include <limits.h> //定义各种数据类型最值常量
#include <locale.h> //定义本地化函数
#include <math.h> //定义数学函数
#include <stdio.h> //定义输入/输出函数
#include <stdlib.h> //定义杂项函数及内存分配函数
#include <string.h> //字符串处理
#include <strstrea.h> //基于数组的输入/输出
#include <time.h> //定义关于时间的函数
#include <wchar.h> //宽字符处理及输入/输出
#include <wctype.h> //宽字符分类
标准 C++ (同上的不再注释)
#include <algorithm> //STL 通用算法
#include <bitset> //STL 位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex> //复数类
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque> //STL 双端队列容器
#include <exception> //异常处理类
#include <fstream>
目的:为了使用户定义的数据类型如同一般数据类型一样使用。
功能:对对象进行初始化,有若干种方法。
特点:1、无返回值说明;2、不能继承;3、可以有缺省参数;4、不能取地址,构造时自动给对象分配栈中内存,析构时回收;
5、自动调用构造函数。
构造函数是类的一个特殊成员函数,其函数名同类名一样。C++通过构造函数可以正确地初始化对象。构造函数不能被显式调用,不能使
虚函数。
例: class queue {
int q[100]; //默认为private
int sloc,rloc;
public:
queue();
void qput(int i);
};
queue ::queue () //隐式调用
{
sloc=rloc=0;
}
int queue ::qput (int i){}
main()
{
queue a,b;
a.qput (10);
b.qput (20);
}
参数化的构造函数:
queue ::queue (int vx,int vy){} };
main()
{
queue a(10,20);
}
缺省参数的构造函数:特殊情况下需要传递参数,一般都是用缺省参数。
单个参数:queue ::queue (int i=16) {} };
main()
{
queue a;
}
多个参数:queue ::queue (int vx=0,int vy=0) {}
缺省参数还可用于一般成员函数。使用时应注意避免二义性。
多构造函数:
public:
queue ( );
queue (int );
queue (int,char );
};
main()
{
queue a;
queue b(1);
queue c(1,'c'); //避免二义性
}
拷贝构造函数:
1、系统产生:
queue ::queue (int vx,int vy){} };
main() { queue a(b) ; }
2、自定义:
queue ::queue (const queue &p){} };
main() { queue }
总结:构造函数的作用是对对象本身做初始化工作,也就是给用户提供初始化类中成员变量的一种方式。
如果一个类中没有定义任何的构造函数,那C++编辑器将在某些情况下提供一个默认的构造函数(不带参数),3种情况:
1)、类有虚拟成员函数或虚拟继承父类(虚拟基类);
2)、类的基类有构造函数;
3)、类中的所有非静态饿对象数据成员,它们所属的类中有构造函数。
构造函数的目的是为了初始化对象,因此一个构造函数至少应该
使得对象处于明确定义的状态。
例://class string
string () {s=new char[80];len=80;}
string (int n) {s=new char[n];len=n;}
}
string::stringprintf() { cout<< s <<endl;}
定义对象:
string x,y(80);
x.print();
y.print();
此时,x和y调用的print()函数结构未定义,因为在构造函数中只对字符数组分配了内存,却未对分配的内存进行初始化。
我们可以通过修改带默认参数值的构造函数来改进:
string (int n=80) {s=new char[n];s[0]='\0';len=n;}
用默认参数的形式来代替函数重载的形式。
注意点:
1)构造函数应该使对象处于明确定义的状态;
2)保持物理状态的一致性:对数据成员的定义保持一致,在所有函数中只能使用一种定义。
3)类不变性:可以将不变性作为程序代码的注释,//len=strlen(s);
4)动态内存的一致性:接口一致性
void assign (char* str) { strcpy(s,str);}
void concat (string& a) {s=new char[len+1];strcpy(s,a.s);}
两函数的表现行为存在不一致性:前者内存不再分配,而后者一直在分配。我们应只使用一种以保持一致性。
5)内存泄露:concat函数中每拷贝一次,s就重新分配一次,s被新的指针值覆盖,而前一指针值被抛弃,产生内存垃圾。
因此concat函数必须保证旧的数组一定要被删除,对于每一个new,就必须有一个delete操作,且delete语句只能被增加在
新的字符串创建之后。
void concat (string& a) {new_s=new char[len+1];strcpy(s,a.s); delete[]s;s=new_s;}
const char*类型是指向常量的指针,不能修改其指向的内容,当可以修改其指向的地址。
例1:
char ch[5]="lisi"; //定义一字符串ch[],并赋值
const char* pStr=ch; //定义一常量指针pStr,将ch赋给pStr
注:ch[]定义时须对其进行赋值,字符长度为5,最后一位为"\0"表示结束。
在对pStr赋值时相当于将ch[]的首地址给pStr,因为const char*类型得指针变量只可以修改其本身的值,即变量保存的内存地址。
因此该变量的值可以改变,但其指向的地址的内容不能改变。
如:*pStr="jiliang"; //错误的,因为其直接改变了内容,所以无法将"jiliang"赋值给ch[];
pStr="jiliang"; //正确的,因为其改变的是地址值,即pStr保存的是="jiliang"的首地址。
我们无法通过pStr来修改其指向地址的内容,但可以通过ch[]来修改内容。
使用:利用指针类型来传递参数时,可以定义为const char*类型,保持内容的一致性。
char* const类型是一个指针常量,可以修改地址指向的内容,但不可以修改其地址值。
例2:
char ch[5]="lisi"; //定义一字符串ch[],并赋值
const char* pStr=ch; //定义一指针常量pStr,将ch赋给pStr
注:对于指针常量,必须在定义时对其赋值。指针常量表示指针本身是常量,即地址值为常量。
如:pStr="jiliang"; //错误的,因为该赋值将新的字符串地址赋值给指针常量,这是不允许的;
*pStr="jiliang";//正确的,可以对指针常量指向的地址修改其内容。
小结:
const char*类型的指针其指向的内容是常量,不能修改,但其地址值可以修改;
char* const类型的指针其地址值是常量,不能修改,但其指向的内容可以修改。
参考:<<VC++深入浅出>>孙鑫