Archive for 六月, 2007

Visual C++ MFC 中常用宏的含义

Posted by 机器人 on 12th 六月 2007 in c/c++

AND_CATCHAND_CATCH

AND_CATCH(exception_class,exception _object_point_name)

说明:

定义一个代码块,它用于获取废除当前TRY块中的附加异常类型。使用CATCH宏以获得一个异常类型,然后使用AND_CATCH宏获得随后的异常处理代 码可以访问异常对象(若合适的话)已得到关于异常的特别原因的更多消息。在AND_CATCH块中调用THROW_LAST宏以便把处理过程移到下个外部 异常框架。AND_CATCH可标记CATCH或AND_CATCH块的末尾。

注释:

AND_CATCH块被定义成为一个C++作用域(由花括号来描述)。若用户在此作用域定义变量,那么记住他们只在此作用域中可以访问。他也用于exception_object_pointer_name变量。

ASSERT

ASSERT(booleanExpression)

说明:

计算变量的值。如果结构的值为0,那么此宏便打印一个诊断消息并且成讯运行失败。如果条件为非0,那么什么也不做。 诊断消息的形式为: assertion failed in file in line 其中name是元文件名,num是源文件中运行失败的中断号。 在Release版中,ASSERT不计算表达式的值也就不中断程序。如果必须计算此表达式的值且不管环境如何那么用VERIFY代替ASSERT。

注释:

ASSERT只能在Debug版中用

ASSERT_VAILD

ASSERT_VAILD(pObject)

说明:

用于检测关于对象的内部状态的有效性。ASSERT_VALID调用此对象的AssertValid成员函数(把它们作为自己的变量来传递)。在 Release版中ASSERT_VALID什么也不做。在DEBUG版中,他检查指针,以不同于NULL的方式进行检查,并调用对象自己的 AssertValid成员函数。如果这些检测中有任何一个失败的话,那么他会以与ASSERT相同的方法显示一个警告的消息。

注释:

此函数只在DEBUG版中有效。

BEGIN_MESSAGE_MAP

BEGIN_MESSAGE_MAP(the class,baseclass)

说明:

使用BEGIN_MESSAGE_MAP开始用户消息映射的定义。在定义用户类函数的工具(.cpp)文件中,以BEGIN_MESSAGE_MAP宏开始消息映射,然后为每个消息处理函数增加宏项,接着以END_MESSAGE_MAP宏完成消息映射。

CATCH

CATCH(exception_class,exception_object_pointer_name)

说明:

使用此用定义一个代码块,此代码用来获取当前TRY块中都一个异常类型。异常处理代码可以访问异常对象,如何合适的话,就会得到关于异常的特殊原因的更多 消息。调用THROW_LAST宏以把处理过程一下一个外部异常框架,如果exception-class是类CExceptioon,那么会获取所有异 常类型。用户可以使用CObject::IsKindOf成员函数以确定那个特别异常被排除。一种获取异常的最好方式是使用顺序的AND_CATCH语 句,每个带一个不同的异常类型。此异常类型的指针由宏定义,用户不必定义。

注释:

此CATCH块被定义作一个C++范围(由花括号描述)。如用户在此范围定义变量,那么它们只在吃范围内可以访问。他还可以用于异常对象的指针名。

DEBUG_NEW

#define new DEBUG_NEW

说明:

帮助查找内存错误。用户在程序中使用DEBUG_NEW,用户通常使用new运算符来从堆上分配。在Debug模式下(但定义了一个DEBUG符号), DEBUG_NEW为它分配的每个对象记录文件名和行号。然后,在用户使用CMemoryState::DumpAllObjectSince成员函数 时,每个以DEBUG_NEW分配的对象分配的地方显示出文件名和行号。 为了使用DEBUG_NEW,应在用户的资源文件中插入以下指令: #define new DEBUG_NEW 一旦用户插入本指令,预处理程序将在使用new的地方插入DEBUG_NEW,而MFC作其余的工作。但用户编译自己的程序的一个发行版时, DEBUG_NEW便进行简单的new操作,而且不产生文件名和行号消息。

DECLARE_DYNAMIC

DECLARE_DYNAMIC(class_name)

说明:

但从CObject派生一个类时,此宏增加关于一个对象类的访问运行时间功能。把DECLARE_DYNAMIC宏加入类的头文件中,然后在全部需要访问 词类对象的.CPP文件中都包含此模块。如果像所描述那样使用DELCARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,那么用户便可使用 RUNTIME_CLASS宏和CObject::IsKindOf函数以在运行时间决定对象类。如果DECLARE_DYNAMIC包含在类定义中,那 么IMPLEMETN_DYNAMIC必须包含在类工具中。

DECLARE_DYNCREATE

DECLARE_DYNCREATE(class_name)

说明:

使用DECLARE_DYNCRETE宏以便允许CObject派生类的对象在运行时刻自动建立。主机使用此功能自动建立新对象,例如,但它在串行化过程 中从磁盘读一个对象时,文件及视图和框架窗应该支持动态建立,因为框架需要自动建立它。把DECLARE_DYNCREATE宏加入类的.H文件中,然后 在全部需要访问此类对象的.CPP文件中包含这一模式。如果DECLARE_DYNCREATE包含在类定义中,那么 IMPLEMENT_DYNCREATE必须包含在类工具中。

DECLARE_MESSAGE_MAP

DECLARE_MESSAGE_MAP()

说明:

用户程序中的每个CCmdTarget派生类必须提供消息映射以处理消息。在类定义的末尾使用DECLARE_MESSAGE_MAP宏。接着,在定义类 成员函数的.CPP文件中,使用BEGIN_MESSAGE_MAP宏,每个用户消息处理函数的宏项下面的列表以及END_MESSAGE_MAP宏。

注释:

如果在DECLARE_MESSAGE_MAP之后定义任何一个成员,那么必须为他们指定一个新存取类型(公共的,私有的,保护的)。

DECLARE_SERIAL

DECLARE_SERIAL(class_name)

说明:

DECLARE_SERIAL为一个可以串行化的CObject派生类产生必要的C++标题代码。串行化是把某个对象的内容从一个文件读出和写入一文件。 在.H文件中使用DECLARE_SERIAL宏,接着在需要访问此类对象的全部.CPP文件中包含此文件。如果DECLARE_SERIAL包含在类定 义中,那么IMPLEMENT_SERIAL必须包含在类工具中。DECLARE_SERIAL宏包含全部DECLARE_DYNAMIC, IMPLEMENT_DYCREATE的功能。

END_CATCH

END_CATCH

说明:

标识最后的CATCH或AND_CATCH块的末尾。

END_MESSAGE_MAP

END_MESSAGE_MAP

说明:

使用END_MESSAGE_MAP宏结束用户的消息映射定义

IMPLEMENT_DYNAMIC

IMPLEMENT_DYNAMIC(class_name,base_class_name)

说明:

通过运行时在串行结构中为动态CObject派生类访问类名和位置来产生必要的C++代码。在.CPP文件中使用IMPLEMENT_DYNAMIC宏,接着一次链接结果对象代码

IMPLEMENT_DYNCREATE

IMPLEMENT_DYNCREATE(class_name,base_class_name)

说明:

通过DECLARE_DYNCREATE宏来使用IMPLEMENT_DYNCREATE宏,以允许CObject派生类对象在运行时自动建立。主机使用 此功能自动建立对象,例如,但它在串行化过程中从磁盘读去一个对象时,他在类工具里加入IMPLEMENT_DYNCREATE宏。若用户使用 DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏,那么接着使用RUNTIME_CLASS宏和CObject:: IsKindOf成员函数以在运行时确定对象类。若declare_dyncreate包含在定义中,那么IMPLEMENT_DYNCREATE必须包 含在类工具中。

IMPLEMENT_SERIAL

IMPLEMENT_SERIAL(class_name,base_class_name,wSchema)

说明:

通过运行时在串行结构中动态CObject派生类访问类名和位置来建立必要的C++代码。在.CPP文件中使用IMPLEMENT_SERIAL宏,然后一次链接结果对象代码。

ON_COMMAND

ON_COMMAND(id,memberFxn)

说明:

此宏通过ClassWizard或手工插入一个消息映射。它表明那个函数将从一个命令用户接口(例如一个菜单项或toolbar按钮)处理一个命令消息。 当一个命令对象通过指定的ID接受到一个Windows WM_COMMAND消息时,ON_COMMAND将调用成员函数memberFxn处理此消息。在用户的消息映射中,对于每个菜单或加速器命令(必须被 映射到一个消息处理函数)应该确实有一个ON_COMMAND宏语句。

ON_CONTROL

ON_CONTROL(wNotifyCode,id,memberFxn)

说明:

表明哪个函数将处理一个常规控制表示消息。控制标识消息是那些从一个控制夫发送到母窗口的消息。

ON_MESSAGE

ON_MESSAGE(message,memberFxn)

说明:

指明哪个函数将处理一用户定义消息。用户定义消息通常定义在WM_USER到0x7FF范围内。用户定义消息是那些不是标准Windows WM_MESSAGE消息的任何消息。在用户的消息映射中,每个必须被映射到一个消息处理函数。用户定义消息应该有一个ON_MESSAGE宏语句。

ON_REGISTERED_MESSAGE

ON_REGISTERED_MESSAGE(nmessageVarible,memberFxn)

说明:

Windows的RegisterWindowsMesage函数用于定义一个新窗口消息,此消息保证在整个系统中是唯一的。此宏表明哪个函数处理已注册消息。变量nMessageViable应以NEAR修饰符来定义。

ON_UPDATE_COMMAND_UI

ON_UPDATE_COMMAND_UI(id,memberFxn)

说明:

此宏通常通过ClassWizard被插入一个消息映射,以指明哪个函数将处理一个用户接口个更改命令消息。在用户的消息映射中,每个用户接口更改命令(比讯被映射到一个消息处理函数)应该有一个ON_UPDATE_COMMAND_UI宏语句。

ON_VBXEVENT

ON_VBXEVENT(wNotifyCode,memberFxn)

说明:

此宏通常通过ClassWizard被插入一个消息映射,以指明哪个函数将处理一个来自VBX控制的消息。在用户的消息映射中每个被映射到一消息处理函数的VBX控制消息应该有一个宏语句。

RUNTIME_CLASS

RUNTIME_CLASS(class_name)

说明:

使用此宏从c++类民众获取运行时类结构。RUNTIME_CLASS为由class_name指定的类返回一个指针到CRuntimeClass结构。 只有以DECLARE_DYNAMIC,DECLARE_DYNCREATE或DECLARE_SERIAL定义的CObject派生类才返回到一个 CRuntimeClass结构的指针。

THROW

THROW(exception_object_pointer)

说明:

派出指定的异常。THROW中断程序的运行,把控制传递给用户程序中的相关的CATCH块。如果用户没有提供CATCH块,那么控制被传递到一个MFC模块,他打印出一个错误并终止运行。

THROW_LAST

THROW_LAST()

说明:

此宏允许用户派出一个局部建立的异常。如果用户试图排除一个刚发现的异常,那么一般此异常将溢出并被删除。使用THROW_LAST,此异常被直接传送到下一个CATCH处理程序。

TRACE

TRACE(exp)

说明:

把一个格式化字符串送到转储设备,例如,文件或调试监视器,而提供与printf相似的功能。同MS_DOS下C程序的printf一样,TRACE宏是 一个在程序运行时跟踪变量值的方便形式。在DEBUG环境中,TRACE宏输出到afxDump。在Release版中他不做任何工作。

注释:

此宏只在MFC的DEBUG版中有效。

TRACE0

TRACE0(exp)

说明:

与TRACE相似,但他把跟踪字符串放在代码段中,而不是DGROUP,因此使用少的DGROUP空间。TRACE0是一组跟踪宏的一个变体,这些宏可用 于调试输出。这一组包括TRACE0,TRACE1,TRACE2和TRACE3,这些宏不同在于所取参数的数目不同。TRACE0只取一个格式化字符串 并可用于简单文本消息。TRACE1取一格式化字符串加上一个变量——一个将转储的变量。同样,TRACE2,TRACE3分别取2个或3个参数(在格式 化字符串之后)。如果用户以便以了应用程序的发行版,那么它只把数据转储到afxDump。

注释:

此宏只在MFC的DEBUG中有效。

TRACE1

TRACE1(exp,param1)

说明:

参见TRACE0

TRACE2

TRACE2(exp,param1,param2)

说明:

参见TRACE0

TRACE3

TRACE3(exp,param1,param2,param3)

说明:

TRY

TRY

说明:

使用此宏建立一TRY块。一个TRY识别一个可排除异常的代码块。这些异常在随后的CATCH和AND_CATCH块处理。传递是允许的:异常可以传递一个外部TRY块,或者忽略它们或者使用THROW_LAST宏。

VERIFY

VERIFY(booleanExpression)

说明:

在MFC的DEBUG版中,VERIFY宏计算它的变量值。 如果结果为0,那么宏打印一个诊断消息并中止程序。如果条件不为0,那么什么工作也不作。 诊断有如下形式: assertion failed in file in line 其中name是源文件的名字,num是在源文件中失败的中止行号。在MFC的Release版中,VERIFY计算表达式值但不打印或中止程序。例如:如 果表达式是个函数调用,那么调用成功。

ODBC数据库连接常用步骤加演示代码(VC++学习笔记)

Posted by 机器人 on 10th 六月 2007 in c/c++

ODBC数据操作步骤:

1.设置一个成员变量,用来接收数据源:

CDatabase m_database;

2.建立记录集:

CPswdSet* m_recordset=new CPswdSet(&m_database);

3.发送SQL语句,返回从数据库里里得到的记录集.

 

strSQL.Format("select * from password where PASSWORD='%s'",m_password);

CDatabase类操作步骤:

1.       构造一个CDatabase对象:

 

CDatabase m_db; //在文档类中嵌入一个CDatabase对象

2.       调用Open成员函数,Open函数负责与数据源的连接.


virtual BOOL Open(
   LPCTSTR lpszDSN,
   BOOL bExclusive = FALSE,
   BOOL bReadOnly = FALSE,
   LPCTSTR lpszConnect = _T("ODBC;"),
   BOOL bUseCursorLib = TRUE
);
//连接一个名为Stutdent的数据源
m_db.Open(“Student”);
//在连接数据源的同时指定了用户账号和口令.
m_db.Open(NULL,FALSE,FASLE,”ODBC;DSN=Stutent;UID=hqlong;PWD=123456);
//弹出一个函数源对话框
m_db.Open(NULL);

3.       使用Execute()函数执行SQL语句.

 

m_db->Exeucte(“SELECT * INTO StudentArchieve FROM Student”);

执行一条插入语句:

 

strSQL.Format("insert into person values(%d,'%s','%s','%s','%s','%s','%s','%s','%s','%s')"
	,i,m_name,m_sex,m_relation,m_hometelephone,m_handphone, m_address,m_workplace,m_email,m_oicq);
m_database.ExecuteSQL(strSQL);

常用函数:

long GetRecordCount( ) const;

Return Value

返回记录集中的记录数,记录集中没有记录,则返回0,如果记录数不能决定,则返回-1

 

//IDC_RADIO1,IDC_RADIO2之间的IDC_RADIO1单选按键选中

主窗口初始化函数:

 


BOOL CMainDlg::OnInitDialog(){
       CDialog::OnInitDialog();
	  // TODO: Add extra initialization here
       //默认为“精确查询”按钮被选中
       CDialog::CheckRadioButton(IDC_RADIO1,IDC_RADIO2,IDC_RADIO1);
       //默认“姓名”项被选中
       m_ctrlfield.SetCurSel(0);
       //让窗口出现时居中
       CenterWindow();
       //为标题栏加图标
       m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
       this->SetIcon(m_hIcon,TRUE);
       //设定列的颜色
       m_ctrlperson.SetTextColor(RGB(100,0,100));
       m_ctrlperson.SetTextBkColor(RGB(240,247,233));
       //确定列名
       m_ctrlperson.InsertColumn(0,"序号");
       m_ctrlperson.InsertColumn(1,"姓名");
       m_ctrlperson.InsertColumn(2,"性别");
       m_ctrlperson.InsertColumn(3,"关系");
       m_ctrlperson.InsertColumn(4,"联系电话");
       m_ctrlperson.InsertColumn(5,"手机号码");
       m_ctrlperson.InsertColumn(6,"家庭住址");
       m_ctrlperson.InsertColumn(7,"工作单位");
       m_ctrlperson.InsertColumn(8,"E_mail地址");
       m_ctrlperson.InsertColumn(9,"OICQ号码");
       //重新分配列宽
       m_ctrlperson.SetColumnWidth(0,40);
       m_ctrlperson.SetColumnWidth(1,60);
       m_ctrlperson.SetColumnWidth(2,40);
       m_ctrlperson.SetColumnWidth(3,80);
       m_ctrlperson.SetColumnWidth(4,100);
       m_ctrlperson.SetColumnWidth(5,100);
       m_ctrlperson.SetColumnWidth(6,150);
       m_ctrlperson.SetColumnWidth(7,150);
       m_ctrlperson.SetColumnWidth(8,150);
       m_ctrlperson.SetColumnWidth(9,80);
       //扩展风格
       m_ctrlperson.SetExtendedStyle(LVS_EX_FULLROWSELECT| LVS_EX_GRIDLINES);//|LVS_SHOWSELALWAYS);
       //查找记录并按ID升序排列
       m_query.Format("select * from person order by ID ASC");
       RefreshData();
       //为操作区增加工具条提示
       m_addTip.Create(this);
       CButton* m_radio_add=(CButton*)GetDlgItem(IDC_RADIO_ADD);
       m_addTip.AddTool(m_radio_add,"单击此按钮,可以为通讯录增加记录。");
       m_modTip.Create(this);
       CButton* m_radio_mod=(CButton*)GetDlgItem(IDC_RADIO_MOD);
       m_modTip.AddTool(m_radio_mod,"先选取列表框中要修改的记录,再单击此按钮就可以修改相应的记录。");
       m_delTip.Create(this);
       CButton* m_radio_del=(CButton*)GetDlgItem(IDC_RADIO_DEL);
       m_delTip.AddTool(m_radio_del,"先选取列表框中要删除的记录,再单击此按钮就可以彻底将此记录删除。");
       m_searchTip.Create(this);
       CButton* m_radio_search=(CButton*)GetDlgItem(IDC_RADIO_SEARCH);
       m_searchTip.AddTool(m_radio_search,"单击此按钮可以查到你想要的记录。");
       //使对话框居中显示
       CRect dlgrect;
       GetWindowRect(&dlgrect);
       CRect desktoprect;
       GetDesktopWindow()->GetWindowRect(&desktoprect);
       CRect rect1,rect2;
       GetDlgItem(IDC_SEARCH_STATIC)->GetWindowRect(&rect1);
       GetDlgItem(IDC_FLAG_STATIC)->GetWindowRect(&rect2);
       m_nReduceHeight=rect1.Height()+(rect1.top-rect2.bottom)/2;//收缩后窗体的高度
       dlgrect.bottom-=(rect1.Height()-(rect1.top-rect2.bottom)/2);
       MoveWindow(&dlgrect);//移动对话框到新的坐标位置.
       m_bflag=false;
       m_bsearchflag=true;
       return TRUE;  // return TRUE unless you set the focus to a control

                     // EXCEPTION: OCX Property Pages should return FALSE

}

刷新记录处理函数.

 

void CMainDlg::RefreshData()
{
	//首先确保数据库打开
	if(!m_database.IsOpen())
	{
		//m_database.Open(_T("addresslist"));
	}
	//对列表控件的内容更新,清空原来的内容
	m_ctrlperson.DeleteAllItems();
	//创建记录集
	CPersonSet m_personset(&m_database);
	m_personset.Open(AFX_DB_USE_DEFAULT_TYPE,m_query);
	CDBVariant varValue;
	char buf[20];
	//用来记录当前记录的序号
	int i=0;
	//如果表中有记录,打开后将游标定在第一位,使记录集中的第一条记录成为当前记录
	if(m_personset.GetRecordCount()!=0)	m_personset.MoveFirst();

	while(!m_personset.IsEOF())
	{
		int temp=0;
		//对整型数字的处理
		m_personset.GetFieldValue(temp,varValue);
		sprintf(buf,"%d",varValue.m_lVal);
		m_ctrlperson.InsertItem(i,buf);
		//对字符串显示处理
		//m_personset.GetFieldValue(0,varValue);
		//m_ctrlperson.SetItemText(i,0,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(1,varValue);
		m_ctrlperson.SetItemText(i,1,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(2,varValue);
		m_ctrlperson.SetItemText(i,2,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(3,varValue);
		m_ctrlperson.SetItemText(i,3,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(4,varValue);
		m_ctrlperson.SetItemText(i,4,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(5,varValue);
		m_ctrlperson.SetItemText(i,5,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(6,varValue);
		m_ctrlperson.SetItemText(i,6,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(7,varValue);
		m_ctrlperson.SetItemText(i,7,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(8,varValue);
		m_ctrlperson.SetItemText(i,8,varValue.m_pstring->GetBuffer(1));

		m_personset.GetFieldValue(9,varValue);
		m_ctrlperson.SetItemText(i,9,varValue.m_pstring->GetBuffer(1));
		m_personset.MoveNext();
		i++;
	}
	//在标题栏中显示共有记录条数
	int counts=m_personset.GetRecordCount();
	CString str;
	str.Format("通讯录 V1.0 试用版     目前共有记录数: %d",counts);
	this->SetWindowText(str);
}

修改记录处理函数:

 

void CMainDlg::OnRadioMod()
{
	// TODO: Add your control notification handler code here
	m_database.Close();//本对话框断开与数据库的连接
	CModifyDlg dlg;
	dlg.m_database.Open(_T("addresslist"));
	int i=m_ctrlperson.GetSelectionMark();
	CString strSQL;
	int id=atoi(m_ctrlperson.GetItemText(i,0));
	CPersonSet m_recordset;
	CDBVariant varValue;
	if(i==-1)
	{
		MessageBox("请选择一条要修改的记录!","提示",MB_OK|MB_ICONINFORMATION);
	}
	else
	{
		int temp=0;
		strSQL.Format("select * from person where ID=%d",id);
		m_recordset.Open(AFX_DB_USE_DEFAULT_TYPE,strSQL);

		m_recordset.GetFieldValue(temp,varValue);
		dlg.m_modid=varValue.m_lVal;

		m_recordset.GetFieldValue(1,varValue);
		dlg.m_modname=varValue.m_pstring->GetBuffer(1);

		m_recordset.GetFieldValue(2,varValue);
		dlg.m_modsex=varValue.m_pstring->GetBuffer(1);

		m_recordset.GetFieldValue(3,varValue);
		dlg.m_modrelation=varValue.m_pstring->GetBuffer(1);

		m_recordset.GetFieldValue(4,varValue);
		dlg.m_modtelephone=varValue.m_pstring->GetBuffer(1);

		m_recordset.GetFieldValue(5,varValue);
		dlg.m_modhandphone=varValue.m_pstring->GetBuffer(1);

		m_recordset.GetFieldValue(6,varValue);
		dlg.m_modaddress=varValue.m_pstring->GetBuffer(1);

		m_recordset.GetFieldValue(7,varValue);
		dlg.m_modworkplace=varValue.m_pstring->GetBuffer(1);

		m_recordset.GetFieldValue(8,varValue);
		dlg.m_modemail=varValue.m_pstring->GetBuffer(1);

		m_recordset.GetFieldValue(9,varValue);
		dlg.m_modoicq=varValue.m_pstring->GetBuffer(1);
		m_database.Close();//此处不能断开与数据库的连接
		dlg.DoModal();
		RefreshData();
	}
}

2007-5-10 机器人 于 北京

怎么在对话框中载入指定的菜单项

Posted by 机器人 on 10th 六月 2007 in c/c++

 

BOOL CTxtDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO: Add extra initialization here
	CMenu *pMenu = new CMenu;
	BOOL ret = pMenu->LoadMenu(菜单ID);
	SetMenu(pMenu);
	return TRUE;  // return TRUE unless you set the focus to a control
   // EXCEPTION: OCX Property Pages should return FALSE
}

 

2007-6-10 机器人于北京

VC++编程小技巧20例

Posted by 机器人 on 10th 六月 2007 in c/c++

一、打开CD-ROM

mciSendString("Set cdAudio door open wait",NULL,0,NULL);

二、关闭CD_ROM

mciSendString("Set cdAudio door closed wait",NULL,0,NULL);

三、关闭计算机

 

OSVERSIONINFO OsVersionInfo; //包含操作系统版本信息的数据结构
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&OsVersionInfo); //获取操作系统版本信息
if(OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
    //Windows98,调用ExitWindowsEx()函数重新启动计算机
    DWORD dwReserved;
    ExitWindowsEx(EWX_REBOOT,dwReserved); //可以改变第一个参数,实现注销用户、
    //关机、关闭电源等操作
    // 退出前的一些处理程序
}

四、重启计算机

 


typedef int (CALLBACK *SHUTDOWNDLG)(int); //显示关机对话框函数的指针
HINSTANCE hInst = LoadLibrary("shell32.dll"); //装入shell32.dll
SHUTDOWNDLG ShutDownDialog; //指向shell32.dll库中显示关机对话框函数的指针
if(hInst != NULL)
{
    //获得函数的地址并调用之
    ShutDownDialog = (SHUTDOWNDLG)GetProcAddress(hInst,(LPSTR)60);
    (*ShutDownDialog)(0);
}

五、枚举所有字体

 

LOGFONT lf;
lf.lfCharSet = DEFAULT_CHARSET; // Initialize the LOGFONT structure
strcpy(lf.lfFaceName,"");
CClientDC dc (this);

//Enumerate the font families
::EnumFontFamiliesEx((HDC) dc,&lf,
(FONTENUMPROC) EnumFontFamProc,(LPARAM) this,0);

//枚举函数
int CALLBACK EnumFontFamProc(LPENUMLOGFONT lpelf,LPNEWTEXTMETRIC lpntm,DWORD nFontType,long lparam)
{
    // Create a pointer to the dialog window
    CDay7Dlg* pWnd = (CDay7Dlg*) lparam;
    // add the font name to the list box

    pWnd ->m_ctlFontList.AddString(lpelf ->elfLogFont.lfFaceName);

    // Return 1 to continue font enumeration
    return 1;
}

其中m_ctlFontList是一个列表控件变量

六、一次只运行一个程序实例,如果已运行则退出

 


if( FindWindow(NULL,"程序标题")) exit(0);

七、得到当前鼠标所在位置

 

CPoint pt;
GetCursorPos(&pt); //得到位置

八、上下文菜单事件触发事件:OnContextMenu事件

九、显示和隐藏程序菜单

 

CWnd *pWnd=AfxGetMainWnd();
if(b_m) //隐藏菜单
{
    pWnd->SetMenu(NULL);
    pWnd->DrawMenuBar();
    b_m=false;
}
else
{
    CMenu menu;
    menu.LoadMenu(IDR_MAINFRAME); ////显示菜单 也可改变菜单项
    pWnd->SetMenu(&menu);
    pWnd->DrawMenuBar();
    b_m=true;
    menu.Detach();
}

十、获取可执行文件的图标

 

HICON hIcon=::ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0);
if (hIcon &&hIcon!=(HICON)-1)
{
    pDC->DrawIcon(10,10,hIcon);
}
DestroyIcon(hIcon);

 

 

十一、窗口自动靠边程序演示

 

BOOL AdjustPos(CRect* lpRect)
{
    //自动靠边
    int iSX=GetSystemMetrics(SM_CXFULLSCREEN);
    int iSY=GetSystemMetrics(SM_CYFULLSCREEN);

    RECT rWorkArea;
    BOOL bResult = SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &rWorkArea, 0); 

    CRect rcWA;
    if(!bResult)
    {
        //如果调用不成功就利用GetSystemMetrics获取屏幕面积
		rcWA=CRect(0,0,iSX,iSY);
    }
    else
		rcWA=rWorkArea;

    int iX=lpRect->left;
    int iY=lpRect->top;
    if(iX < rcWA.left + DETASTEP && iX!=rcWA.left)
    {
        //调整左
		//pWnd->SetWindowPos(NULL,rcWA.left,iY,0,0,SWP_NOSIZE);
		lpRect->OffsetRect(rcWA.left-iX,0);
		AdjustPos(lpRect);
		return TRUE;
    }
    if(iY < rcWA.top + DETASTEP && iY!=rcWA.top)
    {
		//调整上
		//pWnd->SetWindowPos(NULL ,iX,rcWA.top,0,0,SWP_NOSIZE);
		lpRect->OffsetRect(0,rcWA.top-iY);
		AdjustPos(lpRect);
		return TRUE;
    }
    if(iX + lpRect->Width() > rcWA.right - DETASTEP && iX !=rcWA.right-lpRect->Width())
    {
		//调整右
		//pWnd->SetWindowPos(NULL ,rcWA.right-rcW.Width(),iY,0,0,SWP_NOSIZE);
		lpRect->OffsetRect(rcWA.right-lpRect->right,0);
		AdjustPos(lpRect);
		return TRUE;
    }
    if(iY + lpRect->Height() > rcWA.bottom - DETASTEP && iY !=rcWA.bottom-lpRect->Height())
    {
		//调整下
		//pWnd->SetWindowPos(NULL ,iX,rcWA.bottom-rcW.Height(),0,0,SWP_NOSIZE);
		lpRect->OffsetRect(0,rcWA.bottom-lpRect->bottom);
		return TRUE;
    }
    return FALSE;
}
//然后在ONMOVEING事件中使用所下过程调用
CRect r=*pRect;
AdjustPos(&r);
*pRect=(RECT)r;

十二、给系统菜单添加一个菜单项

给系统菜单添加一个菜单项需要进行下述三个步骤:

首先,使用Resource Symbols对话(在View菜单中选择Resource Symbols...可以显示该对话)定义菜单项ID,该ID应大于

0x0F而小于0xF000;

其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加

两个新的菜单项:

 


int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
{
    //Make sure system menu item is in the right range.
    ASSERT(IDM_MYSYSITEM<0xF000);
    //Get pointer to system menu.
    CMenu* pSysMenu=GetSystemMenu(FALSE);
    ASSERT_VALID(pSysMenu);
    //Add a separator and our menu item to system menu.
    CString StrMenuItem(_T ("New menu item"));
    pSysMenu->AppendMenu(MF_SEPARATOR);
    pSysMenu->AppendMenu(MF_STRING, IDM_MYSYSITEM, StrMenuItem);
}

13、运行其它程序


//运行EMAIL或网址

char szMailAddress[80]; 

strcpy(szMailAddress,"mailto:netvc@21cn.com");

ShellExecute(NULL, "open", szMailAddress, NULL, NULL, SW_SHOWNORMAL);

//2、运行可执行程序

WinExec("notepad.exe",SW_SHOW); //运行计事本

14、动态增加或删除菜单

(1)、 增加菜单


//添加
CMenu *mainmenu;
mainmenu=AfxGetMainWnd()->GetMenu(); //得到主菜单
(mainmenu->GetSubMenu (0))->AppendMenu (MF_SEPARATOR);//添加分隔符
(mainmenu->GetSubMenu (0))->AppendMenu(MF_STRING,ID_APP_ABOUT,_T("Always on &Top")); //添加新的菜单项
DrawMenuBar(); //重画菜单

(2)、 删除菜单

 


//删除
CMenu *mainmenu;
mainmenu=AfxGetMainWnd()->GetMenu(); //得到主菜单
CString str ;
for(int i=(mainmenu->GetSubMenu (0))->GetMenuItemCount()-1;i>=0;i--) //取得菜单的项数。
{
    (mainmenu->GetSubMenu (0))->GetMenuString(i,str,MF_BYPOSITION);
    //将指定菜单项的标签拷贝到指定的缓冲区。MF_BYPOSITION的解释见上。
    if(str=="Always on &Top") //如果是刚才我们增加的菜单项,则删除。
    {
		(mainmenu->GetSubMenu (0))->DeleteMenu(i,MF_BYPOSITION);
		break;
    }
}

15、测试ALT键是否按下:

GetKeyState(VK_MENU);
GetAlt();

16、检查是否按下鼠标左键


if((nFlags&MK_LBUTTON)==MK_LBUTTON)

17、检查键盘输入 

在OnKeyDown中的参数nChar是一个数值,当显示的时候,需要转换成字符,使用如下的命令:


char lsChar;
lsChar=char(nChar);
if(lsChar=='A');
{

.......

}

18、调用另一个函数::GetKeyState(),用一个特定的键代码来确定法键是否被按下。如果::GetKeyState函数的返回值是负的,表示该键被按下。如果返回值是非负的,表示该留未被按下。例如:如果要确定shift键是否被按下,可以使用下面的代码:

 


if(::GetKeyState(VK_SHIFT)<O)
{
    AfxMessageBox("shift is pressed");
}

19.如何在编程的过程中随时结束应用程序(常规) 

1)需要向窗口发送 WM_CLOSE/WM_QUIT消息,

调用 CWnd::OnClose成员函数并允许对用户提示是否保存修改过的数据.

AfxGetMainWnd()->SendMessage(WM_CLOSE); //别忘了先得到当前窗口的指针

2)使用函数: void PostQuitMessage( int nExitCode // exit code );

3)使用标准函数:void exit( int status ); //尽量不要在MFC中使用

20.得到屏幕的尺寸大小

HWND hWnd;
CRect Rect;
hWnd = ::GetDesktopWindow();
::GetClientRect(hWnd, &Rect);

//———————————————————

如何查询和设置系统参数

    在Windows 3.1 SDK中介绍过SDK函数SystemParametersInfo,调用该函数可以查询和设置系统参数,诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。  


//Create a font that is used for icon titles.
LOGFONT stFont;
::SystemParametersInfo(SPIF_GETICONTITLELOGFONT,
	sizeof (LOGFONT),&stFont,SPIF_SENDWININICHANGE);
m_font.CreateFontIndirect (&stFont);  //Change the wallpaper to leaves.bmp.
:: SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, _T("forest.bmp"),SPIF_UPDATEINIFILE);

//———————————————————

如何使用一个预定义的Windows光标

      调用CWinApp:: LoadStandardCursor并传送光标标识符。

 

BOOL CSampleDialog::OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message){
	//Display wait cursor if busy.
	if (m_bBusy){
		SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT));
		return TRUE;
	}
	return CDialog:: OnSetCursor (pWnd. nHitTest,message);
}

 

使用CHyperLink类为静态文本添加超链接的方法

Posted by 机器人 on 9th 六月 2007 in c/c++

1.当然每一步是建立一个应用MFC应用程序对话框,工程名为HyperLink然后把CHyperLink这个类的头文件和源文件拷到该工程文件夹内.

2.将CHyperLink添加到工作区.(选择Project->Add Project->File,同时选中CHyperLink的头文件和源文件,点击OK按键),这时在工程区中我们就能看到这个类了.

3.在编辑器中为其添加一个静态文本(增加一个static控件),设置一个该文本控件的标题,为了介绍,这设置为http://hqlong.com.并设置ID为IDC_HYPERLINK.

4.接下来为该static文本控件关联一个CHyperLink类型的变量,提醒一下,CHyperLink是从CStatic类派生而来,所以他继承了CStatic类的所以公共成员函数.关于具体仔细,可能参考该源代码.http://hqlong.com/detail.php?postid=170  .由于静态文本控件不能像其它控件那样,使用向导工具自动关联变量,所以需要手动关联.方法如下:

首先在CHyperLinkDlg类中添加一成员变量.

 

public:
    CHyperLink    m_HyperLink;

然后在该类(CHyperLinkDlg)的DoDataExchange(CDataExchange* pDX)成员函数中添加如下代码.

 

DDX_Control(pDX, IDC_HYPERLINK, m_HyperLink);

 

DDX_Control宏将完成先前我们所设置的文件控件和m_HyperLink的关联.

5.转到OnInitDialog(),在该函数最后添加如下代码:

 

	//设置超链接
	CString sUrl = "http://hqlong.com";
	m_HyperLink.SetURL(sUrl);
	m_HyperLink.SetUnderline(FALSE);//去掉下划线

最后,不要忘了,还要在文件头处添加CHyperLink类的头文件.

 

#include "HyperLink.h"

再起编辑运行,就可以看见效果了.

CHyperLink的源代码在http://hqlong.com/detail.php?postid=170 直接拷贝便可使用.

好了,就介绍到这了.如果有什么问题,可以给我留言..

2007-06-09 23:11:46 机器人 于北京 .

CHyperLink类库的源码

Posted by 机器人 on 9th 六月 2007 in c/c++

由于本空间有限,所以不能上传附件,为了方便大家,在这里特意将CHyperLink类的源代码贴出来,只需要拷贝出来便可使用,代码如下:

头文件:HyperLink.h

 

// HyperLink.h : header file
//
//
// HyperLink static control. Will open the default browser with the given URL
// when the user clicks on the link.
//
// Copyright Chris Maunder, 1997, 1998
// Feel free to use and distribute. May not be sold for profit.

#if !defined(AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

/////////////////////////////////////////////////////////////////////////////
// CHyperLink window

class CHyperLink : public CStatic
{
// Construction/destruction
public:
    CHyperLink();
    virtual ~CHyperLink();

// Attributes
public:

// Operations
public:

    void SetURL(CString strURL);
    CString GetURL() const;

    void SetColours(COLORREF crLinkColour, COLORREF crVisitedColour,
                    COLORREF crHoverColour = -1);
    COLORREF GetLinkColour() const;
    COLORREF GetVisitedColour() const;
    COLORREF GetHoverColour() const;

    void SetVisited(BOOL bVisited = TRUE);
    BOOL GetVisited() const;

    void SetLinkCursor(HCURSOR hCursor);
    HCURSOR GetLinkCursor() const;

    void SetUnderline(BOOL bUnderline = TRUE);
    BOOL GetUnderline() const;

    void SetAutoSize(BOOL bAutoSize = TRUE);
    BOOL GetAutoSize() const;

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CHyperLink)
    public:
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL

// Implementation
protected:
    HINSTANCE GotoURL(LPCTSTR url, int showcmd);
    void ReportError(int nError);
    LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata);
    void PositionWindow();
    void SetDefaultCursor();

// Protected attributes
protected:
    COLORREF m_crLinkColour, m_crVisitedColour;     // Hyperlink colours
    COLORREF m_crHoverColour;                       // Hover colour
    BOOL     m_bOverControl;                        // cursor over control?
    BOOL     m_bVisited;                            // Has it been visited?
    BOOL     m_bUnderline;                          // underline hyperlink?
    BOOL     m_bAdjustToFit;                        // Adjust window size to fit text?
    CString  m_strURL;                              // hyperlink URL
    CFont    m_Font;                                // Underline font if necessary
    HCURSOR  m_hLinkCursor;                         // Cursor for hyperlink
    CToolTipCtrl m_ToolTip;                         // The tooltip

    // Generated message map functions
protected:
    //{{AFX_MSG(CHyperLink)
    afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    //}}AFX_MSG
    afx_msg void OnClicked();
    DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_)

实现文件:HyperLink.cpp

 

// HyperLink.cpp : implementation file
//
// HyperLink static control. Will open the default browser with the given URL
// when the user clicks on the link.
//
// Copyright (C) 1997, 1998 Chris Maunder (chrismaunder@codeguru.com)
// All rights reserved. May not be sold for profit.
//
// Thanks to P錶 K. T鴑der for auto-size and window caption changes.
//
// "GotoURL" function by Stuart Patterson
// As seen in the August, 1997 Windows Developer's Journal.
// Copyright 1997 by Miller Freeman, Inc. All rights reserved.
// Modified by Chris Maunder to use TCHARs instead of chars.
//
// "Default hand cursor" from Paul DiLascia's Jan 1998 MSJ article.
//

#include "stdafx.h"
#include "HyperLink.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define TOOLTIP_ID 1

/////////////////////////////////////////////////////////////////////////////
// CHyperLink

CHyperLink::CHyperLink()
{
    m_hLinkCursor       = NULL;                 // No cursor as yet
    m_crLinkColour      = RGB(  0,   0, 238);   // Blue
    m_crVisitedColour   = RGB( 85,  26, 139);   // Purple
    m_crHoverColour     = ::GetSysColor(COLOR_HIGHLIGHT);
    m_bOverControl      = FALSE;                // Cursor not yet over control
    m_bVisited          = FALSE;                // Hasn't been visited yet.
    m_bUnderline        = TRUE;                 // Underline the link?
    m_bAdjustToFit      = TRUE;                 // Resize the window to fit the text?
    m_strURL.Empty();
}

CHyperLink::~CHyperLink()
{
    m_Font.DeleteObject();
}

BEGIN_MESSAGE_MAP(CHyperLink, CStatic)
    //{{AFX_MSG_MAP(CHyperLink)
    ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
    ON_WM_CTLCOLOR_REFLECT()
    ON_WM_SETCURSOR()
    ON_WM_MOUSEMOVE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHyperLink message handlers

BOOL CHyperLink::PreTranslateMessage(MSG* pMsg)
{
    m_ToolTip.RelayEvent(pMsg);
    return CStatic::PreTranslateMessage(pMsg);
}

void CHyperLink::OnClicked()
{
    int result = (int)GotoURL(m_strURL, SW_SHOW);
    m_bVisited = (result > HINSTANCE_ERROR);
    if (!m_bVisited) {
        MessageBeep(MB_ICONEXCLAMATION);     // Unable to follow link
        ReportError(result);
    } else
        SetVisited();                        // Repaint to show visited colour
}

HBRUSH CHyperLink::CtlColor(CDC* pDC, UINT nCtlColor)
{
    ASSERT(nCtlColor == CTLCOLOR_STATIC);

    if (m_bOverControl)
        pDC->SetTextColor(m_crHoverColour);
    else if (m_bVisited)
        pDC->SetTextColor(m_crVisitedColour);
    else
        pDC->SetTextColor(m_crLinkColour);

    // transparent text.
    pDC->SetBkMode(TRANSPARENT);
    return (HBRUSH)GetStockObject(NULL_BRUSH);
}

void CHyperLink::OnMouseMove(UINT nFlags, CPoint point)
{
    CStatic::OnMouseMove(nFlags, point);

    if (m_bOverControl)        // Cursor is currently over control
    {
        CRect rect;
        GetClientRect(rect);

        if (!rect.PtInRect(point))
        {
            m_bOverControl = FALSE;
            ReleaseCapture();
            RedrawWindow();
            return;
        }
    }
    else                      // Cursor has just moved over control
    {
        m_bOverControl = TRUE;
        RedrawWindow();
        SetCapture();
    }
}

BOOL CHyperLink::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/)
{
    if (m_hLinkCursor)
    {
        ::SetCursor(m_hLinkCursor);
        return TRUE;
    }
    return FALSE;
}

void CHyperLink::PreSubclassWindow()
{
    // We want to get mouse clicks via STN_CLICKED
    DWORD dwStyle = GetStyle();
    ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);

    // Set the URL as the window text
    if (m_strURL.IsEmpty())
        GetWindowText(m_strURL);

    // Check that the window text isn't empty. If it is, set it as the URL.
    CString strWndText;
    GetWindowText(strWndText);
    if (strWndText.IsEmpty()) {
        ASSERT(!m_strURL.IsEmpty());    // Window and URL both NULL. DUH!
        SetWindowText(m_strURL);
    }

    // Create the font
    LOGFONT lf;
    GetFont()->GetLogFont(&lf);
    lf.lfUnderline = m_bUnderline;
    m_Font.CreateFontIndirect(&lf);
    SetFont(&m_Font);

    PositionWindow();        // Adjust size of window to fit URL if necessary
    SetDefaultCursor();      // Try and load up a "hand" cursor

    // Create the tooltip
    CRect rect;
    GetClientRect(rect);
    m_ToolTip.Create(this);
    m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);

    CStatic::PreSubclassWindow();
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink operations

void CHyperLink::SetURL(CString strURL)
{
    m_strURL = strURL;

    if (::IsWindow(GetSafeHwnd())) {
        PositionWindow();
        m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);
    }
}

CString CHyperLink::GetURL() const
{
    return m_strURL;
}

void CHyperLink::SetColours(COLORREF crLinkColour, COLORREF crVisitedColour,
                            COLORREF crHoverColour /* = -1 */)
{
    m_crLinkColour    = crLinkColour;
    m_crVisitedColour = crVisitedColour;

	if (crHoverColour == -1)
		m_crHoverColour = ::GetSysColor(COLOR_HIGHLIGHT);
	else
		m_crHoverColour = crHoverColour;

    if (::IsWindow(m_hWnd))
        Invalidate();
}

COLORREF CHyperLink::GetLinkColour() const
{
    return m_crLinkColour;
}

COLORREF CHyperLink::GetVisitedColour() const
{
    return m_crVisitedColour;
}

COLORREF CHyperLink::GetHoverColour() const
{
    return m_crHoverColour;
}

void CHyperLink::SetVisited(BOOL bVisited /* = TRUE */)
{
    m_bVisited = bVisited; 

    if (::IsWindow(GetSafeHwnd()))
        Invalidate();
}

BOOL CHyperLink::GetVisited() const
{
    return m_bVisited;
}

void CHyperLink::SetLinkCursor(HCURSOR hCursor)
{
    m_hLinkCursor = hCursor;
    if (m_hLinkCursor == NULL)
        SetDefaultCursor();
}

HCURSOR CHyperLink::GetLinkCursor() const
{
    return m_hLinkCursor;
}

void CHyperLink::SetUnderline(BOOL bUnderline /* = TRUE */)
{
    m_bUnderline = bUnderline;

    if (::IsWindow(GetSafeHwnd()))
    {
        LOGFONT lf;
        GetFont()->GetLogFont(&lf);
        lf.lfUnderline = m_bUnderline;

        m_Font.DeleteObject();
        m_Font.CreateFontIndirect(&lf);
        SetFont(&m_Font);

        Invalidate();
    }
}

BOOL CHyperLink::GetUnderline() const
{
    return m_bUnderline;
}

void CHyperLink::SetAutoSize(BOOL bAutoSize /* = TRUE */)
{
    m_bAdjustToFit = bAutoSize;

    if (::IsWindow(GetSafeHwnd()))
        PositionWindow();
}

BOOL CHyperLink::GetAutoSize() const
{
    return m_bAdjustToFit;
}

// Move and resize the window so that the window is the same size
// as the hyperlink text. This stops the hyperlink cursor being active
// when it is not directly over the text. If the text is left justified
// then the window is merely shrunk, but if it is centred or right
// justified then the window will have to be moved as well.
//
// Suggested by P錶 K. T鴑der

void CHyperLink::PositionWindow()
{
    if (!::IsWindow(GetSafeHwnd()) || !m_bAdjustToFit)
        return;

    // Get the current window position
    CRect rect;
    GetWindowRect(rect);

    CWnd* pParent = GetParent();
    if (pParent)
        pParent->ScreenToClient(rect);

    // Get the size of the window text
    CString strWndText;
    GetWindowText(strWndText);

    CDC* pDC = GetDC();
    CFont* pOldFont = pDC->SelectObject(&m_Font);
    CSize Extent = pDC->GetTextExtent(strWndText);
    pDC->SelectObject(pOldFont);
    ReleaseDC(pDC);

    // Get the text justification via the window style
    DWORD dwStyle = GetStyle();

    // Recalc the window size and position based on the text justification
    if (dwStyle & SS_CENTERIMAGE)
        rect.DeflateRect(0, (rect.Height() - Extent.cy)/2);
    else
        rect.bottom = rect.top + Extent.cy;

    if (dwStyle & SS_CENTER)
        rect.DeflateRect((rect.Width() - Extent.cx)/2, 0);
    else if (dwStyle & SS_RIGHT)
        rect.left  = rect.right - Extent.cx;
    else // SS_LEFT = 0, so we can't test for it explicitly
        rect.right = rect.left + Extent.cx;

    // Move the window
    SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER);
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink implementation

// The following appeared in Paul DiLascia's Jan 1998 MSJ articles.
// It loads a "hand" cursor from the winhlp32.exe module
void CHyperLink::SetDefaultCursor()
{
    if (m_hLinkCursor == NULL)                // No cursor handle - load our own
    {
        // Get the windows directory
        CString strWndDir;
        GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
        strWndDir.ReleaseBuffer();

        strWndDir += _T("\\winhlp32.exe");
        // This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
        HMODULE hModule = LoadLibrary(strWndDir);
        if (hModule) {
            HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
            if (hHandCursor)
                m_hLinkCursor = CopyCursor(hHandCursor);
        }
        FreeLibrary(hModule);
    }
}

LONG CHyperLink::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
{
    HKEY hkey;
    LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);

    if (retval == ERROR_SUCCESS) {
        long datasize = MAX_PATH;
        TCHAR data[MAX_PATH];
        RegQueryValue(hkey, NULL, data, &datasize);
        lstrcpy(retdata,data);
        RegCloseKey(hkey);
    }

    return retval;
}

void CHyperLink::ReportError(int nError)
{
    CString str;
    switch (nError) {
        case 0:                       str = "The operating system is out\nof memory or resources."; break;
        case SE_ERR_PNF:              str = "The specified path was not found."; break;
        case SE_ERR_FNF:              str = "The specified file was not found."; break;
        case ERROR_BAD_FORMAT:        str = "The .EXE file is invalid\n(non-Win32 .EXE or error in .EXE image)."; break;
        case SE_ERR_ACCESSDENIED:     str = "The operating system denied\naccess to the specified file."; break;
        case SE_ERR_ASSOCINCOMPLETE:  str = "The filename association is\nincomplete or invalid."; break;
        case SE_ERR_DDEBUSY:          str = "The DDE transaction could not\nbe completed because other DDE transactions\nwere being processed."; break;
        case SE_ERR_DDEFAIL:          str = "The DDE transaction failed."; break;
        case SE_ERR_DDETIMEOUT:       str = "The DDE transaction could not\nbe completed because the request timed out."; break;
        case SE_ERR_DLLNOTFOUND:      str = "The specified dynamic-link library was not found."; break;
        case SE_ERR_NOASSOC:          str = "There is no application associated\nwith the given filename extension."; break;
        case SE_ERR_OOM:              str = "There was not enough memory to complete the operation."; break;
        case SE_ERR_SHARE:            str = "A sharing violation occurred. ";
        default:                      str.Format("Unknown Error (%d) occurred.", nError); break;
    }
    str = "Unable to open hyperlink:\n\n" + str;
    AfxMessageBox(str, MB_ICONEXCLAMATION | MB_OK);
}

HINSTANCE CHyperLink::GotoURL(LPCTSTR url, int showcmd)
{
    TCHAR key[MAX_PATH + MAX_PATH];

    // First try ShellExecute()
    HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);

    // If it failed, get the .htm regkey and lookup the program
    if ((UINT)result <= HINSTANCE_ERROR) {

        if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS) {
            lstrcat(key, _T("\\shell\\open\\command"));

            if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) {
                TCHAR *pos;
                pos = _tcsstr(key, _T("\"%1\""));
                if (pos == NULL) {                     // No quotes found
                    pos = strstr(key, _T("%1"));       // Check for %1, without quotes
                    if (pos == NULL)                   // No parameter at all...
                        pos = key+lstrlen(key)-1;
                    else
                        *pos = '\0';                   // Remove the parameter
                }
                else
                    *pos = '\0';                       // Remove the parameter

                lstrcat(pos, _T(" "));
                lstrcat(pos, url);
                result = (HINSTANCE) WinExec(key,showcmd);
            }
        }
    }

    return result;
}

2007-06-09 机器人 于 北京

VC++怎么给对话框添加一个FLASH控件

Posted by 机器人 on 9th 六月 2007 in c/c++

1.首先新建一个MFC对话框应用程序,工程名叫"TestFlash".

2.添加shockwave flash object控件,(在建立要对话框应用程序后,Project->Add to Project->Component and Control..这里弹出了一对话框,里面有两个文件夹,选择第一文件夹后会出现一系列系统上已注册过的activex控件,然后选择Shockwave Flash Object,注意:如果Flash控件没有注册,将不显示.点击Insert将它插入到工程,点击OK.这样就完成了showwave flash object控件的添加工作,这时,VC给我们生成了一个CShockwaveFlash类.)

3.切换到VC对话框的编辑器的控制面板上,发现多了一个showwave flash object控件,接下将该控件拖放到对话框面板上,然后再给这个控件关联一个对象,关联对象的方法和文本控件等常用的控件一样.(选择该控件,点击鼠标右键,选择ClassWizard,在弹出的向导框中选择Member Variables选项,然后点击Add Variable按钮,增加一个变量,我们这里取名为"m_TestFlash",变量类型就是刚才所生成的对象名,即:CShockwaveFlash.然后关闭对话框.

4.现在打开CTestFlashDlg类,在OnInitDialog()函数最下面增加如下代码:

m_TestFlash.SetMovie("http://images.wx216.com/flash/2007-05-12/1178960659423.swf");

现在编译运行一下,在对话框中的Flash控件就显示出了上面我们所添加的FLASH影片,这里我们所设置的影片是网信公司的一个广告.

这只是简单得实际了完成一个FLASH影片播放的基本功能,其它的方法比较播放,前进,后退等,大家可以自己去尝试,关于使用说明,只要看一个类的头文件,相信大家就会使用它了,因为每个成员函数的取名都比较规范,基本上是从函数名就能知道它的用途.

VC++中,设置对话框背景颜色的常用方法

Posted by 机器人 on 9th 六月 2007 in c/c++

方法一:调用CWinApp类的成员函数SetDialogBkColor来实现。

—- 其中函数的第一个参数指定了背景颜色,第二个参数指定了文本颜色。下面的例子是将应用程序对话 框设置为蓝色背景和红色文本,步骤如下:

—- ① 新建一个基于Dialog的MFC AppWizard应用程序ExampleDlg。

—- ② 在CExampleDlgApp ::InitInstance()中添加如下代码:

BOOL CExampleDlgApp: : InitInstance ( )
{
	…
	CExampleDlgDlg dlg;
	m_pMainWnd = &dlg;
	//先于DoModal()调用,将对话框设置为蓝色背景、红色文本
	SetDialogBkColor(RGB(0,0,255),RGB(255,0,0));
	int nResponse = dlg.DoModal();
}

—- 编译并运行,此时对话框的背景色和文本色已发生了改变。值得注意的是:在调用DoModal()之前必须 先调用SetDialogBkColor,且此方法是将改变应用程序中所有的对话框颜色,并不能针对某一个指定的对 话框。

—- 方法二:重载OnPaint(),即WM_PAINT消息。有关代码如下(以上例工程为准):

void CExampleDlgDlg::OnPaint()
{
	if (IsIconic()){
            //omitted for brevity
        }
	else
	{
		CRect rect;
		CPaintDC dc(this);
		GetClientRect(rect);
		dc.FillSolidRect(rect,RGB(0,255,0)); //设置为绿色背景
		CDialog::OnPaint();
	}
}

—- 方法三:重载OnCtlColor (CDC* pDC, CWnd* pWnd, UINT nCtlColor),即WM_CTLCOLOR消息。具体 步骤如下(以上例工程为准):

—- ①在CExampleDlgDlg的头文件中,添加一CBrush的成员变量:

class CExampleDlgDlg : public CDialog
{
	...
	protected:
	CBrush m_brush;
	...
	};
	---- ②在OnInitDialog()函数中添加如下代码:
	BOOL CExampleDlgDlg::OnInitDialog()
	{
	...
	// TODO: Add extra initialization here
	m_brush.CreateSolidBrush(RGB(0, 255, 0)); // 生成一绿色刷子
	...
}

—- ③利用ClassWizard重载OnCtlColor(…),即WM_CTLCOLOR消息:

HBRUSH CExampleDlgDlg::OnCtlColor
(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	/*
	** 这里不必编写任何代码!
	**下行代码要注释掉
	** HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	*/
	return m_brush; //返加绿色刷子
}

—- 方法四:还是重载OnCtlColor (CDC* pDC, CWnd* pWnd, UINT nCtlColor),即WM_CTLCOLOR消息。 具体步骤如下(以上例工程为准):

—- 步骤①、②同上方法三中的步骤①、②。

—- 步骤③利用ClassWizard重载OnCtlColor(…)(即WM_CTLCOLOR消息)时则有些不同:

HBRUSH CExampleDlgDlg::OnCtlColor
(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	//在这加一条是否为对话框的判断语句
	if(nCtlColor ==CTLCOLOR_DLG)
		return m_brush; //返加绿色刷子
	return hbr;
}

—- 编译并运行即可。

—- 关于如何改变对话框背景颜色的问题,可能还有很多种不同方法可以实现,笔者在这仅举出四种常见 的方法。其中方法三的编程似乎有点不太规范,方法四则要比方法三正统些,笔者这样的对比举例是为了 拓宽VC编程爱好者特别是初学者的编程思路,读者可以根据实际情况选用其中的一种。如果再结合《软件 报》2000年第5期中改变对话框上的控件颜色,相信会使您的MFC应用程序"增色"不少。

另外一种就是用

BOOL CBPCALLView::OnEraseBkgnd(CDC* pDC)
{
	//可以背景图,画刷等
	//return CScrollView::OnEraseBkgnd(pDC);
}

 

最常见的20种VC++编译错误信息集合

Posted by 机器人 on 9th 六月 2007 in c/c++

最常见的20种VC++编译错误信息集合

作者:hqlong 日期:2007-06-09

1、fatal error C1010: unexpected end of file while looking for precompiled header directive。

  寻找预编译头文件路径时遇到了不该遇到的文件尾。(一般是没有#include "stdafx.h")

  2、fatal error C1083: Cannot open include file: ‘R…….h’: No such file or directory

  不能打开包含文件“R…….h”:没有这样的文件或目录。

  3、error C2011: ‘C……’: ‘class’ type redefinition

  类“C……”重定义。

  4、error C2018: unknown character ’0xa3′

  不认识的字符’0xa3′。(一般是汉字或中文标点符号)

  5、error C2057: expected constant expression

  希望是常量表达式。(一般出现在switch语句的case分支中)

  6、error C2065: ‘IDD_MYDIALOG’ : undeclared identifier

  “IDD_MYDIALOG”:未声明过的标识符。

  7、error C2082: redefinition of formal parameter ‘bReset’

  函数参数“bReset”在函数体中重定义。

  8、error C2143: syntax error: missing ‘:’ before ‘{‘

  句法错误:“{”前缺少“;”。

  9、error C2146: syntax error : missing ‘;’ before identifier ‘dc’

  句法错误:在“dc”前丢了“;”。

  10、error C2196: case value ’69′ already used

  值69已经用过。(一般出现在switch语句的case分支中)

11、error C2509: ‘OnTimer’ : member function not declared in ‘CHelloView’

  成员函数“OnTimer”没有在“CHelloView”中声明。

  12、error C2511: ‘reset’: overloaded member function ‘void (int)’ not found in ‘B’

  重载的函数“void reset(int)”在类“B”中找不到。

  13、error C2555: ‘B::f1′: overriding virtual function differs from ‘A::f1′ only by return type or calling convention

  类B对类A中同名函数f1的重载仅根据返回值或调用约定上的区别。

  14、error C2660: ‘SetTimer’ : function does not take 2 parameters

  “SetTimer”函数不传递2个参数。

  15、warning C4035: ‘f……’: no return value

  “f……”的return语句没有返回值。

  16、warning C4553: ‘= =’ : operator has no effect; did you intend ‘=’?

  没有效果的运算符“= =”;是否改为“=”?

  17、warning C4700: local variable ‘bReset’ used without having been initialized

  局部变量“bReset”没有初始化就使用。

  18、error C4716: ‘CMyApp::InitInstance’ : must return a value

  “CMyApp::InitInstance”函数必须返回一个值。

  19、LINK : fatal error LNK1168: cannot open Debug/P1.exe for writing

  连接错误:不能打开P1.exe文件,以改写内容。(一般是P1.Exe还在运行,未关闭)

  20、error LNK2001: unresolved external symbol "public: virtual _ _thiscall C……::~C……(void)"

  连接时发现没有实现的外部符号(变量、函数等)。

  function call missing argument list 调用函数的时候没有给参数。

  member function definition looks like a ctor, but name does not match enclosing class 成员函数声明了但没有使用

  unexpected end of file while looking for precompiled header directive 在寻找预编译头文件时文件意外结束,编译不正常终止可能造成这种情况

什么是封装,怎么能更好的理解封装呢?

Posted by 机器人 on 8th 六月 2007 in mylife

摘自:2007年6月8日晚讨论记录:讨论如何封装最“啰嗦”的部分(明晚讨论话题)

封装如果只是空谈,不去付诸行动的话,那么这个概念可能对大家来讲,会一直抽象下去,所以要更好的掌握封装,那么一定要去多尝试,只要有想法,那么就去实现它,哪怕不成功,也没关系.

为 了更好的说明封装这个问题,给大家举个例子,通过这个例子,大家应该会对封装有个更深入的了解,当然,说到这里,现在在概念上给大家澄清一下,封装,顾名 思义,从字面就很容易理解 它,就是对一些具有特别功能的功能模块进行了组合,即实现高内聚,而且各功能模块之间藕合要低,不能各功能模板之间的依赖关系太强,大家平时常听到的高 内聚低藕合也是封装的宗旨.

下段是一个例子:

 

   在 现实世界中,每一个可能使用概念描述的事物,都可以被我们定义成对象,那么在这里,拿家具厂和螺钉厂再说明这个例子,把这两个客观事物抽象成所需要的两个 类,即:家具类和螺钉类.一个家具能够独立组合而成,要描述一个家具,可能会这样给些参数来进行描述:长度、高度、颜色、螺钉型号等,那么 螺钉类呢?同样也由相应的参数来进行描述:材料、型号、等,为了让外界能够很好的了解螺钉,那么我们就可以提供给外界一些接口,那么给定义一个函数, 该函数的功能是得到该螺钉的型号,如果要生产一个螺钉,为了让螺钉厂知道生产的型号,所以在这里还需要设置一个函数来提供传达生产型号,所以这个 类中就会有这样两个接口:

getModel();//得到型号

setModel();//传达型号

现在再回到家具类这边,要生产一套家具,除了材料等必备的东西外,还需要螺钉,如果没有螺钉,那么家具是很难组合而成的.比如生产一套家具需要m3规格的螺钉,而这时,家具厂是不会去自己生产的,而是把这个任务传达给螺钉厂,让它们来完成生产任务,然后把生成好的螺钉返回给家具厂,那么这个时候,家具厂所需要的材料就都具备了,就可以开始生成材料了.

 

   在上面的例子中,家具厂就生产家具,螺钉厂就生产螺钉,这里的生产家具和生产螺钉就是一个高内聚的功能,所以把它们放在了两个厂里面进行生产,但是 在生产家具的时候,需要螺钉,没有螺钉家具是很难成形的,所以这时就需要螺钉厂给家具厂提供所需的型号,当螺钉厂把螺钉生产好了,然后提供给家具厂,那么 家具厂就可能很好的完成自己的任务了.从这点可以看出,虽然这两个厂进行分离,但是它们之间并不是互不相干的,而是一种合作的关系.

 

  这时有好几家螺钉厂,这时家具厂不但可以向螺钉A厂订购螺钉,同样也可能像其它的螺钉厂家订购螺钉,家具厂的螺钉来源并不是只能依 靠A厂,同样可以依靠其它厂,如果A厂不在了,那么家具厂还可以向其它厂订购螺钉,当然,如果有几家家具厂的话,这时螺钉厂的生意可成了前所未有的兴旺, 不但能给家具A厂提供螺钉,还可以给家具B厂 提供螺钉,如果每家家具厂只能使用特定螺钉厂的螺钉,而每家螺钉厂又只能向特定的家具厂提供螺钉,恐怕再也没 有比这更糟糕的事情了.程序设计来也具有这样的道理,如果把某一段代码紧紧的与另外一边的唯一的一处代码紧紧的关联起来,那么这段代码也就必需紧紧的依靠 另 外的那处代码了,那么就很难将这段代码抽取出来,摞到其他地方或者其它项目中去使用,可能为了完成相似的功能,又得去重新编写类似的代码,就好比,每 家螺钉厂只生产唯一型号的螺钉,而每家家具厂也只生成使用唯一型号螺钉的家具,在这种情况下,如果能把相似功能的代码提取出来,一旦把它写好,或者一旦在 这样的螺钉厂建设好,到时候只要需要螺钉,不管是什么样的螺钉,它都能生成出来,这样情况,就比先前的好多了,这也是我们所希望达到的效果.

   对前面的问题,如果再做一个假设,对具有特定功能的事件不进行封装,如:家具厂的螺钉来源不是由螺钉厂生产,而是要自己去生成,可以想像一下,将会成为 一个什么样的情况,这些问题在我们的现实生活中,都是很行不通的,如果这些事情大家平时多留意,并把它运用到程序设计中,那么对我们 的程序设计能力会有很大的提高,转到程序设计里面也是同样的道理,如果把几个具有特定功能的模块,不进行封装,而是写在一起,那么最后的效果就和家具厂要 自己生成螺钉是一样的道理.

 

对于封装有几个原则可遵循:

1.将具有特定功能的代码进行模块化.

2.尽量消除程序中比较大的功能模块,将其拆分成多个小的模块.

3.将其比较小的,不能完成任何功能的模块进行组合成一个具有特定功能的模块.

大家可以参考上面几个原则来进行设计.

通过上面的举证,相信大家现在已经对封装等一些比较抽象的概念有了比较深入的了解,这里敢保证,一定是这样的.肯定的...

 

2007-06-08 23:04:58