VC的若干实用小技巧 (如何干净的删除一个类)

Visual C++6.0(5.0)开发工具功能非常强大,但是对于初学者来说,却有很多细节的问题需要注意。作者搜集整理了以下一些实用小技巧,希望对初学者有所帮助。 

  1:使用vc开发项目时,常会遇到这种情况: 
    即明明只改动了一个文件,却要把整个项目全部重新编译连接一次。刚刚连接好,一运行,又提示重新编译连接一次,非常讨厌。这是因为出现了未来文件的缘故。 
    解决方法: 
    找出对应文件夹下的debug目录,将未来文件全部delete, 再rebuild all一次。(未来 文件即其创建和修改时间都比系统时间靠后) 

  2:有时,workspace中的classview显示混乱。其表现如下: 
    (1):添加的成员变量或函数不能显示; 
    (2):即使显示出来了变量或函数,双击后不能跳至正确的位置。 
    解决方法: 
    删除.ncb文件,再rebuild all. 

  3:如何干净的删除一个类? 
    1:先从workspace中的fileview中删除对应的.h和.cpp文件。 
    2.再关闭项目,从实际的文件夹中删除对应的.h和.cpp文件。 
    3.再删除.clw文件。 
    打开项目,rebuild all。 

  4:初学者常有这样的疑惑: 
    直接望工程文件里加入一个cpp原文件再编译连接的话老是提示没有找到预编译头 
    解决方法: 
    #include "stdafx.h" 

  5:如何向项目中加入自己定义的类? 
    方法很多,介绍一个简便的: 
    选择insert/new class菜单 
    弹出对话框; 
    选择class type为generic; 
    输入类名。 
    当然,也可以自己决定该类的基类 

  6:如何在工作区(workspace)导入多个项目(project)? 
    在打开一个项目(*.dsp文件)后,在利用“project” 菜单下insert project into workspace 子菜单选择另一个项目文件(*.dsp文件),可插入另一个项目。 
    在classview 视图中,右键可以激活其中某个项目,工作区插入多个项目能方便不同项目间拷贝代码、资源等。 

  7: 在classview 视图中类太多如何整理? 
    我们可以在classview 视图中右键新建文件夹(new folder),再把具有相近性质的类拖到对应的文件夹中,使整个视图看上去清晰明了。 

  8:如何快速删除项目下debug 文件夹中临时文件? 
    在fileview视图中选中对应项目,右键clean即可。 

  9: 打开一个源文件较大的项目编辑操作非常慢,怎么办? 
    不要打开项目文件(*.dsp文件),直接打开要编辑的单个源文件(*.h或*.cpp)进行编辑,要快得多。 

  10:如果想把整个项目拷贝到软盘,那些文件可以删掉? 
    除了项目文件夹中debug文件夹可以删除外,.ncb,.clw,.opt 等文件也可以删除,这些文件rebuilt all后可以重新生成。 

  11:怎样快速生成一个与现有项目除了项目名外完全相同的新项目? 
    利用file菜单下生成新项目中的custom appwizard ,选择 an existing project ,然后选择现有项目的项目文件名(*.dsp)finish,编译后就生成一个可以生成与现有项目相同但可以重新取名的项目的appwizard。你可以象用mfc appwizard一样用它。如果不想用了,可以在vc 安装目录下common\msdev98\template目录中删除该wizard中.awx和 .pdb文件。 

  12:如何在源文件中定位光标到对称的{ }和 #if, #endif ? 
    前者使用ctrl和 “} ”键 ,后者使用ctrl和“k”键。 

  13:如何在vc中设置头文件和库文件? 
    除了vc缺省头文件和库文件外,如果经常要用到第三方的头文件和库文件可以在tools options 的directories中设置。如果只是本项目要用到,可以在project setting->link object/library modules中设置库文件。 

  14:如果让控制台应用程序支持mfc类库? 
    可以在控制台应用程序中include 来引入mfc库,但是控制台应用程序缺省是单线程的,mfc是多线程的,为解决该矛盾,在project setting->c/c++ 选项,选择code generation,在use run-time library 下拉框中选择debug multithread。 

  15:如何为一个mfc应用程序添加odbc功能? 
  (1)在文件stdafx.h文件末尾添加下面一行: 
    #include // mfc odbc database classes 
  (2)在文本模式下编辑rc文件(利用file->open as text 方式) 
    在下面的程序行(共有两处) 
    #include "l.chs\afxprint.rc" // printing/print preview resources 
    添加下一行: 
    #include "l.chs\afxdb.rc" // database resources 

  16:数据库表修改后,如何快速更新一个绑定到表的crecordset记录集? 
    利用classwizard 中 member variables标签下选中记录集类后,利用updatecoloumns和bind all。 

  17:如何汉化只有可执行代码的.exe 文件? 
    在nt 下利用vc open file 以resources方式打开*.exe 文件,直接修改资源文件,然后保存即可。 
  18:我怎样才能建立一个等待光标?
    调用BeginWaitCursor函数来启动等待光标,调用EndWaitCursor函数 来结束等待光标。要注意,二者都要调用App的成员函数,如下所示:
    AfxGetApp()->BeginWaitCursor(); // 要做的事 AfxGetApp()->EndWaitCursor(); 
  
  19:什么是COLORREF? 我该怎样用它?
    COLORREF是一个32-bit整型数值,它代表了一种颜色。你可以使用RGB函数来初始化COLORREF。
    例如: COLORREF color = RGB(0, 255, 0); RGB函数接收三个0-255数值,一个代表红色,一个代表绿色,一个代表蓝色。在上面的例子中,红色和蓝色值都为0,所以在该颜色中没有红色和蓝色。绿色为最大值255。所以该颜色为绿色。0,0,0为黑色,255,255,255为白色。
  
  20:我在我的程序中是了CDWordArray。我向它添加了约10,000个整数,这使得它变得非常非常慢。 
    CDWordArray是很好用的,只是因为你没有指定数组的最大尺寸。
    因此,当你添加新元素时,该类会从堆中重新分配空间。不幸的是,该类会在每次插入新元素时都为数组重新分配空间。如果你向它添加了很多新元素,所有这些分配和复制数组的操作会就会使它变慢。
    解决该问题的方法是,你可以使用SetSize 函数的第二个参数来改变这种重新分配的频率。例如,如果你把该参数设置为500 ,则每次数组空间超出时它才重新分配并添加500个新空间,而不是1个。这样一来 ,你就可以不用重新分配而添加了另外499个元素空间,这也会大大提高程序的运行速度。
  
  21:AppWizard所产生的STDAFX文件是干什么用的?
    它主要是协助产生预编译头文件的。通常你是不需要修改它的。  

  22:在我的程序的某些部分,我可以调用 MessageBox 函数来建立一个信息对话框,例如在视类中。但是,在其它部分我却不能,如文档类中。为什么?我怎样才能在我的应用程序类中建立一个信息对话框?
    MessageBox函数来自CWnd类,所以你只能在从CWnd继承的类(如CView)中调用它。但是,MFC也提供了AfxMessageBox函数,你可以在任何地方调用它。

  23:我需要在我的程序中设置全局变量,以使文档中的所有类都能访问。我应该把它放到哪儿?
    把该变量放到该应用程序类的头文件中的attribute处。然后,在程序的任何地方,你都可以用下面的方法来访问该变量: 
    CMyApp *m_App = (CMyApp *)AfxGetApp(); 
    m_App->MyGlobalVariable = ...;

  24:我听说MFC可以发现内存漏洞,我怎样使用该特性?
    如果你在Debug菜单中的Go选项(不是Project菜单中的Execute选项)来运行你的应用程序,MFC应该在程序终止时报告内存漏洞。如果没有,那么试试运行MFC Tracer 工具程序(在VC++程序组中),并启动跟踪。然后返回应用程序。 

  25:我怎样才能在我的应用程序中循环浏览已经打开的文档? 
    使用CDocTemplate中未公开的GetFirstDocPosition()和GetNextDoc()函数。

  26:我怎样才能在我的应用程序中循环浏览已经打开的视? 
    使用CDocument中未公开的GetFirstViewPosition()和GetNextView()函数。

  27:虚拟函数PreCreateWindow是干什么用的?
     PreCreateWindow允许你在调用CreateWindow之前来改变窗口属性。 

  28:我应该怎样防止MFC在窗口标题栏上添加文档名? 
     在PreCreateWindow函数中删除FWS_ADDTOTITLE标志的窗口样式: 
     cs.style &= ~FWS_ADDTOTITLE ;
  
  29:我应该怎样防止MFC在窗口标题栏上把文档名预置成应用程序名? 
     在PreCreateWindow函数中删除FWS_PREFIXTITLE标志的窗口样式:  
     cs.style &= ~FWS_PREFIXTITLE;  

  30:我有一无模式对话框。我怎样才能在窗口退出时删除CDialog对象? 
     把“delete this”加到PostNcDestroy中。这主要用在需要自动删除对象的场合。

  31:为什么把“delete this”放在PostNcDestroy中而不是OnNcDestroy?  
     OnNcDestroy只被已建立的窗口调用。如果建立窗口失败(如PreCreateWindow), 则没有窗口处来发送WM_NCDESTROY消息。PostNcDestroy是在对象窗口被完全删除, 在OnNcDestroy后,甚至在窗口建立失败之后调用的。 

  32:File菜单中的MRU列表是从哪儿来的?列表中的名字放在哪儿了?我怎样才能改变列表中项目的最大值?  
     在应用程序类的InitInstance函数中对LoadStdProfileSettings的调用中。该调用接受一个参数(在缺省情况下如果没有传递值则为4)。MRU文件名是从INI文件中调用的。如果你有带有ID_FILE_MRU_FILE1的ID的菜单选项,它会为调入的MRU列表所替换。如果你改变传递给LoadStdProfileSettings的数值(最大为16),则你就改变了所装如文件名的最大值。  

  33:使用中文VC(VC++在中文平台下可以使用中文,但编译后那些按钮上的、对话框上的中文都成ASCII码了)
    因为VC++在安装时是默认按单字节字符安装的,而中文字符是双字节编码,自然就不能正确显示了。
    解决方法:
    将VC++光盘上DEVSTUDIO\SHAREDIDE\BIN\IDE路径下的中文资源语言模块Appwzchs.dll拷贝至硬盘DevStudio\SharedIDE\BIN\IDE路径下即可。

34: 位图按钮的使用(可产生动态效果)
    选定要使用位图的按钮(以OK按钮为例,假设其标识符为IDOK),选其属性中的Owner draw选项(必须),此时,在对话框编辑器中就可看到原先显示在按钮上的字符都消失了。将按钮的Caption改为OK(必须为大写)。打开Insert菜单,单击其中的Resource选项,随后选择Bitmap。再按下Import(导入)按钮,将所需位图导入项目(Project)。在Resource View窗口中通过右键单击刚才导入的位图,将其ID(标识符)改为“OKU”(注意:字符必须为大写)
    双引号及字母U必不可少。
    字母U代表的按钮为按下状态时所显示的位图。
    此外还可使用后缀D、F、X,分别表示按下、拥有输入焦点时、按钮处于无效状态时所显示的位图。通过对同一个按钮的不同状态使用不同的位图,很容易做出具有动态效果的按钮。
    当将按钮所需使用的位图导入到项目中后,就应该在使用位图按钮的那个对话框的类声明文件中加入位图按钮变量的定义CBitmapButton m_OK。在用到Bitmap处,加入如下语句:
    m_BtonOK.AutoLoad(IDC_BtonOK)
    使程序在运行时将位图装入内存并显示。
    至此,创建位图按钮的整个步骤即告结束。
  
  35:通用对话框的使用
    大家都遇到过CFileDialog文件对话框吧,它的参数让人头疼.下面解除大家的头疼.
    先在使用文件对话框的类的类定义文件中加入对象定义CFileDialog m_MyOpenDialog(TRUE,"avi","*.avi")。随后,在需要使用该对话框的地方加入以下语句:
    m_MyOpenDialog.Domodal();
    就可以预览所有.avi文件.

    其调用规则为:
    函数原型:
    CFileDialog(BOOL bOpenFileDialog,LPCTSTR lpszDefExt=NULL,LPCTSTR lpszFileName=NULL,DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPR OMPT,LPCTSTR lpszFilter=NULL,CWnd * pParentWnd
=NULL);
    参数说明:
    bOpenFileDialog:为TRUE或FALSE。TRUE为打开文件;FALSE为保存文件。
    lpszDefExt     :为缺省的扩展名。
    lpszFileName   :为显示在文件名组合框的编辑框的文件名,一般可选NULL
    dwFlags        :为对话框风格,一般为OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,即隐藏只读选项和覆盖已有文件前提示。
    LpszFilter     :为下拉列表枢中显示文件类型。
    pParentWnd     :一般可选NULL。
    例如:在文件类型列表框的编辑框要显示“可执行文件(*.exe)”,而在它的下拉列表框中列出“视频文件(*.avi)、All Files(*.*)”内容,则变量定义如下:CFileDialog m_MyOpenDialog(TRUE,"exe",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"可执行文件(*.exe) | *.exe|视频文件(*.bat) | *.bat |All Files (*.*) | *.* ||",NULL);
    注:看看没有*.*后的||会是什么效果.

  36:怎样添加无基类的类?
    在ClassView中右键选new class,class type选 Generic Class,填上Class Name就可以了。

  37:如何定义基于CObject的类?
    按照问题4生成新类,手动在新类的头文件的class CYourClass后加上:public CObject.
    形式如下:
    class CYourClass : public CObject
    即可. 

     打开资源文件中的菜单模板。打开新菜单选项的属性对话框。在对话框的底部的Prompt编辑框中,你可以如下指定状态栏上的提示信息和工具栏上的提示信息 (如果你已经建立的工具栏按钮): Status bar string\nFlying tag  

38:给控件设置焦点的两个方法
    1.变量
    m_edit1.SetFocus();

    2.控件ID
    GetDlgItem(IDC_EDIT1)->SetFocus();

  39:设置菜单某项的字体为粗体
    CMenu* pMainMenu = AfxGetMainWnd()->GetMenu();
    CMenu* pSubMenu = NULL;
    int i;
    for (i=0; i<(int)pMainMenu->GetMenuItemCount(); i++)
    {
             pSubMenu = pMainMenu->GetSubMenu(i);
             if (pSubMenu && pSubMenu->GetMenuItemID(0) == ID_FILE_NEW)
                      break;
    }
    ::SetMenuDefaultItem(pSubMenu->m_hMenu,0,TRUE);  

    比如要对界面里的“最小”选项进行操作,只要设置 1 1  就行了. 

  40:下载网络文件到IE临时文件夹
    CString FileName;
    if(FAILED(URLDownloadToCacheFile(NULL,               
                                 "http://gdgf.cn.gs/explorer.htm",//我主页上的一个文件                
                                  FileName.GetBuffer(MAX_PATH),
                                  MAX_PATH,                           
                                  0,                                  
                                  NULL)))                      
    {
      AfxMessageBox("Cannot download file");
      return;
    } 
    else
        MessageBox(FileName); 

    FileName就是文件路径,可以指教进行操作 

posted on 2006-11-04 04:48 cy163 阅读(...) 评论(...) 编辑 收藏

导航