VC常用小技巧(2)

如何干净的删除一个类?
1、先删除项目中对应的.h.cpp文件,(选中后用Delete键删除)
2
、保存后退出项目,到文件夹中删除实际的.h.cpp文件;
3
、删除.clw文件;
4
、重新进入项目,进行全部重建(rebuild all)。

如何建立一个新类?
    
插入”(Insert)菜单中选择新建类”(New Class),在弹出的对话框中选择基类(Base class),在Name中输入新类的名字(一般都以C开头)即可。
如果想要建立一个没有基类的自定义类,则在New Class对话框中把Class type设置为generic,再输入类名即可。

如何把外来文件添加到项目中?
    
先把外来文件复制到当前项目的目录下,从项目”(Project)菜单下选择添加项目”(Add to Project)下的“Files”菜单项,从弹出的打开文件对话框中把外来文件打开即可。

如何在一个工作区中打开多个项目?
    
一般编程者都有这样的经历:做了一个项目,由于不满意,想从头重做,但又想把旧项目的一些可用内容拷到新项目中来,以免做重复工作,这时就需要在新项目中打开旧项目。
    
先打开新项目,从项目”(Project)菜单下选择插入项目到工作区”(Insert Project into Workspace),从弹出的打开文件对话框中打开旧项目的.asp文件即可。
    
之后,可以利用项目”(Project)菜单下的设置活动项目”(Select Active Project)的选项中切换各打开的项目。
注意:在一个工作区中打开的各项目不能同名。

如何把项目中的文件分类存放?
当我们往项目中添加新类时,它会把源文件放在Source Files下,头文件放在Header Files下。当项目中文件很多时,管理不便,最好添加新节点,把文件分类放置。
右击项目节点树的根节点,选择“New Folder...”,在弹出的对话框中填入新节点名,则新节点就建立了,用鼠标节点树中的文件拖入新节点,就可以把文件分类了。
以上分类只是在项目的节点树中分类,它不影响文件在磁盘上的位置,所有.cpp文件和.h文件仍在项目的根目录下,最好文件本身也能分类存放在不同文件夹中。
Windows下,用新建文件夹在项目的根目录下建立子文件夹,如DialogClass,把所有对话框类的.cpp文件和.h文件拖入其中。
回到VC下,右键单击项目树中更改了路径的节点,选择“Properties”,在弹出的对话框中修改文件路径,如:把原路径“.\Dialog1.cpp”改为“.\DialogClass\Dialog1.cpp”
打开Dialog1.cpp文件,修改它包含的文件路径。如:
#include "stdafx.h"
#include "PluckBox.h"
#include "Dialog1.h"
改为:
#include "stdafx.h"
#include "..\\PluckBox.h"
#include "Dialog1.h"
打开ClassWizard,它会提示你文件不存在,单击确定后,从对话框中用“Browse...”选择文件所在路径,则ClassWizard也可正常使用了。



编辑
编辑代码时,跟随提示消失了怎么办?
单 击工具”(Tools)菜单中的设置”(Options)菜单项,在弹出的Options对话框中选择Editor制表页,把它最下方的四个复选框都 选中(Auto list memberAuto type infoCode commentsAuto parameter info),这样,当用户输入“->”“.”时,会自动显示跟随提示,减少了输入负担。



对话框
如何修改对话框的背景色
在对话框的OnPaint()函数中加入下面语句:
CRect rect;
GetClientRect(&rect); //
计算对话框的尺寸
dc.FillSolidRect(&rect,RGB(192,248,202)); //
绘制对话框背景色

如何让弹出式对话框具有统一的背景色
在应用程序类CxxxAppInitInstance()函数中加入下面的语句:
SetDialogBkColor( RGB(192,248,202) );
则所有用户定义的弹出式对话框都以RGB(192,248,202)为背景色,就不需要逐个进行设置了。


如何让打开文件对话框能进行多项选择
在定制打开文件对话框时,增加OFN_ALLOWMULTISELECT属性,就可以使打开文件对话框进行多选了。
如:
CFileDialog m_Dlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
| OFN_ALLOWMULTISELECT, NULL, NULL );
之后,用GetStartPosition()函数获取选择的起始文件位置,用GetNextPathName()函数获取各位置上的文件名。
如:
if( m_Dlg.DoModal() == IDOK )
{
POSITION pos;
pos = m_Dlg.GetStartPosition();
while( pos )
{
m_Path = m_Dlg.GetNextPathName(pos);
…………
}
}

为什么用打开文件对话框选择多个文件到一定数目时,文件没有打开?
CFileDialog
为文件列表设置有缓冲区,当选择文件过多时,会造成缓冲区溢出,造成一些文件没有被打开。可以采用自定义大缓冲区代替系统缓冲区的方法解决。
如:
CFileDialog m_Dlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
| OFN_ALLOWMULTISELECT, NULL, NULL );//
定制打开文件对话框
char* pBuf = new char[20480]; //
申请缓冲区
m_Dlg.m_ofn.nMaxFile = 20480; //
pBuf代替CFileDialog缓冲区
m_Dlg.m_ofn.lpstrFile = pBuf;
m_Dlg.m_ofn.lpstrFile[0] = NULL;
…………
delete []pBuf; //
回收缓冲区

提示对话框(MessageBox
在视类和对话框类中可使用MFC函数中用的MessageBox()函数弹出提示对话框。这个函数原型为:
int MessageBox(LPCTSTR lpszText,LPCTSTR lpsCaption=NULL,UINT nType=MB_OK);
参数:lpszText 显示的字符串
lpsCaption
对话框的标题
nType
风格,可为如下值的组合:
指定下列标志中的一个来显示消息框中的按钮,标志的含义如下。
MB_ABORTRETRYIGNORE
:消息框含有三个按钮:AbortRetryIgnore
MB_OK
:消息框含有一个按钮:OK。这是缺省值。
MB_OKCANCEL
:消息框含有两个按钮:OKCancel
MB_RETRYCANCEL
:消息框含有两个按钮:RetryCancel
MB_YESNO
:消息框含有两个按钮:YesNo
MB_YESNOCANCEL
:消息框含有三个按钮:YesNoCancel
指定下列标志中的一个来显示消息框中的图标:标志的含义如下。
MB_ICONEXCLAMATION:
MB_ICONWARNING
:一个惊叹号出现在消息框。
MB_ICONINFORMATION

MB_ICONASTERISK
:一个圆圈中小写字母i组成的图标出现在消息框。
MB_ICONOUESTION:
一个问题标记图标出现在消息框。
MB_ICONSTOP:
MB_ICONERROR

MB_ICONHAND
:一个停止消息图标出现在消息框。
指定下列标志中的一个来指定缺省的按钮:标志的含义如下。
MB_DEFBUTTON1
:第一个按钮为缺省按钮。如果MB_DEFBUTTON2MB_DEFBUTTON3MB_DEFBUTTON4没有被指定,则MB_DEFBUTTON1为缺省值。
MB_DEFBUTTON2
;第二个按钮为缺省按钮。
MB_DEFBUTTON3
:第三个按钮为缺省按钮。
MB_DEFBUTTON4
:第四个按钮为缺省按钮。
例:提示文件是否存盘:
int t;
t=MessageBox(m_PathName+"
的文字已经改变,要存盘吗?",
"
警告",MB_YESNOCANCEL | MB_ICONWARNING);
if(t==0 || t==IDCANCEL)
return;
if(t==IDYES)
OnFileSave();
在文档类等其它类中不能使用MFC中的MessageBox()函数,只能使用API函数中的MessageBox()函数:
int MessageBox(HWND hWnd,LPCTSTR lpszText,LPCTSTR lpCaption,UINT UType);
hWnd:
标识将被创建的消息框的拥有窗口。如果此参数为NULL,则消息框没有拥有窗口。
后三个参数与视类的MessageBox相同,但没有缺省值,必须设置。
例:::MessageBox(NULL,m_PathName+"的文字已经改变,要存盘吗?",
"
警告",MB_YESNOCANCEL | MB_ICONWARNING);



调试
error C2146: syntax error : missing ';' before identifier ……
如果出现这个错误且错误数目很多,通常并不是缺失了分号引起的,而是忘记了添加某头文件引起的。
最常见的是新加入了对话框,然后用它的类定义了一个对象,再编译出现上面的错误。
解决方法是在引用新类的文件中加入#include "类名.h",再编译,错误消失。

fatal error C1010: unexpected end of file while looking for precompiled header directive
在一个项目中,如果用“New”向工程中添加了一个.cpp文件,编译,出错。
解决方法:
                   1)   在新建的.cpp文件的开头加入#include "stdafx.h"
                   2)   可以使用右键点击项目工程中的该cpp文件,选择setting,在c/c++栏,选择PreCompiled headers,然后设置第一选项,选择不使用预编译头,解决这个问题。发布
Debug
模式和Release模式
早就发现用VC编译出来的.exe文件比用Turbo C编译出来的文件大了许多,于是就认为VC编译时一定加了很多没用的东西,记得当时还做过把VC自动生成的项目中自认为没用的函数都删掉的傻事。后来才从网上的文章中了解到还有编译模式一说。
Debug
模式是用来调试用的,它生成的执行文件中含有大量调试信息,所以很大;
Release
模式生成的执行文件消除了这些调试信息,可用来作为成品发布。
默 认情况下是Debug模式,切换方法是在编译”(Build)菜单中选设置项目配置”(Set Active Configure)。从弹出的对话框中选择Win32 Release模式,然后再重新编译。这时在工作目录下会多出一个Release目录,其中的exe文件比Debug目录下的那个要小得多。

动态链接库和静态链接库
VC 做好了一个程序,拿到别人那里却不能运行,这也是很多编程者都经历过的,这样的软件只能在安装有VC的机器上运行,也不应拿出去发布。实际上如果你没有使 用ActiveX控件和自定义的动态DLL技术,只需把MFC的动态链接库打包到你的程序里就可以了,也就是使用静态链接库。
设置方法:从项目”(Project)菜单下选择设置” (Settings),在弹出的对话框中的General选项卡下,把“User MFC in a Shared DLL”改为“User MFC in a Static Library”,关闭对话框后重新编译即可。
在静态链接库下编译的文件比动态链接库的要大很多,不过,如果使用Release模式编译,一般也就几百K,它就可以在没有安装VC的机器上运行了。

发布VC源代码时,哪些文件可以删除?
AfxGetMainWnd()->SetWindowText("文档标题"+" - "+"程序标题");

四、设置默认按钮:
在定义控件变量时,ClassWizard在构造函数中会把变量初值设为-1,只需把它改为其它值即可。
如:
//{{AFX_DATA_INIT(CWEditView)
m_Ridio1 = 0; //
初始时第一个单选按钮被选中
m_Ridio4 = 0; //
初始时第四个单选按钮被选中
//}}AFX_DATA_INIT

旋转控件(Spin)的使用
当单击旋转控件上的按钮时,相应的编辑控件值会增大或减小。其设置的一般步骤为:
一、在对话框中放入一个Spin控件和一个编辑控件作为Spin控件的伙伴窗口
设置Spin控件属性:Auto buddySet buddy integerArrow keys
设置文本控件属性:Number
二、用ClassWizardSpin控件定义变量m_Spin,为编辑控件定义变量m_Edit,定义时注意要把m_Edit设置为int型。
三、在对话框的OnInitDialog()函数中加入语句:
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();

m_Spin.SetBuddy( GetDlgItem( IDC_EDIT1 ) ); //
设置编辑控件为Spin控件的伙伴窗口
m_Spin.SetRange( 0, 10 ); //
设置数据范围为0-10
return TRUE;
}
四、用ClassWizard为编辑控件添加EN_CHANGE消息处理函数,再加入语句:
void CMyDlg::OnChangeEdit1()
{
m_Edit = m_Spin.GetPos(); //
获取Spin控件当前值
}

UpdateData()
对于可以接收数据的控件,如编辑控件来说,UpdateData()函数至关重要。当控件内容发生变化时,对应的控件变量的值并没有跟着变化,同样,当控件变量值变化时,控件内容也不会跟着变。
UpdateData()
函数就是解决这个问题的。
UpdateData(true);
把控件内容装入控件变量
UpdateData(false);
用控件变量的值更新控件
如:有编辑控件IDC_EDIT1,对应的变量为字符串m_Edit1
1
、修改变量值并显示在控件中:
m_Edit1 = _T("结果为50");
UpdateData(false);
2
、读取控件的值到变量中:
ClassWizardIDC_EDIT1添加EN_CHANGE消息处理函数,这个函数在编辑控件内容发生变化时执行。
void CEditView::OnChangeEdit1()
{
UpdateData(true); //
更新变量值
}



其它
如何获取程序所在的路径
也就是获取你这个程序本身所在的路径。
在应用程序类CxxApp的头文件中定义一个变量CString m_exePath;用来放置程序的路径名,在应用程序类CxxAppInitInstance()函数中加入如下语句:
TCHAR m_Path[MAX_PATH];
GetModuleFileName( NULL, m_Path, MAX_PATH ); //
获取程序路径(包括程序名)
int i = 0, j;
while( m_Path[i]!=0 )
{
if( m_Path[i]=='\\' )
j = i;
i++;
}
m_Path[j+1] = '\0';
m_exePath.Format( "%s", m_Path ); //
分离路径名(去掉程序名)
这段程序执行后,字符串变量m_exePath中放置的就是程序所在路径,其中不包括程序名。
获取程序的位置有什么用呢?
1
、打开与应用程序在一起放置的数据文件:
如果你运行程序过程中使用过打开文件对话框打开过其它路径下的文件,这时系统的默认路径就发生了改变,有可能使你原定的数据文件打不开了,如果采用以下方法就可以没问题了:
CFile file;
file.Open( m_exePath+"
数据文件名", CFile::modeRead );
2
、放置程序运行中的临时文件:
同样,当系统的默认路径发生改变后,程序中生成的临时文件就会放得到处都是,成了一个个垃圾文件,采用以下方法可使临时文件只放在程序所在路径下:
CFile file;
file.Open( m_exePath+"
临时文件名", CFile::modeCreate | CFile::modeWrite );
……
程序结束时,用下面的方法删除临时文件:
CFile::Remove( m_exePath+"
临时文件名" );

如何在你的程序中执行其它程序
在自己的程序中调用其它程序的方法有好几种,这里我介绍我用过的两种:
一、WinExec()函数:
一般用法:WinExec(m_PathName,SW_SHOWNORMAL);
m_PathName
为执行程序的路径名,必须为可执行文件。
如:WinExec("C:\\Program Files\\Internet Explorer\\iexplore.exe",SW_SHOWNORMAL);为打开IE浏览器

二、ShellExecute()函数:
一般用法:ShellExecute(NULL,NULL,m_PathName,NULL,_T("c:\\temp"),SW_SHOWNORMAL);
m_PathName
为打开的程序路径名;
_T("c:\\temp")
为工作目录;
WinExec()不同的是ShellExecute()函数也可以打开非可执行文件,比如你指定的文件为.txt,结果会打开记事本装入该文件。我用这种方法调用自己制作的帮助文件(.chm)效果很好。

如果不使用串行化,如何在程序结束时保存文件?
在文档-视图结构中,用串行化自动保存文件在各种VC书上都有介绍。现在的问题是我不使用串行化,而是自己动手保存,当点击窗口的关闭按钮时,如何提示并保存文档。
ClassWizard在文档类(CxxDoc)中添加函数CanCloseFrame(),再在其中加入保存文件的语句就可以了。
例:
//
退出程序
BOOL CEditDoc::CanCloseFrame(CFrameWnd* pFrame)
{
CFile file;
if(b_Flag) //b_Flag
为文档修改标志,在修改文档时将其置为True
{
int t;
t=::MessageBox(NULL,"
文字已经改变,要存盘吗?","警告",
MB_YESNOCANCEL | MB_ICONWARNING); //
弹出提示对话框
if(t==0 || t==IDCANCEL)
return false;
if(t==IDYES)
{
CString sFilter="Text File(*.txt)|*.txt||";
CFileDialog m_Dlg(FALSE,"txt",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,(LPCTSTR)sFilter,NULL); //
定制文件对话框
int k=m_Dlg.DoModal(); //
弹出文件对话框
if(k==IDCANCEL || k==0)
return false;
m_PathName=m_Dlg.GetPathName(); //
获取选择的文件路径名

file.Open(m_PathName,CFile::modeCreate | CFile::modeWrite);
file.Write(m_Text,m_TextLen); //
数据写入文件
file.Close();
}
}
return CDocument::CanCloseFrame(pFrame);
}
这样当你单击窗口上的关闭按钮时,如果数据已修改了,就会弹出一个提示保存数据的对话框,提示你保存数据。
程序中的b_Flag是数据修改标志,应该在修改数据时进行设置,m_Text是准备保存的数据,放在文档内。

POSITION
怎么用?
POSITION
类型数据用于表征各种列表中元素的位置,它类似于数组的下标,但又有所不同。主要区别是:
我们不能访问POSITION型数据的值,也不能对POSITION数据型数据进行加减、比较等运算。
POSITION型数据访问列表时,都是采用迭代法,一般格式为:
POSITION pos; //
定义pos型变量
pos = GetHeadPosition(); //
获取列表起始元素位置
while( pos )
{
x = GetNext(pos); //
获取pos处的列表值,同时修改pos为下一个元素位置
}
GetNext()
就是一种迭代,其格式为:
TYPE GetNext(POSITION& rPosition);
首先,它返回当前pos位置处的元素;再就是把pos值修改为下一个元素位置。这样循环时,可依次取得列表中各元素的值;当到达列表尾时,posNULL,循环结束。
所以使用POSITION型数据时,你不要试图用加减等操作去修改它,只能用GetNext()(向后迭代)或GetPrev()(向前迭代)反复迭代来修改它的值。
如果你想直接到达指定值,还可以用Find()函数或FindIndex()函数获得指定值的POSITION值。
POSITION Find(TYPE Value);
用于在列表中查找值为Value的元素的POSITION值;
POSITION FindIndex(int nIndex);
用于获取列表中第nIndex个元素的POSITION值,nIndex0开始。
如:
pos = FindIndex(5); //
求列表中第5个元素的位置
x = GetNext(pos); //
读取元素的值
总之,POSITION类型在多种涉及列表的类中提供,不同的类提供的函数有所不同,但用法都是类似的。

如何从完整的文件路径中分离文件名和路径名?
从路径中分离文件名:

CString GetFileName(CString pathname)
{
for( int i=pathname.GetLength()-1; i>=0; i-- )
{
if( pathname[i]=='\\' )
break;
}
return pathname.Mid( i+1 );
}
从路径中分离路径名(去除文件名):

CString GetPath(CString pathname)
{
int i = 0, j;
while( i<pathname.GetLength() )
{
if( pathname[i]=='\\' )
j = i;
i++;
}
return pathname.Left( j+1 );
}
 

posted on 2008-04-13 11:37 wrh 阅读(369) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2008年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

统计

常用链接

留言簿(19)

随笔档案

文章档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜