为什么我使用GetSafeHwndexcel函数培训VC会说未定义

  Windows的资源管理器想必大家都用过,该程序的窗口一分为二,左边的窗口显示本机当前所有驱动器以及驱动器中的所有文件夹,当用户单击文件夹后,如果该文件夹下面还有子文件夹,则上层文件夹展开显示下级的文件夹;否则,右边的窗口显示选择文件夹下的文件。那么这个程序是如何实现的呢?为了说明这个问题,本实例打造了一个简易的资源管理器,它实现了Windows资源管理器的主要功能,在显示文件的属性(如文件的文件名、文件的大小、文件的创建时间)的同时,还可以改变文件显示的方式,如大小图标方式、列表方式等。对于Visual C++初学者来说,这个实例和《

》要结合起来细细的学习、消化,这两个实例包含了Visual C++编程中的很多细节知识,如工具栏的处理、树型控件/列表控件的使用、窗口的拆分、字符串的处理等,相信读者朋友可以从中学到很多知识点。本实例代码编译运行后的界面效果如图一所示:

  从上面的界面效果图可以看出,在程序中使用了拆分窗口,在拆分的过程中,左边窗口为CTreeView 类的子类CLeftView,右边的窗口为CListView类的子类CdriveExplorerView。窗口的拆分和CTreeView、CListView类不是本实例讲述的重点,相关的知识在本书的实例中都有介绍,读者朋友可以参阅上述内容及实例的原代码,这里主要介绍程序中一些具体的细节知识。

  资源管理器中一个重要的问题是如何得到本机中的驱动器信息,微软提供的有关驱动器的API函数有GetLogicalDrives(),GetDriveType()。

  对于喜欢操作位和字节的汇编语言使用者来说,GetLogicalDrives()是个很好用的API函数。它以位掩码的形式返回逻辑驱动器。即在一个DWORD类型的返回值中,位0(最小的一位)表示驱动器A,位1表示驱动器B,以此类推。每一个位的状态如果是on,则表示对应的逻辑驱动器存在;否则状态为off,表示对应的逻辑驱动器不存在。大家知道DWORD是一个32位的值,足以包括所有的英文字母,也就是说最多可有26个盘符。

  上述代码实现的仅仅是资源管理器的主要功能,只要能够对CListView、CtreeView等类灵活运用,在此基础上添加些代码还可以在左右两个视之间实现文件或文件夹的拖动功能,这时两个视都应该有它们自己的实现函数来进行拖放操作。只要不设置"SetCapture()、ReleaseCapture()",被拖放的条目就能从原来的视拖放到目的视。如果被拖的条目(鼠标下的)离开了原来的视,那么目的视的WM_MOUSEMOVE消息就获得了该条目的控制条件。具体实现时要注意保证不同的视(原来的视以及目的视)能访问相同的成员变量,解决的办法是在app类里面定义一些共用的成员变量。


图一、资源管理器界面效果图

  Windows的资源管理器想必大家都用过,该程序的窗口一分为二,左边的窗口显示本机当前所有驱动器以及驱动器中的所有文件夹,当用户单击文件夹后,如果该文件夹下面还有子文件夹,则上层文件夹展开显示下级的文件夹;否则,右边的窗口显示选择文件夹下的文件。那么这个程序是如何实现的呢?为了说明这个问题,本实例打造了一个简易的资源管理器,它实现了Windows资源管理器的主要功能,在显示文件的属性(如文件的文件名、文件的大小、文件的创建时间)的同时,还可以改变文件显示的方式,如大小图标方式、列表方式等。对于Visual C++初学者来说,这个实例和《

》要结合起来细细的学习、消化,这两个实例包含了Visual C++编程中的很多细节知识,如工具栏的处理、树型控件/列表控件的使用、窗口的拆分、字符串的处理等,相信读者朋友可以从中学到很多知识点。本实例代码编译运行后的界面效果如图一所示:

  从上面的界面效果图可以看出,在程序中使用了拆分窗口,在拆分的过程中,左边窗口为CTreeView 类的子类CLeftView,右边的窗口为CListView类的子类CdriveExplorerView。窗口的拆分和CTreeView、CListView类不是本实例讲述的重点,相关的知识在本书的实例中都有介绍,读者朋友可以参阅上述内容及实例的原代码,这里主要介绍程序中一些具体的细节知识。

  资源管理器中一个重要的问题是如何得到本机中的驱动器信息,微软提供的有关驱动器的API函数有GetLogicalDrives(),GetDriveType()。

  对于喜欢操作位和字节的汇编语言使用者来说,GetLogicalDrives()是个很好用的API函数。它以位掩码的形式返回逻辑驱动器。即在一个DWORD类型的返回值中,位0(最小的一位)表示驱动器A,位1表示驱动器B,以此类推。每一个位的状态如果是on,则表示对应的逻辑驱动器存在;否则状态为off,表示对应的逻辑驱动器不存在。大家知道DWORD是一个32位的值,足以包括所有的英文字母,也就是说最多可有26个盘符。

  上述代码实现的仅仅是资源管理器的主要功能,只要能够对CListView、CtreeView等类灵活运用,在此基础上添加些代码还可以在左右两个视之间实现文件或文件夹的拖动功能,这时两个视都应该有它们自己的实现函数来进行拖放操作。只要不设置"SetCapture()、ReleaseCapture()",被拖放的条目就能从原来的视拖放到目的视。如果被拖的条目(鼠标下的)离开了原来的视,那么目的视的WM_MOUSEMOVE消息就获得了该条目的控制条件。具体实现时要注意保证不同的视(原来的视以及目的视)能访问相同的成员变量,解决的办法是在app类里面定义一些共用的成员变量。


图一、资源管理器界面效果图

(1)如何通过代码获得应用程序主窗口的指针?

|SWP_NOAORDER)(15)通用控件的显示窗口MFC提供了几个CView派生的视窗类,封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。(16)重置窗口的大小调用CWnd: )(17)如何单击除了窗口标题栏以外的区域使窗口移动当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数,如果函数返回HTCLIENT nHitTest}上述技术有两点不利之处,其一是在窗口的客户区域双击时,窗口将极大;其二,它不适合包含几个视窗的主框窗口。还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。void )如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化,在以后发行的MFC中将文档化。AfxSetWindowText的实现如下:voik )}}(20)如何防止主框窗口在其说明中显示活动的文档名创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名,必须禁止该风格位,可以使用ClassWizard重置CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。(21)如何获取有关窗口正在处理的当前消息的信息调用CWnd: : ,(22)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : )}(24)如何创建一个不规则形状的窗口可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。Class Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。(27)如何创建和使用无模式对话框MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog )}其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : this最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明了应用程序是如何创建无模式对话的:象;无模式对话不是同步的,创建函数调用后立即返回,void CMainFrame : : OnSampleDialog ( )}(28)如何防止主框窗口在其说明中显示活动的文档名创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名,必须禁止该风格位,可以使用ClassWizard重置CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。(29)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:"temp"1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or &stinfo,&procinfo)(31)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : 32先进的静态控件和Microsoft的资源编辑器,在对话框中显示位图是很容易的,只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。(36)如何改变对话或窗体视窗的背景颜色调用CWinApp : : )}需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。首先,给对话基类增加一人成员变量CBursh :class TRUE}(42)为什么旋转按钮控件看起来倒转需要调用CSpinCtrl : : SetRange 设置旋转按钮控件的范围,旋转按钮控件的缺省上限为0,缺省下限为100,这意味着增加时旋转按控件的值由100变为0。下例将旋转按钮控件的范围设置为0到100:BOOL CAboutDlg 按钮时拷贝的数目增加。(43)为什么旋转按钮控件不能自动地更新它下面的编辑控件如果使用旋转按钮的autu buddy特性,则必须保证在对话的标记顺序中buddy窗口优先于旋转按钮控件。从Layout菜单中选择Tab SetIcon时要指定BS_BITMAP或BS_ICON风格。首先,设置按钮的图标属性。然后,当对话初始化时调用CButton: : SetIcon。注意:下例用图标代替位图,使用位图时要小心,因为不知道背景所有的颜色——并非每个人都使用浅灰色。BOOL CSampleDlg : : OnInitDialog ( 风格位和检测框以及按钮来创建一个三态下压按钮。这很容易,只需将检测框和按钮拖拉到对话中并指定属性Push—like即可。不用任何附加程序就可以成为三态下压按钮。(46)如何动态创建控件分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件事:忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按钮控件://In )(47)如何限制编辑框中的准许字符如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指定新的创建标志ES_NUMBERS,它是Windows 95新增加的标志,该标志限制编辑控件只按收数字字符。如果用户需要复杂的编辑控件,可以使用Microsoft 的屏蔽编辑控件,它是一个很有用的OLE定制控件。如果希望不使用OLE 定制控件自己处理字符,可以派生一个CEdit类并处理WM_CHAR消息,然后从编辑控件中过滤出特定的字符。首先,使用ClassWizard建立一个 CEdit的派生类,其次,在对话类中指定一个成员变量将编辑控件分类在OnInitdialog 中调用CWnd: : ))}(48)如何改变控件的颜色有两种方法。其一,可以在父类中指定控件的颜色,或者利用MFC4.0新的消息反射在控件类中指定颜色。当控件需要重新着色时,工作框调用父窗口(通常是对话框)的CWnd: : hbr}然而,由于每个父窗口必须处理通知消息并指定每个控件的绘画属性,所以,这种方法不是完全的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。消息反射允许用户这样做。通知消息首先发送给父窗口,如果父窗口没有处理则发送给控件。创建一个定制彩色列表框控件必须遵循下述步骤。首先,使用ClassWizard ()}现在,控件可以自己决定如何绘画,与父窗口无关。(49)当向列表框中添加多个项时如何防止闪烁调用CWnd::SetRedraw SetBkmode并传送OPAQUE用当前的背景颜色填充背景,或者调用CDC::SetBkMode并传送TRANSPAARENT使背景保持不变,这两种方法都可以设置背景模式。下例设置背景模式为TRANSPARENT,可以两次更新串,用花色带黑阴影更新文本。黑色串在红色串之后,但由于设置了背景模式仍然可见。void CSampleView:: OnDraw DT_SINGLELINE | DT_CENTER | DT_VCENTER)}(55)如何创建一个具有特定点大小的字体可以指定字体逻辑单位的大小,但有时指定字体的点的大小可能会更方便一些。可以如下将字体的点转换为字体的高度:int nHeigth=mulDiv 根据当前选择的字体计算一个串的高度和宽度。如果使用的不是系统字体而是其他字体,则在调用GetTextExtent之前将字体选进设备上下文中是很重要的,否则计算高度和宽度时将依据系统字体,由此得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按钮的大小,按钮的大小由按钮的字体和标题的大小而定。响应消息WM_SETTEXT时调用OnSetText,该消息使用ON_MESSAE宏指令定义的用户自定义消息。LRESULT bResult}(57)如何显示旋转文本只要用户使用TrueType或者GDI笔或字体就可以显示旋转文本(有些硬件设备也支持旋转光栅字体)。LOGFONT结构中的ifEscapement成员指定了文本行和x轴的角度,角度的单位是十分之一度而不是度,例如,ifEscapement为450表示字体旋转45度。为确保所有的字体沿坐标系统的同一方向旋转,一定要设置ifEscapement成员的CLIP_LH_ANGLES位,否则,有些字体可能反向旋转。下例使用了14点Arial字体每间隔15度画一个串。void lParam)}最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。(63)如何确定顶层菜单所占据的菜单行数这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。int (pWnd. nHitTest,message)}(68)如何检索原先的Task Manager应用程序使用的任务列表原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: szDir)(70)在哪儿创建临文件调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。下例说明了如何创建一个临时文件。//get unique temporary 视窗。它有个取消按钮,我需要当用户按取消按钮时可关闭form视窗。我应该如何关闭该文档?调用 OnCloseDocument 函数。(73)如何访问桌面窗口静态函数CWnd:: GetDesktopWindow 32-bit 整型数值,它代表了一种颜色。你可以使用 RGB 函数来初始化 COLORREF。例如:COLORREF color = RGB(0, 255, 0);RGB 函数接收三个 0-255 数值,一个代表红色,一个代表绿色,一个代表蓝色。在上面的例子中,红色和蓝色值都为 0,所以在该颜色中没有红色和蓝色。绿色为最大值 中的颜色对话框,它需要文件。(75)AppWizard所产生的STDAFX文件是干什么用的?它主要是协助产生预编译头文件的。通常你是不需要修改它的。(76)我在我的程序中是了CDWordArray。我向它添加了约10,000个整数,这使得它变得非常非常慢。为什么会这么糟?CDWordArray 是很好用的,只是因为你没有指定数组的最大尺寸。因此,当你添加新元素时,该类会从堆中重新分配空间。不幸的是,该类会在每次插入新元素时都为数组重新分配空间。如果你向它添加了很多新元素,所有这些分配和复制数组的操作会就会使它变慢。解决该问题的方法是,你可以使用 SetSize 函数的第二个参数来改变这种重新分配的频率。例如,如果你把该参数设置为 500,则每次数组空间超出时它才重新分配并添加 500 个新空间,而不是 1 个。这样一来,你就可以不用重新分配而添加了另外 499 个元素空间,这也会大大提高程序的运行速度。(77)我该如何改变MDI框架窗口的子窗口的大小以使在窗口以一定的大小打开?在视中的 OnInitialUpdate 函数中调用 GetParentFrame 函数。GetParentFrame 会返回一指向一保存有该视的框架窗口的指针。然后调用在框架窗口上调用 MoveWindow。(78)在我的程序的某些部分,我可以调用 MessageBox 函数来建立一个信息对话框,例如在视类中。但是,在其它部分我却不能,如文档类中。为什么?我怎样才能在我的应用程序类中建立一个信息对话框?MessageBox 函数来自 CWnd 类,所以你只能在从 CWnd 继承的类 ( 如 CView ) 中调用它。但是,MFC 也提供了 AfxMessageBox 函数,你可以在任何地方调用它。(79)我需要在我的程序中设置全局变量,以使文档中的所有类都能访问。我应该吧它放到哪儿?把该变量放到该应用程序类的头文件中的 attribute 选项 ( 不是 Project 菜单中的 Execute 选项 ) 来运行你的应用程序,MFC 应该在程序终止时报告内存漏洞。如果没有,那么试试运行 MFC Tracer 工具程序 ( 在 VC++ 程序组中 ),并启动跟踪。然后返回应用程序。(81)我怎样才能在我的应用程序中循环浏览已经打开的文档?使用CDocTemplate中未公开的GetFirstDocPosition()和GetNextDoc()函数。(82)才能在我的应用程序中循环浏览已经打开的视?使用 CDocument ;(86)我应该如何改变视窗口的大小?因为视窗口实际上是框架窗口的子窗口,所以你必须改变框架窗口的大小,而不是改变视窗口。使用 CView 类中的 GetParentFrame() 函数获得指向框架窗口的指针,然后调用 MoveWindow() 函数来改变框架的大小。这会使变尺寸的视充满框架窗口。(87)我有一无模式对话框。我怎样才能在窗口退出时删除CDialog对象?把“delete this”加到 PostNcDestroy 中。这主要用在需要自动删除对象的场合。(88)为什么把“delete 后,甚至在窗口建立失败之后调用的。(89)File菜单中的MRU列表是从哪儿来的?列表中的名字放在哪儿了?我怎样才能改变列表中项目的最大值?在应用程序类的 InitInstance 函数中对 LoadStdProfileSettings 的调用中。该调用接受一个参数 ( 在缺省情况下如果没有传递值则为 4 )。MRU 文件名是从 INI ),则你就改变了所装如文件名的最大值。(90)我在菜单中添加了新的项。但是,当我选该项时,在状态栏上没有出现任何提示信息。为什么?打开资源文件中的菜单模板。打开新菜单选项的属性对话框。在对话框的底部的 Prompt 编辑框中,你可以如下指定状态栏上的提示信息和工具栏上的提示信息 ( 如果你已经建立的工具栏按钮 ):Status bar string"nFlying tag(91)我怎样才能在应用程序的缺省系统菜单中加上一些东西?系统菜单与其它菜单类似,你可以添加或删除项目,这需要使用 CMenu 类的成员函数。下面的代码在你的系统菜单后面添加一个新菜单项:CMenu 类。(92)我建立了一个对话框。但是当我显示该对话框时,第一个编辑框总是不能获得焦点,我必须单击它来使它获得焦点。我怎样才能使第一个编辑框在对话框打开时就获得焦点?打开资源编辑器中的对话框模板。在 Layout 菜单中选择 Tab Order 选项。按你的需求单击对话框中的控制来重新排列这些控制的 tab view添加文档模板。我先建立了对话框模板,然后使用ClassWizard建立了基于CFormView的新类,它也是从CDocument继承来的。我还建立了相应的资源并在InitInstance中添加了新的文档模板。但是,当我试图运行该程序时,出现了Assertion信息。为什么?form 的对话框模板需要些特殊设置以便可用于 CFromView。确保这些设置的最简单方法是使用 AppWizard 来建立 CFormView 应用程序,并查看 AppWizard 所建立的对话框模板所选择的Styles Properties。你会发现该对话框模板具有下列样式:没有标题栏、不可见和“Child”。把你的 form view 的对话框属性变成这样就可以了。(95) 我在一对话框中有一列表框,我需要tabbed列表框中的项目。但是,当我处理含有tab字符(用AddString添加的)的列表项时,tab被显示成小黑块而没有展开。哪儿出错了?在对话框模版中,打开列表框的属性。确保选择了“Use Tabstops” 样式。然后,确保在对话框类中 OnInitDialog 函数中调用 SetTabStops。(96) 我建立了一个应用程序,并使用了CRecordset类。但是,当我运行该程序时,它试图要访问数据库,并给出“Internal Application Error”对话框。我应该怎样做?通常情况下,当你的程序中向数据库发送信息的 SQL 的单引号,则不会出现问题。当你看到“Internal Application Error”时,最好检查一下试图要发送给数据库的 SQL 语句。(97) 我用ClassWizard建立了一个类。但是,我把名字取错了,我想把它从项目中删除,应该如何做?在 ClassWizard 对话框关闭后,用文件管理器删除新类的 H 和 CPP 文件。然后打开 ClassWizard,它会提示丢失了两个文件,并询问你该如何做。你可以选择从项目中删除这两个问的按钮。(98) 当我打开应用程序中的窗口时,我要传递该窗口的矩形尺寸。该矩形指定了窗口的外围大小,但是当我调用GetClientRect时,所得到的尺寸要比所希望的值要小(因为工具栏和窗口边框的缘故)。有其它方法来计算窗口的尺寸吗?参见 CWnd::CalcWindowRect。(99) 我在文档类中设置了一个整型变量。但是,当我试图把该变量写入Serialize函数中的archive文件中时,出现了类型错误。而文档中的其它变量没有问题。为什么?archive 类只重载某些类型的 >> 和 << 操作符。“int”类型没有在其中,也许是因为 如何只存储文档的某一部分?我只想存储文档的某一部分,能否象使用文件一样使用文档?(也就是有定位函数).将每个CArchive类设置为CFile类的派生类,这样你就能使用Seek等成员函数.(103) 保存工具条菜单有bug吗?使用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动的,重起应用程序时它会出现在左上角,而它固定在屏幕其它位置时,下一次启动就会出现在该位置,这是什么原因?你试试这个PToolBar->Create(this,...,ID_MYTOOLBAR);你的工具条需要包括id,而不是象默认的工具条那样.(104) Tip of the day的bug我创建了一个简单的mdi应用程序,使用.BSF(自定义的文档扩展名)作为它的文档我保存一个foo.bsf文档后,可以在资源管理器中双击该文件打开mdi应用程序同时打开foo.bsf文档.但当我给mdi应用程序加上a tip of the 如何可以让我的程序可以显示在其它的窗口上面?让用户选择"总是在最上面"最好是在系统菜单里加入一个选项.可以通过修改WM_SYSCOMMAND消息来发送用户的选择.菜单的命令标识(id)会作为一个参数传给OnSysCommand().要定义标识(id),将如下代码加入到CMainFrame.CPP中:#define 如何控制窗口框架的最大最小尺寸?要控制一个框架的的最大最小尺寸,你需要做两件事情.在CFrameWnd的继承类中处理消息WM_GETMINMAXINFO,结构MINMAXINFO设置了整个窗口类的限制,因此记住要考虑工具条,卷动条等等的大小.// 最大最小尺寸的象素点 - 示例#define MINX 如何改变窗口框架的颜色?MDI框架的客户区被另一个窗口的框架所覆盖.为了改变客户区的背景色,你需要重画这个客户窗口.为了做到这点,你要处理消息WM_ERASEBKND产生一个新类,从CWnd继承,姑且称之为CMDIClient.给它加上一个成员变量,#include "MDIClient.h"class |SWP_NOAORDER)(15)通用控件的显示窗口MFC提供了几个CView派生的视窗类,封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。(16)重置窗口的大小调用CWnd: )(17)如何单击除了窗口标题栏以外的区域使窗口移动当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数,如果函数返回HTCLIENT nHitTest}上述技术有两点不利之处,其一是在窗口的客户区域双击时,窗口将极大;其二,它不适合包含几个视窗的主框窗口。还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。void )如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化,在以后发行的MFC中将文档化。AfxSetWindowText的实现如下:voik )}}(20)如何防止主框窗口在其说明中显示活动的文档名创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名,必须禁止该风格位,可以使用ClassWizard重置CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。(21)如何获取有关窗口正在处理的当前消息的信息调用CWnd: : ,(22)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : )}(24)如何创建一个不规则形状的窗口可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。Class Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。(27)如何创建和使用无模式对话框MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog )}其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : this最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明了应用程序是如何创建无模式对话的:象;无模式对话不是同步的,创建函数调用后立即返回,void CMainFrame : : OnSampleDialog ( )}(28)如何防止主框窗口在其说明中显示活动的文档名创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名,必须禁止该风格位,可以使用ClassWizard重置CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。(29)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:"temp"1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or &stinfo,&procinfo)(31)如何在代码中获取工具条和状态条的指针缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : 32先进的静态控件和Microsoft的资源编辑器,在对话框中显示位图是很容易的,只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。(36)如何改变对话或窗体视窗的背景颜色调用CWinApp : : )}需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。首先,给对话基类增加一人成员变量CBursh :class TRUE}(42)为什么旋转按钮控件看起来倒转需要调用CSpinCtrl : : SetRange 设置旋转按钮控件的范围,旋转按钮控件的缺省上限为0,缺省下限为100,这意味着增加时旋转按控件的值由100变为0。下例将旋转按钮控件的范围设置为0到100:BOOL CAboutDlg 按钮时拷贝的数目增加。(43)为什么旋转按钮控件不能自动地更新它下面的编辑控件如果使用旋转按钮的autu buddy特性,则必须保证在对话的标记顺序中buddy窗口优先于旋转按钮控件。从Layout菜单中选择Tab SetIcon时要指定BS_BITMAP或BS_ICON风格。首先,设置按钮的图标属性。然后,当对话初始化时调用CButton: : SetIcon。注意:下例用图标代替位图,使用位图时要小心,因为不知道背景所有的颜色——并非每个人都使用浅灰色。BOOL CSampleDlg : : OnInitDialog ( 风格位和检测框以及按钮来创建一个三态下压按钮。这很容易,只需将检测框和按钮拖拉到对话中并指定属性Push—like即可。不用任何附加程序就可以成为三态下压按钮。(46)如何动态创建控件分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件事:忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按钮控件://In )(47)如何限制编辑框中的准许字符如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指定新的创建标志ES_NUMBERS,它是Windows 95新增加的标志,该标志限制编辑控件只按收数字字符。如果用户需要复杂的编辑控件,可以使用Microsoft 的屏蔽编辑控件,它是一个很有用的OLE定制控件。如果希望不使用OLE 定制控件自己处理字符,可以派生一个CEdit类并处理WM_CHAR消息,然后从编辑控件中过滤出特定的字符。首先,使用ClassWizard建立一个 CEdit的派生类,其次,在对话类中指定一个成员变量将编辑控件分类在OnInitdialog 中调用CWnd: : ))}(48)如何改变控件的颜色有两种方法。其一,可以在父类中指定控件的颜色,或者利用MFC4.0新的消息反射在控件类中指定颜色。当控件需要重新着色时,工作框调用父窗口(通常是对话框)的CWnd: : hbr}然而,由于每个父窗口必须处理通知消息并指定每个控件的绘画属性,所以,这种方法不是完全的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。消息反射允许用户这样做。通知消息首先发送给父窗口,如果父窗口没有处理则发送给控件。创建一个定制彩色列表框控件必须遵循下述步骤。首先,使用ClassWizard ()}现在,控件可以自己决定如何绘画,与父窗口无关。(49)当向列表框中添加多个项时如何防止闪烁调用CWnd::SetRedraw SetBkmode并传送OPAQUE用当前的背景颜色填充背景,或者调用CDC::SetBkMode并传送TRANSPAARENT使背景保持不变,这两种方法都可以设置背景模式。下例设置背景模式为TRANSPARENT,可以两次更新串,用花色带黑阴影更新文本。黑色串在红色串之后,但由于设置了背景模式仍然可见。void CSampleView:: OnDraw DT_SINGLELINE | DT_CENTER | DT_VCENTER)}(55)如何创建一个具有特定点大小的字体可以指定字体逻辑单位的大小,但有时指定字体的点的大小可能会更方便一些。可以如下将字体的点转换为字体的高度:int nHeigth=mulDiv 根据当前选择的字体计算一个串的高度和宽度。如果使用的不是系统字体而是其他字体,则在调用GetTextExtent之前将字体选进设备上下文中是很重要的,否则计算高度和宽度时将依据系统字体,由此得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按钮的大小,按钮的大小由按钮的字体和标题的大小而定。响应消息WM_SETTEXT时调用OnSetText,该消息使用ON_MESSAE宏指令定义的用户自定义消息。LRESULT bResult}(57)如何显示旋转文本只要用户使用TrueType或者GDI笔或字体就可以显示旋转文本(有些硬件设备也支持旋转光栅字体)。LOGFONT结构中的ifEscapement成员指定了文本行和x轴的角度,角度的单位是十分之一度而不是度,例如,ifEscapement为450表示字体旋转45度。为确保所有的字体沿坐标系统的同一方向旋转,一定要设置ifEscapement成员的CLIP_LH_ANGLES位,否则,有些字体可能反向旋转。下例使用了14点Arial字体每间隔15度画一个串。void lParam)}最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。(63)如何确定顶层菜单所占据的菜单行数这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。int (pWnd. nHitTest,message)}(68)如何检索原先的Task Manager应用程序使用的任务列表原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: szDir)(70)在哪儿创建临文件调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。下例说明了如何创建一个临时文件。//get unique temporary 视窗。它有个取消按钮,我需要当用户按取消按钮时可关闭form视窗。我应该如何关闭该文档?调用 OnCloseDocument 函数。(73)如何访问桌面窗口静态函数CWnd:: GetDesktopWindow 0);RGB函数接收三个0-255数值,一个代表红色,一个代表绿色,一个代表蓝色。在上面的例子中,红色和蓝色值都为0,所以在该颜色中没有红色和蓝色。绿色为最大值255。所以该颜色为绿色。0,0,0为黑色,255,255,255 为白色。另一种初始化COLORREF的方法如下所示:CColorDialog colorDialog.GetColor();}这段代码使用了MFC中的颜色对话框,它需要文件。(75)AppWizard所产生的STDAFX文件是干什么用的?它主要是协助产生预编译头文件的。通常你是不需要修改它的。(76)我在我的程序中是了CDWordArray。我向它添加了约10,000个整数,这使得它变得非常非常慢。为什么会这么糟?CDWordArray是很好用的,只是因为你没有指定数组的最大尺寸。因此,当你添加新元素时,该类会从堆中重新分配空间。不幸的是,该类会在每次插入新元素时都为数组重新分配空间。如果你向它添加了很多新元素,所有这些分配和复制数组的操作会就会使它变慢。解决该问题的方法是,你可以使用SetSize函数的第二个参数来改变这种重新分配的频率。例如,如果你把该参数设置为500,则每次数组空间超出时它才重新分配并添加500个新空间,而不是1 个。这样一来,你就可以不用重新分配而添加了另外499个元素空间,这也会大大提高程序的运行速度。(77)我该如何改变MDI框架窗口的子窗口的大小以使在窗口以一定的大小打开?在视中的OnInitialUpdate函数中调用GetParentFrame函数。GetParentFrame会返回一指向一保存有该视的框架窗口的指针。然后调用在框架窗口上调用MoveWindow。(78)在我的程序的某些部分,我可以调用 MessageBox 函数来建立一个信息对话框,例如在视类中。但是,在其它部分我却不能,如文档类中。为什么?我怎样才能在我的应用程序类中建立一个信息对话框?MessageBox函数来自CWnd 类,所以你只能在从CWnd继承的类(如CView )中调用它。但是,MFC也提供了AfxMessageBox函数,你可以在任何地方调用它。(79)我需要在我的程序中设置全局变量,以使文档中的所有类都能访问。我应该吧它放到哪儿?把该变量放到该应用程序类的头文件中的attribute处。然后,在程序的任何地方,你都可以用下面的方法来访问该变量:CMyApp 应该在程序终止时报告内存漏洞。如果没有,那么试试运行MFC Tracer工具程序(在VC++程序组中),并启动跟踪。然后返回应用程序。(81)我怎样才能在我的应用程序中循环浏览已经打开的文档?使用CDocTemplate中未公开的GetFirstDocPosition()和GetNextDoc()函数。(82)才能在我的应用程序中循环浏览已经打开的视?使用CDocument ;(86)我应该如何改变视窗口的大小?因为视窗口实际上是框架窗口的子窗口,所以你必须改变框架窗口的大小,而不是改变视窗口。使用CView类中的GetParentFrame()函数获得指向框架窗口的指针,然后调用MoveWindow()函数来改变框架的大小。这会使变尺寸的视充满框架窗口。(87)我有一无模式对话框。我怎样才能在窗口退出时删除CDialog对象?把“delete ),则没有窗口处来发送WM_NCDESTROY消息。PostNcDestroy是在对象窗口被完全删除,在OnNcDestroy后,甚至在窗口建立失败之后调用的。(89)File菜单中的MRU列表是从哪儿来的?列表中的名字放在哪儿了?我怎样才能改变列表中项目的最大值?在应用程序类的InitInstance函数中对LoadStdProfileSettings的调用中。该调用接受一个参数(在缺省情况下如果没有传递值则为4 ),则你就改变了所装如文件名的最大值。(90)我在菜单中添加了新的项。但是,当我选该项时,在状态栏上没有出现任何提示信息。为什么?打开资源文件中的菜单模板。打开新菜单选项的属性对话框。在对话框的底部的Prompt 编辑框中,你可以如下指定状态栏上的提示信息和工具栏上的提示信息(如果你已经建立的工具栏按钮):Status bar string"nFlying tag(91)我怎样才能在应用程序的缺省系统菜单中加上一些东西?系统菜单与其它菜单类似,你可以添加或删除项目,这需要使用CMenu类的成员函数。下面的代码在你的系统菜单后面添加一个新菜单项:CMenu *sysmenu;sysmenu = 类。(92)我建立了一个对话框。但是当我显示该对话框时,第一个编辑框总是不能获得焦点,我必须单击它来使它获得焦点。我怎样才能使第一个编辑框在对话框打开时就获得焦点?打开资源编辑器中的对话框模板。在Layout菜单中选择Tab Order 选项。按你的需求单击对话框中的控制来重新排列这些控制的tab顺序。(93)我怎样才能使一个窗口具有“always on view添加文档模板。我先建立了对话框模板,然后使用ClassWizard建立了基于CFormView的新类,它也是从CDocument继承来的。我还建立了相应的资源并在InitInstance中添加了新的文档模板。但是,当我试图运行该程序时,出现了Assertion信息。为什么?form的对话框模板需要些特殊设置以便可用于CFromView。确保这些设置的最简单方法是使用 AppWizard来建立CFormView应用程序,并查看AppWizard 所建立的对话框模板所选择的Styles Properties。你会发现该对话框模板具有下列样式:没有标题栏、不可见和“Child”。把你的form view的对话框属性变成这样就可以了。(95)我在一对话框中有一列表框,我需要tabbed列表框中的项目。但是,当我处理含有tab字符(用AddString添加的)的列表项时,tab被显示成小黑块而没有展开。哪儿出错了?在对话框模版中,打开列表框的属性。确保选择了“Use Tabstops” 样式。然后,确保在对话框类中OnInitDialog函数中调用SetTabStops。(96)我建立了一个应用程序,并使用了CRecordset类。但是,当我运行该程序时,它试图要访问数据库,并给出“Internal Application Error”对话框。我应该怎样做?通常情况下,当你的程序中向数据库发送信息的SQL语句出现问题时才出现该对话框。例如,参见下面的例子:set.m_strFilter = "(ZipCode = '27111')";如果 ZipCode 列被定义为字符串时不会出现问题,如果定义为long,则会出现“Internal Application Error”对话框,这是由于类型不匹配的缘故。如果你删除27111的单引号,则不会出现问题。当你看到“Internal Application Error”时,最好检查一下试图要发送给数据库的SQL语句。(97)我用ClassWizard建立了一个类。但是,我把名字取错了,我想把它从项目中删除,应该如何做?在ClassWizard对话框关闭后,用文件管理器删除新类的H 和CPP文件。然后打开ClassWizard,它会提示丢失了两个文件,并询问你该如何做。你可以选择从项目中删除这两个问的按钮。(98)当我打开应用程序中的窗口时,我要传递该窗口的矩形尺寸。该矩形指定了窗口的外围大小,但是当我调用GetClientRect时,所得到的尺寸要比所希望的值要小(因为工具栏和窗口边框的缘故)。有其它方法来计算窗口的尺寸吗?参见CWnd::CalcWindowRect。(99)我在文档类中设置了一个整型变量。但是,当我试图把该变量写入Serialize函数中的archive文件中时,出现了类型错误。而文档中的其它变量没有问题。为什么?archive NT/95有所不同的缘故吧。“long”类型得到了支持,所以你可以把int类型改成long型。参见MFC帮助文件中CArchive类。(100)如何控制菜单的大小?我用MFC的CMenu生成了一个动态菜单(例如File,Edit,View...Help), 我想控制这个菜单的大小(长+高).方法一:查找 hDC);}/*此时,size.cy即为高度,size.cx为宽度,你可以给菜单加上自定义的高度和宽度,通过比较,我发现宽度为4比较合适。*/(101)改变LVIS_SELECTED的状态颜色?我想将CListCtrl项和CTreeCtrl项在LVIS_SELECTED状态时的颜色变灰.方法一:查找函数CustomDraw,它是IE4提供的公共控制,允许有你自己的代码.方法二:生成一个draw控件,然后在DrawItem中处理文本颜色.(102)如何只存储文档的某一部分?我只想存储文档的某一部分,能否象使用文件一样使用文档?(也就是有定位函数).将每个CArchive类设置为CFile类的派生类,这样你就能使用Seek等成员函数.(103)保存工具条菜单有bug吗?使用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动的,重起应用程序时它会出现在左上角,而它固定在屏幕其它位置时,下一次启动就会出现在该位置,这是什么原因?你试试这个PToolBar->Create(this,...,ID_MYTOOLBAR);你的工具条需要包括id,而不是象默认的工具条那样.(104)Tip of the day的bug我创建了一个简单的mdi应用程序,使用.BSF(自定义的文档扩展名)作为它的文档我保存一个foo.bsf文档后,可以在资源管理器中双击该文件打开mdi应用程序同时打开foo.bsf文档.但当我给mdi应用程序加上a tip of the lParam);}}(106)如何控制窗口框架的最大最小尺寸?要控制一个框架的的最大最小尺寸,你需要做两件事情.在CFrameWnd的继承类中处理消息WM_GETMINMAXINFO,结构MINMAXINFO设置了整个窗口类的限制,因此记住要考虑工具条,卷动条等等的大小.// CFrameWnd::PreCreateWindow(cs);}(107)如何改变窗口框架的颜色?MDI框架的客户区被另一个窗口的框架所覆盖.为了改变客户区的背景色,你需要重画这个客户窗口.为了做到这点,你要处理消息WM_ERASEBKND产生一个新类,从CWnd继承,姑且称之为CMDIClient.给它加上一个成员变量,#include FALSE;}然后就可以加入对消息WM_ERASEBKGND的处理了.(108)如何将应用程序窗口置于屏幕正中?要将你的应用程序窗口放置在屏幕正中央,只须在MainFrame的OnCreate函数中加入:CenterWindow(

我要回帖

更多关于 excel函数培训 的文章

 

随机推荐