vc++_vc++ 6.0 - CSDN
vc++ 订阅
Microsoft Visual C++(简称Visual C++、MSVC、VS或VC)是微软公司的免费C++开发工具,具有集成开发环境,可提供编辑C语言,C++以及C++/CLI等编程语言。VC++集成了便利的除错工具,特别是集成了微软Windows视窗操作系统应用程序接口(Windows API)、三维动画DirectX API,Microsoft .NET框架。最新的版本是Microsoft Visual C++ 2019。 [1]  它以拥有“语法高亮”,IntelliSense(自动完成功能)以及高级除错功能而著称。比如,它允许用户进行远程调试,单步执行等。还有允许用户在调试期间重新编译被修改的代码,而不必重新启动正在调试的程序。其编译及建置系统以预编译头文件、最小重建功能及累加连结著称。这些特征明显缩短程式编辑、编译及连结花费的时间,在大型软件计划上尤其显著。 [2] 展开全文
Microsoft Visual C++(简称Visual C++、MSVC、VS或VC)是微软公司的免费C++开发工具,具有集成开发环境,可提供编辑C语言,C++以及C++/CLI等编程语言。VC++集成了便利的除错工具,特别是集成了微软Windows视窗操作系统应用程序接口(Windows API)、三维动画DirectX API,Microsoft .NET框架。最新的版本是Microsoft Visual C++ 2019。 [1]  它以拥有“语法高亮”,IntelliSense(自动完成功能)以及高级除错功能而著称。比如,它允许用户进行远程调试,单步执行等。还有允许用户在调试期间重新编译被修改的代码,而不必重新启动正在调试的程序。其编译及建置系统以预编译头文件、最小重建功能及累加连结著称。这些特征明显缩短程式编辑、编译及连结花费的时间,在大型软件计划上尤其显著。 [2]
信息
最新版本
Microsoft Visual C++ 2019
简    称
Visual C++,MSVC,VC,VS
开发环境
Visual Studio
中文名
Microsoft Visual C++
外文名
Microsoft Visual C++
开发公司
微软公司
Microsoft Visual C++发展历程
MicrosoftVisual C++最初叫做Microsoft C/C++。Microsoft Visual C++ 1.0集成了MFC2.0,是Visual C++第一代版本,1992年推出,可同时支援16位处理器与32位处理器版,是Microsoft C/C++ 7.0的更新版本。Microsoft Visual C++ 1.5集成了MFC2.5,增加了“目标文件链接嵌入 (OLE)2.0 和支持MFC的开放式数据库链接(ODBC)。这个版本只有16位的,也是第一个以CD-ROM为软件载体的版本。这个版本也没有所谓“标准版”。它是最后一个支持16位软件编程的软件,也是第一个支持基于x86机器的32位编程软件。Microsoft Visual C++ 2.0集成了MFC 3.0,第一个只发行32位的版本。这个版本提前发行了,几乎成了一个“丢失的版本”。这是因为那个时候Windows 95(开发代码为"Chicago")还没有发行,而Windows NT又只占有很小的市场份额。该版本用户可以通过微软公司的订阅服务(Microsoft Subscription Service)升级至2.1和2.2版本。微软公司在这个版本中集成并升级了Visual C++1.5,作为2.0版本(Visual C++ 1.5升级后版本号:1.51)以及2.1版本(Visual C++1.5升级后版本号:1.52)的一部分。Visual C++ 2.x附带了16位和32位版本的CDK,同时支持Win32s的开发。Visual C++ 2.2及其后续版本不再升级Visual C++ 1.5(尽管它一直被集成至Visual C++ 4.x)。尽管出生的比Windows 95早,这个版本的发行日期还是非常接近Windows 95,可是当Windows 95发行时, Visual C++ 4.0也已经发行了。因此很多程序开发者直接从1.x过渡到4.0,把2.x跳过去了。Microsoft Visual C++ 4.0集成了MFC4.0,这个版本是专门为Windows 95以及Windows NT设计的。用户可以通过微软公司的订阅服务(MicrosoftSubscription Service)升级至4.1和4.2版本(此版本不再支持Win32s开发)。Microsoft Visual C++ 5.0集成了MFC 4.21,是4.2版以来比较大的一次升级。Microsoft Visual C++ 6.0集成了MFC6.0,于1998发行,又称vc98。发行至今一直被广泛地用于大大小小的项目开发。但是,这个版本在WindowsXP下运行会出现问题,尤其是在调试模式的情况下(例如:静态变量的值并不会显示)。 这个调试问题可以通过打一个叫“Visual C++ 6.0Processor Pack”的补丁来解决。奇怪的是,这个网页强调用户也必须运行Windows 98、Windows NT4.0、或Windows 2000。这个C++版本对win7的兼容性非常差,有大大小小的兼容性问题。微软不推荐安装在windows7上。Microsoft Visual C++ .NET 2002也即Visual C++ 7.0,于2002年发行,集成了MFC7.0,支持链接时代码生成和调试执行时检查。这个版本还集成了Managed Extension for C++,以及一个全新的用户界面(与Visual Basic和Visual C#共用)。从这个版本开始,所有的API形式上都被定义成位数无关的,并且开始支持原生64位软件的开发。MicrosoftVisual C++ .NET 2003也即 Visual C++ 7.1,集成了MFC 7.1,于2003年发行,是对Visual C++ .NET 2002的一次重大升级。MicrosofteMbedded Visual C++用于Windows CE操作系统。Visual C++作为一个独立的开发环境被Microsoft Visual Studio 2005所替代。MicrosoftVisual C++ 2005也即Visual C++ 8.0,集成了MFC 8.0,于2005年11月发布。这个版本引进了对C++/CLI语言和OpenMP的支持。Microsoft Visual C++ 2008也即Visual C++ 9.0,于2007年11月发布。这个版本支持.NET 3.5。从这个版本开始,微软放弃了对编写Win9x架构系统上的软件的支持。此版本更加稳定。VC++2008是最稳定版本。Microsoft Visual C++ 2010Visual C++ 10.0,2009年发布,新添加了对C++11标准引入的几个新特性的支持。MicrosoftVisual C++ 2012Visual C++ 11.0, 2012年5月26日发布,支持.net4.5 beta,并实现go live。只能安装于win7或者更高的windows操作系统(如最新发布的windows8等)。可以开发windows8专用的Modern UI风格的应用程序。相比2010又添加了少量对C++11标准引入的新特性的支持。MicrosoftVisual C++ 2013Visual C++ 12.0, 2013年8月发布,可以看作是Visual C++ 11.0的升级版。这个版本相对于2012添加了大量对C++11标准的支持。可以开发windows8.1专用的Modern UI风格的应用程序(但却不支持windows8,支持windows8.1)。开发环境亦内置了源代码染色的功能。最新稳定版本(亦适用于2013)Visual C++ 被整合在Visual Studio之中,但仍可单独安装使用。有四种最新版本:Visual Studio 2012 Professional是供开发人员执行基本开发任务的重要工具。可简化在各种平台(包括 SharePoint 和云)上创建、调试和开发应用程序的过程。Visual Studio 2012 Professional 自带对测试驱动开发的集成支持以及调试工具,以帮助确保提供高质量的解决方案。Visual Studio 2012 Premium是一个功能全面的工具集,可为个人或团队简化应用程序开发过程,支持交付可扩展的高质量应用程序。无论是编写代码、构建数据库、测试还是调试,您都可以使用能够按照你的方式工作的强大工具来提高工作效率。Visual Studio 2012 Ultimate是一个综合性的应用程序生命周期管理工具套件,可供团队用于确保从设计到部署的整个过程都能取得较高质量的结果。无论是创建新的解决方案,还是改进现有的应用程序,Visual Studio 2012 Ultimate 都能让您针对不断增加的平台和技术(包括云和并行计算)将梦想变成现实。Visual Studio Test Professional 2012是质量保障团队的专用工具集,可简化测试规划和手动测试执行过程。Test Professional 与开发人员的 Visual Studio 软件配合运行,可在整个应用程序开发生命周期内实现开发人员和测试人员之间的高效协作。以前的版本:Visual C++ 2008 Express、Visual C++ 2008 Standard 标准版、Visual C++ 2008 Professional 专业版、Visual C++ 2008 Team System 团队系统版,其中 Microsoft Visual C++ 2008 Express 可从微软网站免费下载使用,并且不限制商业使用。
收起全文
精华内容
参与话题
  • vc++ 6.0 完整版

    2020-07-30 23:30:10
    由于vc++6.0已经很早了,所以Windows10会出现各种不兼容问题,最主要的就是 不能打开。现在提供一种办法,不是修改兼容性,而是替换文件,方法已经使用多次。有人反应使用我的文件编的程序会出错,可能与某些原因...
  • VC++2010(VC++最新版!)

    千次下载 热门讨论 2020-07-30 23:32:51
    这是微软官网的VC++2010免费的学生版,是在线安装的,我找过它安装时下载的离线安装包,但都太分散不完整,无法保存实现独立安装(我水平有限...) 这个VC++2010微软官方中文免费版,双击这个在线安装器它会自动下载并安装...
  • VC++——下载地址(网盘)

    千次阅读 2019-07-16 13:45:23
    链接:https://pan.baidu.com/s/1WPGWo3WKaeZPLnrks_YTAQ 提取码:wv9g

    链接:https://pan.baidu.com/s/1WPGWo3WKaeZPLnrks_YTAQ 


    提取码:wv9g 

    展开全文
  • 写给VC++初学者

    千次阅读 2018-11-22 18:51:38
     我记得我开始学习编程的时候是从2006年初,那时候刚开始接触的就是C语言,后来逐渐过渡到C++,直到现在的VC++  可以说一路走来,风雨颠簸,困难重重!  我的入门老师是一个学习JAVA的程序员,那时候看他写JAVA...

       众所周知,一个好的程序员的基础要求就是——耐心!耐心!持续的耐心!

       以下是写给那些初入编程门槛的初学者一些我的个人感悟,如有疏偏,请多指正。

       我记得我开始学习编程的时候是从2006年初,那时候刚开始接触的就是C语言,后来逐渐过渡到C++,直到现在的VC++

       可以说一路走来,风雨颠簸,困难重重!

       我的入门老师是一个学习JAVA的程序员,那时候看他写JAVA程序代码的时候十分潇洒,于是就萌生了拜师的愿望,也就是从2006年起,入门老师一上来就让我学C和C++,然后我开始自学C语言和C++,后期逐渐过渡到稍微复杂些的VC++(当然VC++的复杂度也是很厉害的,一般学习VC++的人很容易被VC++的复杂度搞崩溃了,我是属于 神经比较粗大的那一类,不崩溃,崩溃的只会是我使用的电脑。),偏重于进行windows系统软件的开发,自己主持开发了一款ERP生产管理软件,是基于VC++和SQLserver数据库写的,有机会给大家共享一下源代码。

       我的编程学习方式很独特,一蒙二猜三调试,刚开始的时候我的计算机英语不过关,只能靠蒙函数语句命令,后来就是靠猜,时间长了,我对VC++的整体结构开始比较了解,学会了看.H头文件函数,依然是靠猜,一遍一遍的调试,每天我的学习时间为:上午起床7点半吃完早饭,8点钟准时坐在电脑前码代码,中途泡杯茶,然后坐到11点开始吃饭,吃完饭,下午2点钟开工,继续坐在电脑前,不断调试调试调试,直到下午5点半。六点回到住处,脑袋里面全是代码行,有时候一个功能可能难住我三四天,但是一旦突破,那感觉真的是非常爽。

       经过了四年多的努力,我现在已经能够独立开发企业管理软件(4万3千行)、ERP生产系统软件(19万8千行)、仓储软件(3万9千行)以及各种windows操作系统软件(无法统计,大概几十万行),另外我还学会了JAVA、Aap.NET、熟练掌握MYsql、SqlServer数据库,笼统的计算一下,我也是突破100万行代码编写经验的程序员了(那些写了10万行的就不要说自己有经验了,哪个程序员不要写个百万行才能练出金刚不坏之身!不管100万行是黄金代码还是调试代码,没有100万行想进入高级程序员是比较难的!当然100万行中的黄金代码行按照比例来说大概只有10万甚至5万行是黄金代码,其他的可能都是调试代码或者测试代码行了)。

        近两年APP比较火!所以我又开始学习Eclipse 和 Android Studio,根据我的体验,我个人比较偏好使用Eclipse,当然萝卜青菜,各有所爱,至今为止,我最喜欢的编译软件系统有VC++6.0和Eclipse,因为这两款都属于那种独行侠式的软件。

        今天有点累。。。。刚写完程序来舒缓下脑子,就写到这里吧,顺便练练字,各位小白有什么问题可以与我探讨,大家一起进步。

        现在我自己带着团队,主要从事APP、淘宝、微信、企业进销存软件、Windows系统工具软件的开发。

        送大家一张我在家的工作图 

      

       

      简陋的工作环境+陈旧的电脑,就是程序猿的真实写照啊。

       努力吧!程序猿要变成RMB猿啊!

    展开全文
  • c与c++原始编译器,适合初学者使用
  • VC++是什么?

    千次阅读 2017-08-24 16:14:06
    VC++是什么?  这个问题很奇怪吗?大概是。不过,当我又看到有人发表诸如“Windows/Office是VC编写的”或者“VC是无所不能的”这种高论,我就禁不住这样问自己。  Visual C++究竟是什么?你平常在其中工作的...

    VC++是什么?


        这个问题很奇怪吗?大概是。不过,当我又看到有人发表诸如“Windows/Office是VC编写的”或者“VC是无所不能的”这种高论,我就禁不住这样问自己。

        Visual C++究竟是什么?你平常在其中工作的那个标记着“Microsoft Visual C++”的窗口,真的就代表Visual C++吗?

        按照我的理解,Visual C++是一个开发工具包,它大概可以分成三个主要的部分:

    1. Developer Studio,这是一个集成开发环境,我们日常工作的99%都是在它上面完成的,再加上它的标题赫然写着“Microsoft Visual C++”,所以很多人理所当然的认为,那就是Visual C++了。其实不然,虽然Developer Studio提供了一个很好的编辑器和很多Wizard,但实际上它没有任何编译和链接程序的功能,真正完成这些工作的幕后英雄后面会介绍。我们也知道,Developer Studio并不是专门用于VC的,它也同样用于VB,VJ,VID等Visual Studio家族的其他同胞兄弟。所以不要把Developer Studio当成Visual C++, 它充其量只是Visual C++的一个壳子而已。这一点请切记!

    2. MFC。从理论上来讲,MFC也不是专用于Visual C++,Borland C++,C++Builder和Symantec C++同样可以处理MFC。同时,用Visual C++编写代码也并不意味着一定要用MFC,只要愿意,用Visual C++来编写SDK程序,或者使用STL,ATL,一样没有限制。不过,Visual C++本来就是为MFC打造的,Visual C++中的许多特征和语言扩展也是为MFC而设计的,所以用Visual C++而不用MFC就等于抛弃了Visual C++中很大的一部分功能。但是,Visual C++也不等于MFC。

    3. Platform SDK。这才是Visual C++和整个Visual Studio的精华和灵魂,虽然我们很少能直接接触到它。大致说来,Platform SDK是以Microsoft C/C++编译器为核心(不是Visual C++,看清楚了),配合MASM,辅以其他一些工具和文档资料。上面说到Developer Studio没有编译程序的功能,那么这项工作是由谁来完成的呢?是CL,是NMAKE,和其他许许多多命令行程序,这些我们看不到的程序才是构成Visual Studio的基石。

        为什么我会觉得“Windows是用VC开发的”这种说法很奇怪?因为它太含糊了。用VC,可以编写MFC应用,也可以编写纯SDK程序,不论哪一种方式,都不一定是非VC不可。只要乐意,我完全可以用UltraEdit来写出一个MFC程序,再用CL编译之,没有必要一定动用VC这个大家伙。而且有许多黑客和买不起Visual Studio的人就是这么干的!用SDK编程就更不需要VC了,Down一个Borlan C++ Compiler下来,或者用lcc之类的编译器,同样可以达到目的。再说了,Windows可不是一个单纯的产品。用VC来编写Windows外围程序是完全不成问题的,可是操作系统的核心部分呢?就算可以用VC来编写代码,调试怎么办?VC自身的调试器对一般的应用功能是够强大的,可是对于系统级的调试根本无能为力,因为这个调试器本身就是依赖于操作系统的。只有系统级的调试程序如debug,SoftIce和Wdebug这些工具才能完成如此重大的任务。

        从历史上来看,Visual C++ 1.0的出现晚于Windows 3.0,而且那时候的MFC只有一个雏形而已,用来开发操作系统根本是不可能的事情。在Visual C++ 1.0的前面倒是有一个Microsoft C/C++ 7.0,但是它整体水平不如Borland C++ 3.1,在扩展内存管理方面的功能又不如Watcom C++ ,所以一直没有占据很大的市场。它现在已经不作为单独的产品,但仍然作为Platform SDK的主要组成部分而存在于Visual Studio产品中,而且其功能比过去也不可同日而语了。到Windows 95问世的时候,MFC仍然在尽力追赶操作系统的功能。应该说Visual C++ 5.0是一个转折点,一方面MFC已经发展比较完善,另一方面,操作系统的基本结构也已经稳定,后面就主要着眼于系统整合与完善作为商务平台的功能。已经稳定的系统不可能再进行翻天覆地的修改,所以,我比较能够接受“Windows系统是用Microsoft C++和MASM作为编译器完成的”这种说法。研究Windows的系统文件可以看出,很多文件显示出来的Linker Version明显是Microsoft C++编译器。至于代码是用什么编写的?我不知道,也不想知道,除了Developer Studio的编辑器之外,任何好的文本编辑器都能够做到这一点。

        Visual C++是无所不能的吗?唔,最好也是分开来说。Developer Studio肯定不是—它只是个外壳而已。MFC呢?也不是。一方面它是对API的封装,离开了API它就什么也干不了;另一方面,MFC对API的封装也不够全面,有些时候还是要直接调用API函数才能够“为所欲为”。至于Platform SDK,倒真的可以说它几乎是无所不能的。不过,过分强调这一点并没有太大意义。只要有一套完整的编译器,和必须的支持文件,其他开发工具也可以说是“无所不能”的,比如Borland C++ Compiler或者lcc都可。

        老实说,我并不喜欢“无所不能”这类字眼。关键在于各人的理解不同。如果我较起真来,说能不能写个VC程序让电脑拿起鼠标砸向我不喜欢的老板,你说它能办得到吗?所谓的“无所不能”究竟有何意义?让我用VC写一个Server,能在普通工作站上支持每秒几千万的访问量,杀了我也办不到,不管VC的优化手段是多么有效。在具体的平台上,在特定的操作系统中,不论多么强大的工具,最终还是要受到平台和系统本身的限制。大家应该知道这个悖论吧:上帝能否制造出一块他自己也举不起来的石头?

        我也常常看到“MFC永远不会过时”或者“C++是不会灭亡的”这种发言。我理解发言人的心情,不过这种说法绝不客观。一种语言也好,一个Application Framework也罢,它们之所以有今天的地位,并不是纯粹自然形成的,有许多复杂因素的作用,也有时势造英雄的理由在内,所谓“居高声自远,非是籍秋风”是也。历史的舞台从来不是为某人专设,即使真有所谓万古长青的怪胎,恐怕也正应了那句老话:“众人都死了,只剩咱们两个老妖精,有什么意思!”我们现在使用的语言,不论Basic,Pascal还是C++,甚至如日中天的Java和C#,终究都会有功成身退的一天。这并不是我们的损失,相反,薪尽火传,一种语言中好的,合理的因素,肯定会被后续者所继承和发扬,自然界的新陈代谢本该如此。

        天空没有飞翔的痕迹,而飞鸟已经飞过。一种语言只要曾经在历史上留下浓墨重彩的一笔,完成它“为先贤继圣学,为万世开太平”的历史使命(有点夸张),这就够了,何必缠绵不舍作儿女之态!不知道我有生之年会不会看到C++的消亡,如果真有这么一天,我会拍手欢呼,因为这说明已经有了另外一种更新更好的语言来代替它(或许是几种)。不过照我猜想,像C++这种轰动武林惊万教的语言,其灭亡恐怕也不会是悄无声息,而多半属于“始皇既没,余威震于殊俗”那种情况。

        最后请允许我发表一点感慨。语言的优劣其实是一个无需讨论的问题,个人的经历和所处环境在很大程度上就决定了你对某种语言的看法,这是很个人的东西。好比碰到一位法国朋友,他多半会自豪的告诉你:法语是世界上最好最优美的语言。对这种说法我会微笑表示赞同,并且欣赏他的民族自豪感,而不会觉得这是对汉语或者英语的贬低—虽然我心底里一直深信,汉语才是世界上最好的语言。当然,如果他对我说“你们那些破烂中文是些什么玩意”,那我可能就是另外一种反应了。


    展开全文
  • vc++经典技巧总结

    万次阅读 2008-12-31 12:24:00
    1."属性页的添加:创建对话框的类,该类要从CpropertyPage继承;然后在要添加该对话框为属性页的类(头文件)里创建CpropertySheet类的一个对象m_tabsheet和新创建的对话框类的对象m_skatch;最后,在.cpp文件里的...
      
    

    1."属性页的添加:

    创建对话框的类,该类要从CpropertyPage继承;然后在要添加该对话框为属性页的类(头文件)里创建CpropertySheet类的一个对象m_tabsheet和新创建的对话框类的对象m_skatch;最后,在.cpp文件里的OnInitDialog()之类的函数里实现如下代码:
    m_tabsheet.Create(this, WS_CHILD | WS_VISIBLE, 0);
    "//使选项卡的按钮在下面
    "if(m_tabsheet.m_hWnd)
    "m_tabsheet.ShowWindow(SW_MAXIMIZE);//显示选项卡
    //加入标签,标签名由各个子对话框的标题栏决定
    "m_tabsheet.AddPage(&m_skatch);
    "//用Create来创建一个属性页
    "m_tabsheet.Create(this, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT);
    "
    RECT rect;
    "m_tabsheet.GetWindowRect(&rect);
    "int width = rect.right - rect.left;
    "int height = rect.bottom - rect.top;
    "
    "//调整属性页的大小和位置
    "m_tabsheet.SetWindowPos(NULL, 225, 225, width-82, height,SWP_NOACTIVATE);
    属性页的添加完成。如果要添加多个属性页,则只需要增加多个对象,如下:m_tabsheet.AddPage(&m_skatch1);
      m_tabsheet.AddPage(&m_skatch2);
    . . . . . .

    2."List Control中标题栏(Column)的添加:

    创建一个List Control,其ID为IDC_LIST,在其Styles属性项下的View项里选择Report、Align项里选择Top、Sort项里选择None.
    然后在该List所在对话框的类(头文件)里创建ClistCtrl的一个对象m_list然后在.cpp文件的OnInitDialog()之类的函数里实现如下代码:
    CString strname[3];
    strname[0]="Screen Name";
    strname[1]="Form ID";
    strname[2]="Category Path";
    for(int i=0;i<3;i++)
    {
    m_List.InsertColumn(i,strname[i],LVCFMT_LEFT,130);
    }
    在这之前也要将List Control的ID与ClistCtrl的对象m_list在DoDataExchange(CDataExchange* pDX)函数里绑定,如下:
    DDX_Control(pDX, IDC_LIST, m_List);

    3."ToolBar和StatusBar中控件的添加:

    方法⑴.只能在ToolBar里创建控件:首先,在ToolBar中创建一个Button,其ID为ID_TOOL_COMBO(我们要将创建的控件放在该Button的位置上).
    其次,新创建一个类CMainToolBar,要从CToolBar继承(创建过程大概如下:选择工程/增加到工程/新的类;也可以选择工程的根,然后点击右键,选择新的类;或者CTL+W,选择增加类/新的类 --- 然后在class type里选择Generic Class,在Name栏里输入新类的名字,Base class里输入CToolBar),创建成功后在该类里创建要增加的控件的对象,如:
    CComboBox""m_wndMyCombo; 
    CStatic""m_wndCategory, m_wndCategoryPath;
    CButton""m_wndOpenButton;
    Cedit"""m_wndEdit;
    然后在构造函数里初始化如:
    m_wndMyCombo.m_hWnd = NULL;
    m_wndCategory.m_hWnd = NULL;
    m_wndCategoryPath.m_hWnd = NULL;
    m_wndOpenButton.m_hWnd = NULL;
    m_wndEdit.m_hWnd = NULL;
    接着在CMainframe的头文件里创建CMainToolBar的一个对象m_wndToolBar,最后在.cpp文件的OnCreate函数的最后实现如下:
    "int index = 0;
    "CRect rect;  // 可定义在头文件当中
    "// ComboBox
    "{
    ""//找到指定的工具项
    ""while(m_wndToolBar.GetItemID(index)!=ID_TOOL_COMBO)
    """index++;
    ""//设置指定工具项的宽度并获取新的区域 120是宽度
    ""m_wndToolBar.SetButtonInfo(index, ID_TOOL_COMBO, TBBS_SEPARATOR, 120);
    ""m_wndToolBar.GetItemRect(index, &rect);
    ""
    ""//设置位置
    ""rect.top+=1;
    ""rect.bottom += 200;
    ""
    ""// 创建并显示控件
    ""if(!m_wndToolBar.m_wndMyCombo.Create(WS_CHILD|WS_VISIBLE| CBS_AUTOHSCROLL| 
    """CBS_DROPDOWNLIST | CBS_HASSTRINGS , rect, &m_wndToolBar, ID_TOOL_COMBO))
    ""{ 
    """TRACE0("Failed to create combo-box/n");
    """return FALSE;
    ""}
    ""m_wndToolBar.m_wndMyCombo.ShowWindow(SW_SHOW);
    ""
    ""//填充内容"
    ""m_wndToolBar.m_wndMyCombo.AddString("25%");
    ""m_wndToolBar.m_wndMyCombo.AddString("50%");
    ""m_wndToolBar.m_wndMyCombo.AddString("75%");
    "
    ""//选择默认项
    ""m_wndToolBar.m_wndMyCombo.SetCurSel(0);
    ""
    ""//获取到内容并MSGBOX显示出来
    ""CString strContent;
    ""m_wndToolBar.m_wndMyCombo.GetWindowText(strContent);

    ""index = 0;
    "}
    其他控件都类似创建(只需要注意一下各自的Create函数的参数即可)。
    方法⑵.这种方法创建不太容易控制:直接在CMainframe的头文件中创建要增加的控件的对象,如CButton"的对象m_wndAboutButton,然后创建CToolBar或者CstatusBar的对象,如:CstatusBar的对象_wndStatusBar;再增加几个函数如下:
    Protected:
    virtual void RecalcLayout(BOOL bNotify = TRUE);
    "afx_msg void CMainFrame::OnViewStatusBar();
    接着在.cpp文件中将StatusBar的ID和OnViewStatusBar 函数绑定在一起,如下所示:BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    "  // {{AFX_MSG_MAP(CMainFrame)
    "  ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar)
    "  ON_WM_CREATE()
    "  // }}AFX_MSG_MAP
    END_MESSAGE_MAP()
    然后Create函数的最后(返回值之前)实现如下代码:
    CRect rc;
    "VERIFY(m_wndAboutButton.Create(_T("MyAbout"),
    ""  WS_VISIBLE,rc,this,ID_APP_ABOUT));

    "// TODO: Remove this if you don't want tool tips or a resizeable toolbar
    "m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
    "CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
    再在RecalcLayout函数里实现:
    CRect rc;
    if (m_wndStatusBar.m_hWnd)
    {
    ""m_wndStatusBar.GetWindowRect(&rc);
    ""ScreenToClient(&rc);
    ""rc.right -= 50;
    ""m_wndStatusBar.SetWindowPos(NULL,rc.left,rc.top,rc.Width(),rc.Height(),
    """SWP_NOZORDER);

    ""rc.left = rc.right;
    ""rc.right += 50;
    ""m_wndAboutButton.SetWindowPos(NULL,rc.left,rc.top,rc.Width(),rc.Height(),
    """SWP_NOZORDER);
    "}
    最后在OnViewStatusBar()里实现:
    BOOL bShow = m_wndStatusBar.GetStyle() & WS_VISIBLE;
    "m_wndAboutButton.SetWindowPos(NULL, 0, 0, 0, 0,
    SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|
    (bShow ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
    ToolBar中的创建与此相同,只需更改一下句柄即可。

    4."通过Control创建的控件,对其属性的动态控制:

    在对话框类的头文件里创建所要改变属性的控件的对象,如要改变一个Button(其ID为IDC_MyButton)的属性,则需创建Cbutton的对象m_button。然后在.cpp中的DoDataExchange函数里将Button的ID和创建的对象绑定在一起:
    //{{AFX_DATA_MAP(CPrintDlg)
    ""// NOTE: the ClassWizard will add DDX and DDV calls here
    "DDX_Control(pDX, IDC_MyButton, m_button);
    "//}}AFX_DATA_MAP
    然后可以在该函数的最后进行初始化:
    "m_button.EnableWindow(FALSE);
    到这里已经实现了改变属性。如果要动态改变其属性,可如下实现(通过两个Button的点击改变起属性):
    // RadioAll Button的点击响应函数
    void CPrintDlg::OnRadioAll() 
    {
    ""// TODO: Add your control notification handler code here
    ""m_button.EnableWindow(TRUE);
    }

    // RadioSelect Button的点击响应函数
    void CPrintDlg::OnRadioSelect() 
    {
    ""// TODO: Add your control notification handler code here
    ""m_button.EnableWindow(FALSE);
    }
    也可以通过一个Check Button的点击来改变,在其点击响应函数里实现:
    m_button.EnableWindow(!m_button.IsWindowEnabled());
    其余控件属性的改变都如此。

    5."窗口的分割与停靠:                        
    一、新建一个类CMySplitter,基类为CSplitterWnd
    二、重载该类的OnMouseMove函数:
    void CMySplitter::OnMouseMove(UINT nFlags, CPoint point)

    "// 限制切分条的运动范围。 
    "if(point.x<228||point.x>600) 
    "{ 
    ""CWnd::OnMouseMove(nFlags, point); 
    "} 
    "else 
    "{ 
    ""CSplitterWnd::OnMouseMove(nFlags, point); 
    "} 
    }
    三、 然后就可以跟一般的窗口分割那样去做了,if(point.x<228||point.x>600)这里的范围可以随你去设置了 ^_^,够简单吧。 
    四、切分窗口 
    在MaiFram.h建立切分条对象:
    protected: 
    CMySplitter m_wndSplitter; //切分窗口对象 
    //在MaiFram.cpp中实现窗口切分: 
    BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,CCreateContext* pContext) 

    "// 创建拆分器窗口 
    if (!m_wndSplitter.CreateStatic(this, 1, 2)) 
    ""return FALSE; 
    if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView),CSize(228,100), pContext) ||!m_wndSplitter.CreateView(0,1, RUNTIME_CLASS(CDataEditView), CSize(100, 100), pContext)) 
    "{ 
    ""m_wndSplitter.DestroyWindow(); 
    ""return FALSE; 
    "} 

    "return TRUE; 
    }


    6. ①怎样在程序开始的时候让它最大化?
    ②vc++做出来的exe文件在窗体的右上方是没有最大化和最小化按钮的,怎样实现这一功能? 
    ③如何在显示窗口时,使最大化按钮变灰?

    ①在App类里的C…App::InitInstance()中把m_pMainWnd->ShowWindow(SW_SHOW)改成m_pMainWnd->ShowWindow(SW_MAXIMIZE);
    ②在CreateWidnow时用WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX 风格.
      ③ 第一种方法:
    BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 

    if( !CFrameWnd::PreCreateWindow(cs) ) 
    return FALSE; 
    // TODO: Modify the Window class or styles here by modifying 
    // the CREATESTRUCT cs 
    // disable the maxmini box 
    cs.style &= ~WS_MAXIMIZEBOX; 
    return TRUE; 
    }
    第二种方法:
    CMenu *pMenu=AfxGetApp()->m_pMainWnd->GetSystemMenu(FALSE); 
         int x=pMenu->GetMenuItemCount( ); 
         UINT pID=pMenu->GetMenuItemID(x-1); 
         pMenu->EnableMenuItem(pID, MF_DISABLED);
    第三种方法:
    ModifyStyle(WS_MAXIMIZEBOX, 0); 
    这个函数也可以是最大化按钮失效! 
    并且可以在程序中动态的改变窗口的风格

    7. 更改属性页标题

    void CProSheet::SetPageTitle(int nPage, int nImage, CString strTitle)
    {
     TC_ITEM item;
     //item.mask = TCIF_TEXT|TCIF_IMAGE;  //设置图标+文字
     item.mask = TCIF_IMAGE;    //只设置图标
     item.iImage = nImage;
    // item.pszText = strTitle.GetBuffer(0);  //设置文字
     GetTabControl ()->SetItem (nPage, &item);
    //要设置文字时就将上面2行有注释符的代码前的注释符去掉
    }

    8. 创建动态菜单

    void CMainFrame::OnSelectState(NMTOOLBAR* pnmtb, LRESULT *plr) 

    "CMenu menu; 
    "if(!menu.CreateMenu()) 
    "return; 
    "menu.AppendMenu(MF_STRING,0,"开始"); 
    "menu.AppendMenu(MF_STRING,0,"结束"); 
    "CRect rc; 
    "m_wndToolBar.SendMessage(TB_GETRECT, pnmtb->iItem, (LPARAM)&rc); 
    "m_wndToolBar.ClientToScreen(&rc); 
    "menu.TrackMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL, 
    """rc.left, rc.bottom, this, &rc); 
    //"menu.DestroyMenu(); 
    "menu.detach();
    }
    9.关于打印

    1.要打印哪个视就 
    ((CMainFrame*)AfxGetMainWnd())->m_wndSplitter.SetActivePane(...) 
    //要打印的那个视对应的Pane

    2.有一个单文档工程,文档窗口被切分:左视图由CTreeView 的派生类管理,右视图由CListView 的派生类CMyListView(其为风格为LVS_REPORT)管理,我想为右视图添加打印和打印预览,我在MyListView.cpp中添加了 
      ON_COMMAND(ID_FILE_PRINT,CListView::OnFilePrint) 
      ON_COMMAND(ID_FILE_PRINT_PREVIEW,CListView::OnFilePrintPreview)还有 
      BOOL CMyListView::OnPreparePrinting(CPrintInfo* pInfo) 
      { 
         // TODO: call DoPreparePrinting to invoke the Print dialog box 

         // return CListView::OnPreparePrinting(pInfo); 
         pInfo->SetMaxPage(2); 
         BOOL bret=DoPreparePrinting(pInfo); 
         pInfo->m_nNumPreviewPages=2; 
         return bret; 
      }
    3. 下面是从MSDN中摘出来的一段,是用来改变消息路由的。用了这段代码之后,CView中的消息(菜单,控件,子窗口)将先被CMyShape类来处理。不知道你要的是不是这样的效果。 

      // This example illustrates extending the framework's standard command 
      // route from the view to objects managed by the view. This example 
      // is from an object-oriented drawing application, similar to the 
      // DRAWCLI sample application, which draws and edits "shapes". 

      BOOL CMyView::OnCmdMsg(UINT nID, int nCode, void* pExtra, 
        AFX_CMDHANDLERINFO* pHandlerInfo) 
      { 
          // Extend the framework's command route from the view to 
          // the application-specific CMyShape that is currently selected 
          // in the view. m_pActiveShape is NULL if no shape object 
          // is currently selected in the view. 
          if ((m_pActiveShape != NULL) 
            && m_pActiveShape->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) 
           return TRUE; 

          // If the object(s) in the extended command route don't handle 
          // the command, then let the base class OnCmdMsg handle it. 
          return CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); 
         } 

         // The command handler for ID_SHAPE_COLOR (menu command to change 
         // the color of the currently selected shape) was added to 
         // the message map of CMyShape (note, not CMyView) using ClassWizard.  

         // The menu item will be automatically enabled or disabled, depending 
         // on whether a CMyShape is currently selected in the view, that is, 
         // depending on whether CMyView::m_pActiveView is NULL. It is not 
         // necessary to implement an ON_UPDATE_COMMAND_UI handler to enable 
         // or disable the menu item.  

       BEGIN_MESSAGE_MAP(CMyShape, CCmdTarget) 
        //{{AFX_MSG_MAP(CMyShape) 
        ON_COMMAND(ID_SHAPE_COLOR, OnShapeColor) 
        //}}AFX_MSG_MAP 
       END_MESSAGE_MAP() 

    如果你只是想调用OnFilePrint( )函数,可以试一试下面的代码,就和调用其它类中的函数一样。 

    CMDIFrameWnd *pFrame = 
           (CMDIFrameWnd*)AfxGetApp()->m_pMainWnd; 

    // Get the active MDI child window. 
    CMDIChildWnd *pChild = 
           (CMDIChildWnd *) pFrame->GetActiveFrame(); 

    // or CMDIChildWnd *pChild = pFrame->MDIGetActive(); 

    // Get the active view attached to the active MDI child 
    // window. 
    CMyView *pView = (CMyView *) pChild->GetActiveView(); 

    pView->OnFilePrint( );


    4.
    void CMyReportView::OnFileOpen() 

    char Filter[] = "Crystal Report files(*.rpt)|*.rpt|All files(*.*)|*.*||"; 
    CRect rect; 
    CFileDialog OpenDlg(TRUE,0,0,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,(LPCTSTR)Filter,NULL); 
    if(OpenDlg.DoModal()!=IDOK) ///显示文件对话框 
    return; 
    CString m_fName=OpenDlg.GetPathName(); ///取得文件名 
    if(m_CrystalReport) 
    m_CrystalReport.DestroyWindow(); 
    GetClientRect(rect); 
    ///创建控件/// 
    if (!m_CrystalReport.Create(AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),WS_CHILD|WS_VISIBLE,rect,this,IDC_CRYSTALREPORT1)) 

    AfxMessageBox("控件创建失败!"); 
    return ; 

    m_CrystalReport.SetWindowParentHandle((long)(this->m_hWnd));///设置父窗口 
    m_CrystalReport.SetWindowBorderStyle(0); ///设置为没有边框 
    m_CrystalReport.SetWindowLeft(0); ///左空间 
    m_CrystalReport.SetWindowTop(0); ///顶部空间 
    m_CrystalReport.SetWindowControls(FALSE); ///不显示工具条 
    m_CrystalReport.SetReportFileName(m_fName); ///设置报表文件 
    m_CrystalReport.SetWindowWidth(rect.Width()); ///设置窗口宽度 
    m_CrystalReport.SetWindowHeight(rect.Height()); ///设置窗口高度 
    m_CrystalReport.SetFormulas(0, "Company=/"VC知识库/""); ///将报表中的Company变量的值设置为VC知识库 
    m_CrystalReport.SetDestination(0); ///设置输出对象是屏幕 
    m_CrystalReport.PrintReport(); ///显示报表 

    void CMyReportView::OnFilePrint() 

    if(m_CrystalReport && m_CrystalReport.GetReportFileName() != "") 

    m_CrystalReport.SetDestination(1); ///设置输出对象是打印机 
    m_CrystalReport.PrintReport(); ///打印
    }

    10. Scroll

    创建一个基于CScrollview的SDI Project(在第6步中选CScrollview) 
    若你已创建了,这步可以省略。 
    然后: 
    改为如 
    void CTestView::OnInitialUpdate() 

    CScrollView::OnInitialUpdate(); 

    CSize sizeTotal; 
    // TODO: calculate the total size of this view 
    sizeTotal.cx = 1024; //改这两个 
    sizeTotal.cy = 768;  // 
    SetScrollSizes(MM_TEXT, sizeTotal); 
    }

     

     

    11. 修改主窗口风格 

    AppWizard生成的应用程序框架的主窗口具有缺省的窗口风格,比如在窗口标题条中自动添加文档名、窗口是叠加型的、可改变窗口大小等。要修改窗口的缺省风格,需要重载CWnd::PreCreateWindow(CREATESTRUCT& cs)函数,并在其中修改CREATESTRUCT型参数cs。
    CWnd::PreCreateWindow 函数先于窗口创建函数执行。如果该函数被重载,则窗口创建函数将使用CWnd::PreCreateWindow 函数返回的CREATESTRUCT cs参数所定义的窗口风格来创建窗口;否则使用预定义的窗口风格。
    CREATESTRUCT结构定义了创建函数创建窗口所用的初始参数,其定义如下:

    typedef struct tagCREATESTRUCT { 
    LPVOID lpCreateParams; // 创建窗口的基本参数 
    HANDLE hInstance; // 拥有将创建的窗口的模块实例句柄 
    HMENU hMenu; // 新窗口的菜单句柄 
    HWND hwndParent; // 新窗口的父窗口句柄 
    int cy; // 新窗口的高度 
    int cx; // 新窗口的宽度 
    int y; // 新窗口的左上角Y坐标 
    int x; // 新窗口的左上角X坐标 
    LONG style; // 新窗口的风格 
    LPCSTR lpszName; // 新窗口的名称 
    LPCSTR lpszClass; // 新窗口的窗口类名 
    DWORD dwExStyle; // 新窗口的扩展参数 
    } CREATESTRUCT; 

    CREATESTRUCT结构的style域定义了窗口的风格。比如,缺省的MDI主窗口的风格中就包括FWS_ADDTOTITLE(在标题条中显示当前的工作文档名)、FWS_PREFIXTITLE(把文档名放在程序标题的前面)、WS_THICKFRAME(窗口具有可缩放的边框)等风格。由于多种风格参数由逻辑或(“|”)组合在一起的,因此添加某种风格,就只需用“|”把对应的参数加到CREATESTRUCT结构的style域中;删除已有的风格,则需用“&”连接CREATESTRUCT结构的style域与该风格的逻辑非值。
    CREATESTRUCT结构的x、y、cx、cy域分别定义了窗口的初始位置和大小,因此,在CWnd::PreCreateWindow 函数中给它们赋值,将能定义窗口的初始显示位置和大小。
    下例中的代码将主框窗口的大小将固定为1/4屏幕,标题条中仅显示窗口名,不显示文档名。

    BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 

    // TODO: Modify the Window class or styles here by modifying 
    // the CREATESTRUCT cs 

    // 修改主窗风格 
    cs.style &= ~FWS_ADDTOTITLE; //去除标题条中的文档名 
    cs.style &= ~WS_THICKFRAME; //去除可改变大小的边框 
    cs.style |= WS_DLGFRAME; //增加不能改变大小的边框 

    // 确定主窗的大小和初始位置 
    int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);//获得屏幕宽 
    int cyScreen = ::GetSystemMetrics(SM_CYSCREEN); //获得屏幕高 
    cs.x = 0; // 主窗位于左上角 
    cs.y = 0; 
    cs.cx = cxScreen/2; // 主窗宽为1/2屏幕宽 
    cs.cy = cxScreen/2; // 主窗高为1/2屏幕高 
    return CMDIFrameWnd::PreCreateWindow(cs); 
    }

    12. 控制滚动条

    BOOL CDiagramShowView::PreTranslateMessage(MSG* pMsg) 

    "CFileTreeDoc* pDoc = (CFileTreeDoc*)GetDocument();
    "CPoint point = GetScrollPosition();
    "
    "if(pMsg->message == WM_KEYDOWN) 
    "{ 
    ""switch(pMsg->wParam) 
    ""{ 
    ""case VK_LEFT:
    """if( point.x > 10)
    """{
    """"EndPoint.x = EndPoint.x - 10;
    """"EndPoint.y = EndPoint.y;
    """}
    """else
    """{
    """"EndPoint.x = 0;
    """"EndPoint.y = EndPoint.y;
    """}
    """ScrollToPosition(EndPoint);
    """InvalidateRect(NULL,TRUE);
    """break;
    ""case VK_RIGHT:
    """if( point.x < pDoc->intDiagramColumnCount * pDoc->intColumnWidth - 10 )
    """{
    """"EndPoint.x = EndPoint.x + 10;
    """"EndPoint.y = EndPoint.y;
    """}
    """else
    """{
    """"EndPoint.y = pDoc->intDiagramColumnCount * pDoc->intColumnWidth;
    """"EndPoint.x = EndPoint.x;
    """}
    """ScrollToPosition(EndPoint);
    """InvalidateRect(NULL,TRUE);
    """break;
    ""case VK_UP:
    """if( point.y > 10)
    """{
    """"EndPoint.y = EndPoint.y - 10;
    """"EndPoint.x = EndPoint.x;
    """}
    """else
    """{
    """"EndPoint.y = 0;
    """"EndPoint.x = EndPoint.x;
    """}
    """ScrollToPosition(EndPoint);
    """InvalidateRect(NULL,TRUE);
    """break;
    ""case VK_DOWN:
    """if( point.y < pDoc->intDiagramRowCount * pDoc->intRowHeight - 10 )
    """{
    """"EndPoint.y = EndPoint.y + 10;
    """"EndPoint.x = EndPoint.x;
    """}
    """else
    """{
    """"EndPoint.y = pDoc->intDiagramRowCount * pDoc->intRowHeight;
    """"EndPoint.x = EndPoint.x;
    """}
    """ScrollToPosition(EndPoint);
    """InvalidateRect(NULL,TRUE);
    """break;
    ""default:
    """break;
    ""} 
    "} 
    "return FALSE;



    // 通过正负号判断是向上还是向下滚动
    if(zDelta==120) 
    向上滚动
    if(zDelta==-120)
    向下滚动

    BOOL CDiagramShowView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
    {
    "CFileTreeDoc* pDoc = (CFileTreeDoc*)GetDocument();
    "CPoint point = GetScrollPosition();
    "
    "if(zDelta==120)
    "{
    ""if( point.y >= 20 )
    ""{
    """EndPoint.x = point.x;
    """EndPoint.y = point.y;
    """
    """EndPoint.x = EndPoint.x;
    """EndPoint.y = EndPoint.y - 20;
    ""}
    ""else
    ""{
    """EndPoint.x = EndPoint.x;
    """EndPoint.y = 0;
    ""}
    "}
    "
    "if(zDelta==-120)
    "{
    ""if( point.y <= pDoc->intDiagramRowCount * pDoc->intRowHeight - 20 )
    ""{
    """EndPoint.x = point.x;
    """EndPoint.y = point.y;
    """
    """EndPoint.x = EndPoint.x;
    """EndPoint.y = EndPoint.y + 20;
    ""}
    ""else
    ""{
    """EndPoint.x = EndPoint.x;
    """EndPoint.y = EndPoint.y;
    ""}
    "}
    "
    "ScrollToPosition(EndPoint);
    "InvalidateRect(NULL,TRUE);
    "return CScrollView::OnMouseWheel(nFlags, zDelta, pt);
    }

    13. 属性页处理通知消息 

    CPropertyPageImpl有一个消息映射处理WM_NOTIFY。如果通知代码是PSN_*的值,OnNotify()就会调用相应的通知处理函数。这使用了编译阶段虚函数机制,从而使得派生类可以很容易的重载这些处理函数。
    由于WTL 3和WTL 7设计的改变,从而存在两套不同的通知处理机制。在WTL 3中通知处理函数返回的值与PSN_*消息的返回值不同,例如,WTL 3是这样处理PSN_WIZFINISH的:

    case PSN_WIZFINISH:
    lResult = !pT->OnWizardFinish();
    break;
    OnWizardFinish()期望返回TRUE结束向导,FALSE阻止关闭向导。这个方法很简陋,但是IE5的通用控件对PSN_WIZFINISH处理的返回值添加了新解释,他返回需要获得焦点的窗口的句柄。WTL 3的程序将不能使用这个特性,因为它对所有非0的返回值都做相同的处理。
    在WTL 7中,OnNotify() 没有改变 PSN_* 消息的返回值,处理函数返回任何文档中规定的合法数值和正确的行为。当然,为了向前兼容,WTL 3 仍然使用当前默认的工作方式,要使用WTL 7的消息处理方式,你必须在中including atldlgs.h一行之前添加一行定义:
    #define _WTL_NEW_PAGE_NOTIFY_HANDLERS
    编写新的代码没有理由不使用WTL 7的消息处理函数,所以这里就不介绍WTL 3的消息处理方式。
    CPropertyPageImpl 为所有消息提供了默认的通知消息处理函数,你可以重载与你的程序有关的消息处理函数完成特殊的操作。默认的消息处理函数和相应的行为如下:
    int OnSetActive() - 允许页面成为激活状态
    BOOL OnKillActive() - 允许页面成为非激活状态
    int OnApply() - 返回 PSNRET_NOERROR 表示应用操作成功完成
    void OnReset() - 无相应的动作
    BOOL OnQueryCancel() - 允许取消操作
    int OnWizardBack() - 返回到前一个页面
    int OnWizardNext() - 进行到下一个页面
    INT_PTR OnWizardFinish() - 允许向导结束
    void OnHelp() - 无相应的动作
    BOOL OnGetObject(LPNMOBJECTNOTIFY lpObjectNotify) - 无相应的动作
    int OnTranslateAccelerator(LPMSG lpMsg) - 返回 PSNRET_NOERROR 表示消息没有被处理 
    HWND OnQueryInitialFocus(HWND hWndFocus) - 返回 NULL 表示将按Tab Order顺序的第一个控件设为焦点状态
    14.使工具条上的按钮点击一次为按下,再点击才弹起
    bCheck=m_RtfEditToolBar.GetToolBarCtrl().IsButtonChecked(ID_TB_BOLD);
    m_RtfEditToolBar.GetToolBarCtrl().CheckButton(ID_TB_BOLD, !bCheck);
    15. VC中基于 Windows 的精确定时
      
    在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等。特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要精确定时操作。
      众所周知,Windows 是基于消息机制的系统,任何事件的执行都是通过发送和接收消息来完成的。 这样就带来了一些问题,如一旦计算机的CPU被某个进程占用,或系统资源紧张时,发送到消息队列 中的消息就暂时被挂起,得不到实时处理。因此,不能简单地通过Windows消息引发一个对定时要求 严格的事件。另外,由于在Windows中已经封装了计算机底层硬件的访问,所以,要想通过直接利用 访问硬件来完成精确定时,也比较困难。所以在实际应用时,应针对具体定时精度的要求,采取相适 应的定时方法。
      VC中提供了很多关于时间操作的函数,利用它们控制程序能够精确地完成定时和计时操作。本文详细介绍了 VC中基于Windows的精确定时的七种方式.
      方式一:VC中的WM_TIMER消息映射能进行简单的时间控制。首先调用函数SetTimer()设置定时 间隔,如SetTimer(0,200,NULL)即为设置200ms的时间间隔。然后在应用程序中增加定时响应函数 OnTimer(),并在该函数中添加响应的处理语句,用来完成到达定时时间的操作。这种定时方法非常 简单,可以实现一定的定时功能,但其定时功能如同Sleep()函数的延时功能一样,精度非常低,最小 计时精度仅为30ms,CPU占用低,且定时器消息在多任务操作系统中的优先级很低,不能得到及时响 应,往往不能满足实时控制环境下的应用。只可以用来实现诸如位图的动态显示等对定时精度要求不高的情况。如示例工程中的Timer1。 
      方式二:VC中使用sleep()函数实现延时,它的单位是ms,如延时2秒,用sleep(2000)。精度非常 低,最小计时精度仅为30ms,用sleep函数的不利处在于延时期间不能处理其他的消息,如果时间太 长,就好象死机一样,CPU占用率非常高,只能用于要求不高的延时程序中。如示例工程中的Timer2。
      方式三:利用COleDateTime类和COleDateTimeSpan类结合WINDOWS的消息处理过程来实现秒级延时。如示例工程中的Timer3和Timer3_1。以下是实现2秒的延时代码: 
       COleDateTime   start_time = COleDateTime::GetCurrentTime();
       COleDateTimeSpan end_time= COleDateTime::GetCurrentTime()-start_time;
       while(end_time.GetTotalSeconds()< 2) //实现延时2秒
       { 
           MSG  msg;
           GetMessage(&msg,NULL,0,0);
           TranslateMessage(&msg); 
           DispatchMessage(&msg);
           
           //以上四行是实现在延时或定时期间能处理其他的消息,
           //虽然这样可以降低CPU的占有率,
           //但降低了延时或定时精度,实际应用中可以去掉。
           end_time = COleDateTime::GetCurrentTime()-start_time;
       }//这样在延时的时候我们也能够处理其他的消息。   
      方式四:在精度要求较高的情况下,VC中可以利用GetTickCount()函数,该函数的返回值是 DWORD型,表示以ms为单位的计算机启动后经历的时间间隔。精度比WM_TIMER消息映射高,在较 短的定时中其计时误差为15ms,在较长的定时中其计时误差较低,如果定时时间太长,就好象死机一样,CPU占用率非常高,只能用于要求不高的延时程序中。如示例工程中的Timer4和Timer4_1。下列代码可以实现50ms的精确定时:
        DWORD dwStart = GetTickCount();
        DWORD dwEnd  = dwStart;
        do
        {
         dwEnd = GetTickCount()-dwStart;
        }while(dwEnd <50);
    为使GetTickCount()函数在延时或定时期间能处理其他的消息,可以把代码改为:
        DWORD dwStart = GetTickCount();
        DWORD dwEnd  = dwStart;
        do
        {
           MSG  msg;
           GetMessage(&msg,NULL,0,0);
           TranslateMessage(&msg); 
           DispatchMessage(&msg);
           dwEnd = GetTickCount()-dwStart;
        }while(dwEnd <50);
    虽然这样可以降低CPU的占有率,并在延时或定时期间也能处理其他的消息,但降低了延时或定时精度。
      方式五:与GetTickCount()函数类似的多媒体定时器函数DWORD timeGetTime(void),该函数定时精 度为ms级,返回从Windows启动开始经过的毫秒数。微软公司在其多媒体Windows中提供了精确定时器的底 层API持,利用多媒体定时器可以很精确地读出系统的当前时间,并且能在非常精确的时间间隔内完成一 个事件、函数或过程的调用。不同之处在于调用DWORD timeGetTime(void) 函数之前必须将 Winmm.lib 和 Mmsystem.h 添加到工程中,否则在编译时提示DWORD timeGetTime(void)函数未定义。由于使用该 函数是通过查询的方式进行定时控制的,所以,应该建立定时循环来进行定时事件的控制。如示例工程中的Timer5和Timer5_1。
      方式六:使用多媒体定时器timeSetEvent()函数,该函数定时精度为ms级。利用该函数可以实现周期性的函数调用。如示例工程中的Timer6和Timer6_1。函数的原型如下: 
        MMRESULT timeSetEvent( UINT uDelay, 
                    UINT uResolution, 
                    LPTIMECALLBACK lpTimeProc, 
                    WORD dwUser, 
                    UINT fuEvent )
      该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数, 成功后返回事件的标识符代码,否则返回NULL。函数的参数说明如下:
        uDelay:以毫秒指定事件的周期。
        Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。
        LpTimeProc:指向一个回调函数。
        DwUser:存放用户提供的回调数据。
        FuEvent:指定定时器事件类型:
        TIME_ONESHOT:uDelay毫秒后只产生一次事件
        TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。   
      具体应用时,可以通过调用timeSetEvent()函数,将需要周期性执行的任务定义在LpTimeProc回调函数 中(如:定时采样、控制等),从而完成所需处理的事件。需要注意的是,任务处理的时间不能大于周期间隔时间。另外,在定时器使用完毕后, 应及时调用timeKillEvent()将之释放。 
      方式七:对于精确度要求更高的定时操作,则应该使用QueryPerformanceFrequency()和 QueryPerformanceCounter()函数。这两个函数是VC提供的仅供Windows 95及其后续版本使用的精确时间函数,并要求计算机从硬件上支持精确定时器。如示例工程中的Timer7、Timer7_1、Timer7_2、Timer7_3。
    QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下:
        BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
        BOOL QueryPerformanceCounter(LARGE_INTEGER *lpCount);
      数据类型ARGE_INTEGER既可以是一个8字节长的整型数,也可以是两个4字节长的整型数的联合结构, 其具体用法根据编译器是否支持64位而定。该类型的定义如下:
        typedef union _LARGE_INTEGER
        {
          struct
          {
           DWORD LowPart ;// 4字节整型数
           LONG HighPart;// 4字节整型数
          };
          LONGLONG QuadPart ;// 8字节整型数
          
        }LARGE_INTEGER ;
      在进行定时之前,先调用QueryPerformanceFrequency()函数获得机器内部定时器的时钟频率, 然后在需要严格定时的事件发生之前和发生之后分别调用QueryPerformanceCounter()函数,利用两次获得的计数之差及时钟频率,计算出事件经 历的精确时间。下列代码实现1ms的精确定时:
        LARGE_INTEGER litmp; 
        LONGLONG QPart1,QPart2;
        double dfMinus, dfFreq, dfTim; 
        QueryPerformanceFrequency(&litmp);
        dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率
        QueryPerformanceCounter(&litmp);
        QPart1 = litmp.QuadPart;// 获得初始值
        do
        {
         QueryPerformanceCounter(&litmp);
         QPart2 = litmp.QuadPart;//获得中止值
         dfMinus = (double)(QPart2-QPart1);
         dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
        }while(dfTim<0.001);
      其定时误差不超过1微秒,精度与CPU等机器配置有关。 下面的程序用来测试函数Sleep(100)的精确持续时间:
        LARGE_INTEGER litmp; 
        LONGLONG QPart1,QPart2;
        double dfMinus, dfFreq, dfTim; 
        QueryPerformanceFrequency(&litmp);
        dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率
        QueryPerformanceCounter(&litmp);
        QPart1 = litmp.QuadPart;// 获得初始值
        Sleep(100);
        QueryPerformanceCounter(&litmp);
        QPart2 = litmp.QuadPart;//获得中止值
        dfMinus = (double)(QPart2-QPart1);
        dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒   
      由于Sleep()函数自身的误差,上述程序每次执行的结果都会有微小误差。下列代码实现1微秒的精确定时:
        LARGE_INTEGER litmp; 
        LONGLONG QPart1,QPart2;
        double dfMinus, dfFreq, dfTim; 
        QueryPerformanceFrequency(&litmp);
        dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率
        QueryPerformanceCounter(&litmp);
        QPart1 = litmp.QuadPart;// 获得初始值
        do
        {
         QueryPerformanceCounter(&litmp);
         QPart2 = litmp.QuadPart;//获得中止值
         dfMinus = (double)(QPart2-QPart1);
         dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
        }while(dfTim<0.000001);
    其定时误差一般不超过0.5微秒,精度与CPU等机器配置有关。

    16. 为对话框中的控件增加提示的简单方法

    我学VC从VC知识库中得到不少好处,相来都是一些热心朋友们的帮助,在此表示感谢!本工程可分五步:
    1、建一个基于对话框的程序TipTest,在CTipTestDlg中增加成员变量:CToolTipCtrl m_tip[2],CWnd *m_pSub[2];
    2、在CTipTestDlg::OnInitDialog()函数中增加如下代码: 
         pSub[0] = GetDlgItem(IDC_RADIO1);   //得到单选按钮的指针
         pSub[1] = GetDlgItem(IDC_BUTTON1);

    "m_tip[0].Create(pSub[0],TTS_ALWAYSTIP); //创建CToolTipCtrl
    "m_tip[0].AddTool(pSub[0]);        //将CToolTipCtrl与相应的控件对应起来

    "m_tip[1].Create(pSub[1],TTS_ALWAYSTIP);
    "m_tip[1].AddTool(pSub[1]);

    "m_tip[0].SetTipTextColor(RGB(0,0,255)); //设定文字的颜色
         m_tip[0].SetDelayTime(150);       //设定提示文字在控件上停留的时间

    3、重载CTipTestDlg::PreTranslateMessage(MSG* pMsg)函数,增加如下代码: 
       if(m_tip[0].m_hWnd!=NULL)
         m_tip[0].RelayEvent(pMsg);  //如果m_tip[0]句柄不为空,就从主窗口中捕获消息,如WM_MOUSEMOVE,WM_LBUTTONDOWN等消息
       if(m_tip[1].m_hWnd!=NULL)
         m_tip[1].RelayEvent(pMsg); 
    4、捕获主窗口的WM_MOUSEMOVE消息,在CTipTestDlg::OnMouseMove(UINT nFlags, CPoint point)函数中增加如下代码: 
         m_tip[0].UpdateTipText("VC知识库欢迎你!",pSub[0]);    //鼠标在相应的控件上移动时显示提示文字
    "m_tip[1].UpdateTipText("http://vckbase.com",pSub[1]);

    17.删除文件夹

    // 删除文件夹及其所有内容
    void CBaseDoc::RemoveFolder(const CString &strPathName)
    {
      CString path = strPathName;
      if (path.Right(1) != _T("//"))
        path += _T("//");
      path += _T("*.*");

      CFileFind ff;
      BOOL res = ff.FindFile(path);
      while (res)
      {
        res = ff.FindNextFile();
        // 是文件时直接删除
        if (!ff.IsDots() && !ff.IsDirectory())
          DeleteFile(ff.GetFilePath());
        else if (ff.IsDots())
          continue;
        else if (ff.IsDirectory())
        {
          path = ff.GetFilePath();
          // 是目录时继续递归,删除该目录下的文件
          RemoveFolder(path);
          ::RemoveDirectory(path);
        }
      }
    }

    18.消息映射

    有对话框A,B
    从A中发消息给B然后B处理。
    准备工作,先定义消息,如下
    #define WM_B_NOTIFY WM_USER + 300 

    首先,必须将B的对话框句柄传送给A,暂时叫m_hWndB;

    在A的发送消息的地方这样写:
    ::SendMessage( m_hWndB,WM_B_NOTIFY,TRUE,NULL );

    这样A中的处理就完了,下面说B 中的
    首先定义消息处理函数,如下
    void B::ModiNotify( WPARAM wParam, LPARAM lParam )
    {
      MessageBox("小样,我就不信,搞不定你!");
    }

    然后加消息隐射,如下:
    BEGIN_MESSAGE_MAP(CB, CDialog)
      //{{AFX_MSG_MAP(CRPServerDlg)

      ON_MESSAGE( WM_B_NOTIFY,ModiNotify )

      //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    19.给从CWnd派生的窗口添加滚动条
    ModifyStyle(0,WS_VSCROLL);

    20. SetWindowPos
    函数功能:该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。  
      
         函数原型:BOOL  SetWindowPos(HWN  hWnd,HWND  hWndlnsertAfter,int  X,int  Y,int  cx,int  cy,UNIT.Flags);  
      
         参数:  
      
         hWnd:窗口句柄。  
      
         hWndlnsertAfter:在z序中的位于被置位的窗口前的窗口句柄。该参数必须为一个窗口句柄,或下列值之一:  
      
         HWND_BOTTOM:将窗口置于Z序的底部。如果参数hWnd标识了一个顶层窗口,则窗口失去顶级位置,并且被置在其他窗口的底部。  
      
         HWND_DOTTOPMOST:将窗口置于所有非顶层窗口之上(即在所有顶层窗口之后)。如果窗口己经是非顶层窗口则该标志不起作用。  
      
         HWND_TOP:将窗口置于Z序的顶部。  
      
         HWND_TOPMOST:将窗口置于所有非顶层窗口之上。即使窗口未被激活窗口也将保持顶级位置。  
      
         查g看该参数的使用方法,请看说明部分。  
      
         x:以客户坐标指定窗口新位置的左边界。  
      
         Y:以客户坐标指定窗口新位置的顶边界。  
      
         cx:以像素指定窗口的新的宽度。  
      
         cy:以像素指定窗口的新的高度。  
      
         uFlags:窗口尺寸和定位的标志。该参数可以是下列值的组合:  
      
         SWP_ASNCWINDOWPOS:如果调用进程不拥有窗口,系统会向拥有窗口的线程发出需求。这就防止调用线程在其他线程处理需求的时候发生死锁。  
      
         SWP_DEFERERASE:防止产生WM_SYNCPAINT消息。  
      
         SWP_DRAWFRAME:在窗口周围画一个边框(定义在窗口类描述中)。  
      
         SWP_FRAMECHANGED:给窗口发送WM_NCCALCSIZE消息,即使窗口尺寸没有改变也会发送该消息。如果未指定这个标志,只有在改变了窗口尺寸时才发送WM_NCCALCSIZE。  
      
         SWP_HIDEWINDOW;隐藏窗口。  
      
         SWP_NOACTIVATE:不激活窗口。如果未设置标志,则窗口被激活,并被设置到其他最高级窗口或非最高级组的顶部(根据参数hWndlnsertAfter设置)。  
      
         SWP_NOCOPYBITS:清除客户区的所有内容。如果未设置该标志,客户区的有效内容被保存并且在窗口尺寸更新和重定位后拷贝回客户区。  
      
         SWP_NOMOVE:维持当前位置(忽略X和Y参数)。  
      
      SWP_NOOWNERZORDER:不改变z序中的所有者窗口的位置。  
      
      SWP_NOREDRAW:不重画改变的内容。如果设置了这个标志,则不发生任何重画动作。适用于客户区和非客户区(包括标题栏和滚动条)和任何由于窗回移动而露出的父窗口的所有部分。如果设置了这个标志,应用程序必须明确地使窗口无效并区重画窗口的任何部分和父窗口需要重画的部分。  
      
      SWP_NOREPOSITION;与SWP_NOOWNERZORDER标志相同。  
      
      SWP_NOSENDCHANGING:防止窗口接收WM_WINDOWPOSCHANGING消息。  
      
      SWP_NOSIZE:维持当前尺寸(忽略cx和Cy参数)。  
      
      SWP_NOZORDER:维持当前Z序(忽略hWndlnsertAfter参数)。  
      
      SWP_SHOWWINDOW:显示窗口。  
      
      返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误消息,请调用GetLastError函数。  
      
      备注:如果设置了SWP_SHOWWINDOW和SWP_HIDEWINDOW标志,则窗口不能被移动和改变大小。如果使用SetWindowLoog改变了窗口的某些数据,则必须调用函数SetWindowPos来作真正的改变。使用下列的组合标志:SWP_NOMOVEISWP_NOSIZEISWP_FRAMECHANGED。  
      
      有两种方法将窗口设为最顶层窗口:一种是将参数hWndlnsertAfter设置为HWND_TOPMOST并确保没有设置SWP_NOZORDER标志;另一种是设置窗口在Z序中的位置以使其在其他存在的窗口之上。当一个窗口被置为最顶层窗口时,属于它的所有窗口均为最顶层窗口,而它的所有者的z序并不改变。  
      
      如果HWND_TOPMOST和HWND_NOTOPMOST标志均未指定,即应用程序要求窗口在激活的同时改变其在Z序中的位置时,在参数hWndinsertAfter中指定的值只有在下列条件中才使用:  
      
      在hWndlnsertAfter参数中没有设定HWND_NOTOPMOST和HWND_TOPMOST标志。  
      
      由hWnd参数标识的窗口不是激活窗口。  
      
      如果未将一个非激活窗口设定到z序的顶端,应用程序不能激活该窗口。应用程序可以无任何限制地改变被激活窗口在Z序中的位置,或激活一个窗口并将其移到最高级窗口的顶部或非最高级窗口的顶部。  
      
      如果一个顶层窗口被重定位到z序的底部(HWND_BOTTOM)或在任何非最高序的窗口之后,该窗口就不再是最顶层窗口。当一个最顶层窗口被置为非最顶级,则它的所有者窗口和所属者窗口均为非最顶层窗口。  
      
      一个非最顶端窗口可以拥有一个最顶端窗口,但反之则不可以。任何属于顶层窗口的窗口(例如一个对话框)本身就被置为顶层窗口,以确保所有被属窗口都在它们的所有者之上。  
      
      如果应用程序不在前台,但应该位于前台,就应调用SetForegroundWindow函数来设置。  
      
      Windows  CE:如果这是一个可见的顶层窗口,并且未指定SWP_NOACTIVATE标志,则这个函数将激活窗口、如果这是当前的激活窗口,并且指定了SWP_NOACTIVATE或SWP_HIDEWINDOW标志,则激活另外一个可见的顶层窗口。  
      
      当在这个函数中的nFlags参数里指定了SWP_FRAMECHANGED标志时,WindowsCE重画窗口的整个非客户区,这可能会改变客户区的大小。这也是重新计算客户区的唯一途径,也是通过调用SetwindowLong函数改变窗口风格后通常使用的方法。  
      
      SetWindowPos将使WM_WINDOWPOSCHANGED消息向窗口发送,在这个消息中传递的标志与传递给函数的相同。这个函数不传递其他消息。  
      
      Windows  CE  1.0不支持在hWndlnsertAber参数中的HWND_TOPMOST和HWND_NOTOPMOST常量。  
      
       Windows  CE1.0不支持在fuFags参数中的SWP_DRAWFRAME和SWP_NOCOPYBITS标志。  
      
      速查:Windows  NT:3.1以上版本;Windows:95以上版本;Windows  CE:1.0以上版本;头文件:winuser.h库文件:eser32lib

     

    21. 介绍函数过程中一种任意键退出同时能处理消息的实现方法

    1. 设置定时器,用于使::GetMessage(...)函数总能快速取到消息.
    2. 在函数处理中加入:

    函数每执行完一步后执行下面的代码.
    if (::GetMessage(&msg, 0, 0, 0))
    {
      if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) return ;
      ::TranslateMessage(&msg);
      ::DispatchMessage(&msg);
    }
    else ::PostQuitMessage(0);

    22. 如何隐藏工具栏

    添加如下两个函数
    隐藏:
    void CMainFrame::OnHide() 
    {
      if(m_wndToolBar.IsWindowVisible())
        m_wndToolBar.ModifyStyle(WS_VISIBLE,0);
      SendMessage(WM_SIZE);
    }

    显示:
    void CMainFrame::OnShow() 
    {
      if(!m_wndToolBar.IsWindowVisible())
        m_wndToolBar.ModifyStyle(0,WS_VISIBLE);
      SendMessage(WM_SIZE);
    }

    23. 如何动态获取工具条指针并给工具条加标题?

    [问题提出]
    工具条也是窗口,是窗口就有标题,如何给工具条加标题?
    [程序实现]
    不想动态改变工具条的标题就在CMainFrame::OnCreate()中:
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    ......
    m_wndToolBar.SetWindowText(_T("Standdard")); 
    return 0;
    }
    若想动态改变工具条的标题,如下:
    声明一个菜单,并响应事件,如响应:OnMyToolBar()函数
    void CMainFrame::OnMyToolBar() 
    {
    // TODO: Add your command handler code here
    CToolBar *pToolBar = (CToolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR); 
    pToolBar->SetWindowText (_T("Standdard"));
    }
    不要在TooBar悬浮时做OnMyToolBar()会出错的. 
    顺便提一下如何获得状态条的指针:
    CStatusBar * pStatusBar =(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);

    24. 在状态条中显示鼠标的设备坐标与逻辑坐标

    显示器的设备坐标系的原点在客户区的左上角,x轴向右增长,y轴向下增长。我们要设置的逻辑坐标系的原点则在客户区的中心,x轴向右增长,y轴向上增长,如一个笛卡尔坐标系一般。

    为CChildView添加一个成员函数void OnPrepareDC(CDC * pDC, CPrintInfo * pInfo = NULL);

    void OnPrepareDC(CDC * pDC, CPrintInfo * pInfo){
     CRect rect;

     // 设置映射模式为LOMETRIC (0.1mm),右上为增长方向
     pDC->SetMapMode (MM_LOMETRIC);

     // 将坐标原点定在客户区的中心
     GetClientRect(rect);
     pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);
    }
    为CChildView响应鼠标移动消息,并在状态条中显示鼠标的坐标值。m_ptMouse数据成员是原打算做十字交叉线用的,在此使用没有实际意义。

    void CChildView::OnMouseMove(UINT nFlags, CPoint point){
     CClientDC dc(this);
     CString str;
     
     OnPrepareDC(&dc);

     //要访问类CMainFrame,需要将mainfrm.h文件引入
     CMainFrame * pFrame = (CMainFrame *) AfxGetApp()->m_pMainWnd;

     //要访问CMainFrame的数据成员m_wndStatusBar,需要手工修改mainfrm.h,public这个数据成员
     CStatusBar * pStatus = (CStatusBar *) &pFrame->m_wndStatusBar;
     
     m_ptMouse = point;
     str.Format ("设备坐标 X=%i pixel, Y=%i pixel", m_ptMouse.x, m_ptMouse.y);
     pStatus->SetPaneText(1, str);
     
     dc.DPtoLP(&m_ptMouse);
     str.Format ("逻辑坐标 X=%i * 0.1mm, Y=%i * 0.1mm", m_ptMouse.x, m_ptMouse.y);
     pStatus->SetPaneText(2, str);
    }

    25. 如何用VC++ 动态修改应用程序菜单

     [问题提出]
      本文将介绍一些使用CMenu的方法,如查找指定菜单,在指定选项前添加菜单项.....

     [解决方法]
      使用CWnd::GetMenu( )访问主菜单,GetMenu( )返回指向CMenu对象的指针,它有一些成员函数,允许我们修改一个菜单。
      1) 如何实现找到一个菜单项:
      步骤如下:
      {
         //动态修改菜单:
         // Get the Main Menu
         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;
         }
         CString s;
         s.Format("%d",i);//菜单项的位数.
         AfxMessageBox(s);
         ASSERT(pSubMenu);
      }

      2) 动态编辑菜单:
      步骤如下(可以用上例的pSubMenu,要加的菜单你自己定义.):
      1) 添加一个称为Wzd2,命令ID为IDC_NAME_NEW1的菜单命令到该菜单中,可以用:
         pSubMenu->AppendMenu(0,IDC_NAME_NEW1,"New&1");

      2) 在New1前插入New2,可以用:
         pSubMenu->InsertMenu(IDC_NAME_NEW1,MF_BYCOMMAND,IDC_NAME_NEW2, "New&2");

      3) 把New1改变成New3,可以用:
         pSubMenu->ModifyMenu(IDC_NAME_NEW1,MF_BYCOMMAND,IDC_NAME_NEW3, "New&3");

      4) 删除该菜单中第二项,可以用:
         pSubMenu->RemoveMenu(1,MF_BYPOSITION);

    26. VC++中的3D按钮的编程

    运行AppWizard生成一个基于对话框的test工程,在对话框中加入一个CButton控件。在CButton控件的General属性页将控件的ID改为IDC_3DTEXTBTN,Caption改为“谁与争疯”,在控件Styles属性页选中OwnerDraw,其余设置保持默认。
      用classwizard创建一个新类:C3dTextButton,基类为CButton。为C3dTextButton类添加一个protected的函数void Draw(CDC* pDC, const CRect& rect, UINT state)。如下所示编写代码:
      void C3dTextButton::Draw(CDC *pDC, const CRect &rect, UINT state)
      {
        CString text; GetWindowText(text);
        int l=text.GetLength();
        CRect rectClient=rect;
      
        //获得控件的字体
        CFont* pFont=GetFont();
      
        //确定所选字体有效高度和宽度
        LOGFONT logfont;
        pFont->GetObject(sizeof(LOGFONT),&logfont);
        if(logfont.lfHeight==0)logfont.lfHeight=20;
        logfont.lfWidth=0;//宽度设为0,宽度值由高度确定
        logfont.lfWeight=1000;
        logfont.lfEscapement=logfont.lfOrientation=0;
        CFont tryfont; VERIFY(tryfont.CreateFontIndirect(&logfont));
        CFont* pFontOld=pDC->SelectObject(&tryfont);
      
        //根据控件大小,调整字体的高度,使文本与控件协调
        CSize textSizeClient=pDC->GetTextExtent(text,l);
        if(rectClient.Width()*textSizeClient.cy>rectClient.Height()*textSizeClient.cx)
        {
          logfont.lfHeight=::MulDiv(logfont.lfHeight,rectClient.Height(),textSizeClient.cy);
        }
        else{
          logfont.lfHeight = ::MulDiv(logfont.lfHeight,rectClient.Width(),textSizeClient.cx);
        }
      
        //创建并选择协调后的字体
        CFont font; font.CreateFontIndirect(&logfont);
        pDC->SelectObject(&font);
        textSizeClient=pDC->GetTextExtent(text,l);
        //确定文本与控件边界的距离minx,miny
        int minx=rectClient.left+(rectClient.Width()-textSizeClient.cx)/2;
        int miny=rectClient.top+(rectClient.Height()-textSizeClient.cy)/2;
        int oldBkMode=pDC->SetBkMode(TRANSPARENT);
        COLORREF textcol=::GetSysColor(COLOR_BTNTEXT);
        COLORREF oldTextColor=pDC->SetTextColor(textcol);
        int cx = minx;
        int cy = miny;
        int s=(state&ODS_SELECTED)?-1:+1;
        cx+= 3; cy+= 3;
      
        //实现3D效果
        pDC->SetTextColor(::GetSysColor(COLOR_3DDKSHADOW));
        pDC->TextOut(cx-s*2,cy+s*2,text);
        pDC->TextOut(cx+s*2,cy-s*2,text);
        pDC->TextOut(cx+s*2,cy+s*2,text);
        pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
        pDC->TextOut(cx+s*1,cy-s*2,text);
        pDC->TextOut(cx-s*2,cy+s*1,text);
        pDC->TextOut(cx-s*2,cy-s*2,text);
        pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));
        pDC->TextOut(cx-s*1,cy+s*1,text);
        pDC->TextOut(cx+s*1,cy-s*1,text);
        pDC->TextOut(cx+s*1,cy+s*1,text);
        pDC->SetTextColor(::GetSysColor(COLOR_3DLIGHT));
        pDC->TextOut(cx,cy-s*1,text);
        pDC->TextOut(cx-s*1,cy,text);
        pDC->TextOut(cx-s*1,cy-s*1,text);
        pDC->SetTextColor(textcol);
      
        //输出标题
        pDC->TextOut(cx,cy,text);
      
        //恢复设备描述表
        pDC->SetTextColor(oldTextColor);
        pDC->SetBkMode(oldBkMode);
        pDC->SelectObject(pFontOld);
      }

      用classwizard重载C3dTextButton类的DrawItem函数。编写代码如下所示:
      void C3dTextButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
      {
        CDC* pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
        ASSERT_VALID(pDC);
        CRect rectClient=lpDrawItemStruct->rcItem;
        Draw(pDC,rectClient,lpDrawItemStruct->itemState);
      }
      用classwizard为IDC_3DTEXTBTN建立一个C3dTextButton控件变量m_3dTextButton1。

    把“3dTextButton.h”加入testDlg头文件。编译并测试应用程序。

    27. 如何正确的得到ComBox的指针

    CComboBox *mComb = (CComboBox*)GetDlgItem(IDC_DuanCB);
    CComboBox *mComb = (CComboBox*)::GetDlgItem(m_hWnd,IDC_DuanCB);

    28. 如何让对话框中的CEdit控件类接收对话框的消息


    // 如何让对话框中的CEdit控件类接收对话框的消息

    1、在对话框中增加一个ID 为IDC_EDIT1的CEdit1控件

    2、通过ClassWizard 生成一个基于CEdit的新类CMyEdit,

    CMyEdit m_wndEdit;

    3、在对话框OnInitDialog()中,将m_wndEdit子类化,使其能够接受对话框的消息。

    m_wndEdit.SubclassDlgItem (IDC_EDIT1,this);

    29.利用WM_CTLCOLOR消息实现编辑控制(Edit Control)的文本与背景色的改变

    首先要明白:WM_CTLCOLOR是一个由控制(Control)发送给它父窗口的通知消息(Notification message)。

    实现步骤:
    生成一个标准的单文档应用程序框架,假设应用程序的名称为Color。我将利用它的About对话框做示范。在About dialog中添加两个Edit control,设定其ID为IDC_EDIT1与IDC_EDIT2。

    第一种方法(对应于IDC_EDIT1): 按照标准的Windows编程,由其父窗口的消息处理函数负责处理WM_CTLCOLOR消息。

    1. 在CAboutDlg中添加一个数据成员:HBRUSH m_brMine;
    2. 利用向导映射AboutDlg的WM_CTLCOLOR消息,产生函数:HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    pDC是AboutDlg的设备上下文,pWnd是AboutDlg中发送该消息的control指针,nCtlColor市Control的类型编码。对其进行如下修改:

    HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
     if ((pWnd->GetDlgCtrlID() == IDC_EDIT1) && (nCtlColor == CTLCOLOR_EDIT))
     {
       COLORREF clr = RGB(255,0,0);
       pDC->SetTextColor(clr);  //设置红色的文本
       clr = RGB(0,0,0);
       pDC->SetBkColor(clr);   //设置黑色的背景
       m_brMine = ::CreateSolidBrush(clr);
       return m_brMine; //作为约定,返回背景色对应的刷子句柄
     }
     else
     {
       HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
       return hbr;
     }
    }

    第二种方法(对应于IDC_EDIT2): 
    利用MFC 4.0的新特性: Message reflection。

    1.利用向导添加一个新的类:CColorEdit,基类为CEdit;
    2.在CColorEdit中添加一个数据成员: HBRUSH m_bkBrush;
    3.利用向导映射CColorEdit的"=WM_CTLCOLOR"消息,产生函数:

    HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor); 

    对其进行如下修改:

    HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor) 
    {
     COLORREF clr = RGB(0,0,0);
     pDC->SetTextColor(clr);  //设置黑色的文本
     clr = RGB(255,0,0);
     pDC->SetBkColor(clr);   //设置红色的背景
     m_bkBrush = ::CreateSolidBrush(clr);
     return m_bkBrush; //作为约定,返回背景色对应的刷子句柄
    }

    4.利用向导为IDC_EDIT2生成一个数据成员CColorEdit m_coloredit;
    5.在定义CAboutDlg的color.cpp文件中加入:#include "coloredit.h"

    30. 如何防止密码被非法获取?

     [问题提出]
      这两天大家比较专注在获取Edit密码框的密码.在盗取时,我们如何防范呢?
     
     [解决方法]
      此方法针对于通过SendMessage向此窗口发送WM_GETTEXT或EM_GETLINE消息来取得密码.跟我来.
     
     [程序实现]
      方法很简单,用CWnd::DefWindowProc函数拦截得到的消息(向Edit发的).
      建立名为My的对话框工程.建立一个Edit控件ID=IDC_EDIT1.建一个新类名为CMyProtectEdit,派生于CEdit.
      在MyDlg.cpp中声明全局变量:BOOL g_bIdentity;
      BOOL g_bIdentity;

      在MyProtecEdit.cpp中:
      extern BOOL g_bIdentity;

      响应CMyProtectEdit的DefWindowProc函数:
      LRESULT CMyProtectEdit::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
      {
        // TODO: Add your specialized code here and/or call the base class
        // 对Edit的内容获取必须通过以下两个消息之一,不对其采用默认的处理:
        if(( message == WM_GETTEXT) || ( message == EM_GETLINE))
        {  //检查是否为合法
         if(!g_bIdentity)
         {  //非法获取,显示非法信息
           AfxMessageBox(_T("不能让你看我的密码,:( !"));
           return 0;
         )
         g_bIdentity = FALSE;//合法获取
        }
        
        return CEdit::DefWindowProc(message, wParam, lParam);
      }

      然后在MyDlg.cpp中
      void CMyDlg::DoDataExchange(CDataExchange* pDX)
      {
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CGetPasswordDlg)
        // NOTE: the ClassWizard will add DDX and DDV calls here
        if( pDX->m_bSaveAndValidate)
        {
         g_bIdentity = TRUE;
        }   
        //}}AFX_DATA_MAP
      }
      即可.找个程序(盗取)的试试.

    31. 如何在编辑控件中以追加的方式添入字符?

     [问题提出]
      SetDlgItemText可以向Edit控件中输入字符,发送更新的消息也可是Edit控件显示与其关联的变量的值,但若是向已有的Edit字符后追加字符,该如何做?
     [程序实现]
      建立名为My的对话框工程,添加一个Edit和一个Button控件.Edit的ID=IDC_EDIT1,Button的ID=IDC_BUTTON1.建立和IDC_BUTTON1的响应函数:OnButton1()
      void CMyDlg::OnButton1() 
      {
        CString pText="你好";
        CEdit *m_Edit=(CEdit *)GetDlgItem(IDC_EDIT1);
        int nLen=m_Edit->GetWindowTextLength(); 
        m_Edit->SetFocus(); 
        m_Edit->SetSel(nLen, nLen); 
        m_Edit->ReplaceSel(pText); 
      }
      在Edit控件中输入字符,想追加时按IDC_BUTTON1按钮.看看效果.

    32.属性页标题改名

    我用CPropertySheet创建属性页,用的CPropertyPage对象只有一个,也就是每个属性页的内容一样.现在的问题是:这样每个属性页的标题都是一样的,是对话框的标题!怎样动态的改变这个标题,使每个属性页的标签的名称都不同??


    CTabCtrl * pCtrl = pSheet->GetTabControl();
    TCITEM tc;
    tc.mask = TCIF_TEXT;
    tc.pszText = "新标题";
    pCtrl->SetItem(0,&tc);//0即是你要改的TAb的索引

    33. 怎样去掉属性页的Apply与Help按钮?

    //去掉Help
      m_psh.dwFlags |= PSH_HASHELP ;
      m_psh.dwFlags &= ~PSH_HASHELP ;
    //除掉应用按钮 m_psh.dwFlags|=PSH_NOAPPLYNOW; 

    34. 如何给树控件加入工具提示

    1.首先给树控件加入TVS_INFOTIP属性风格,如下所示:

    if (!m_ctrlTree.Create(WS_CHILD|WS_VISIBLE|
      TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT|TVS_SHOWSELALWAYS|TVS_INFOTIP, //加入提示TVS_INFOTIP,jingzhou xu(树控件ID:100)
       CRect(0, 0, 0, 0), &m_wndTreeBar, 100))
      {
       TRACE0("Failed to create instant bar child/n");
       return -1;
      }

    2.其次加入映射消息声明,如下所示:

    afx_msg void OnGetInfoTip(NMHDR* pNMHDR,LRESULT* pResult);    //树控件上加入提示消息,jingzhou xu  

    ON_NOTIFY(TVN_GETINFOTIP, 100, OnGetInfoTip)       //树控件条目上加入提示,jingzhou xu

    3.最后加入呼应涵数处理:

    void CCreateTreeDlg::OnGetInfoTip(NMHDR* pNMHDR, 
                      LRESULT* pResult) 
     {
     *pResult = 0;
     NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR;
     LPARAM itemData = (DWORD) pTVTipInfo->lParam;
     //对应每个条目的数据
     HTREEITEM hItem = pTVTipInfo->hItem;
     CString tip;
     HTREEITEM hRootItem = m_chassisTree.GetRootItem();
     if (hRootItem != pTVTipInfo->hItem)
     {
      tip = "树结点的提示";
     }
     else
     {
      tip = "树根上的提示";
     }
     strcpy(pTVTipInfo->pszText, (LPCTSTR) tip);
    }

    35. 如何在TreeList中加图标?

     [问题提出]
     请问treeview控件和treectrl控件的用法有何不同呢?向如何imagelist控件中加图象呀?
     [解决方法]
     1)
      HICON hicon[8];
      m_imageList.Create(16,16,0,8,8);
      hicon[0]=AfxGetApp()->LoadIcon(IDI_ICON0);
      hicon[1]=AfxGetApp()->LoadIcon(IDI_ICON1);
      hicon[2]=AfxGetApp()->LoadIcon(IDI_ICON2);
      hicon[3]=AfxGetApp()->LoadIcon(IDI_ICON3);
      hicon[4]=AfxGetApp()->LoadIcon(IDI_ICON4);
      hicon[5]=AfxGetApp()->LoadIcon(IDI_ICON5);
      hicon[6]=AfxGetApp()->LoadIcon(IDI_ICON6);
      hicon[7]=AfxGetApp()->LoadIcon(IDI_ICON7);
      for(int n=0;n<8;n++)
        m_imageList.Add(hicon[n]);

      CTreeCtrl *pTree=(CTreeCtrl *)GetDlgItem(IDC_TREE);
      pTree->SetImageList(&m_imageList,TVSIL_NORMAL);

     2)
      CImageList cil1;
      cil1.Create(32,32,TRUE,2,2);
      cil1.Add(pApp->LoadIcon(IDI_DAO1));
      cil1.Add(pApp->LoadIcon(IDI_DAO2));
      cil1.Add(pApp->LoadIcon(IDI_DAO3));
      cil1.Add(pApp->LoadIcon(IDI_DAO4));
      cil1.Add(pApp->LoadIcon(IDI_DAO5));
      cil1.Add(pApp->LoadIcon(IDI_DAO6));
      cil1.Add(pApp->LoadIcon(IDI_DAO7));
      cil1.Add(pApp->LoadIcon(IDI_DAO8));
      cil1.Add(pApp->LoadIcon(IDI_DAO9));
      
      //设置图象列表
      m_list.SetImageList(&cil1,LVSIL_NORMAL);

    36. 如何双击列表框项启动一个与文件关联的程序?

    有人问我如何双击列表框项启动一个程序?其实这个问题很简单,Windows中有一个API函数可以打开任何类型的文件:

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

    参数 lpFileName 是文件的全路径名。用这个变量你可以传递象“C://MyExcelFile.xls”或者“http://www.vckbase.com”启动Excel程序或者浏览器程序。如果你只是想获取与文件关联的程序名,而不是要运行程序,那么调用::FindExecutable就可以了。

    37. 如何防止在listbox中添加很多数据出现不停的刷新?

     [问题提出]
      在listbox添加很多数据的时候,由于控件不停的刷新,导致出现闪烁,如何解决?
     [解决方法]
      再添加数据以前,禁止控件刷新,数据添加完毕以后,再刷新一次。
     [程序实现](其中:m_ListBox是CListBox的控件类型的变量)
      m_ListBox.LockWindowUpdate();//禁止本listbox刷新。
      for(int i=0;i<9999;i++)
      {
         m_ListBox.AddString("test");
      }//添加数据。 
      this->RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);

    38. 如何得到CListBox所选择项的String?

     [问题提出]
     如何得到CListBox所选择项的String
     [解决方法]
     用到:CListBox::GetText()
     [程序实现]
     CString scInfo; 
     pList->GetText( GetCurSel(),scInfo);

    39. 用鼠标移动基于对话框的无标题栏程序的简单方法

    void CVCTestDlg::OnLButtonDown(UINT nFlags, CPoint point) 
    {
      //一句话解决问题 
      SendMessage(WM_SYSCOMMAND,0xF012,0);
      CDialog::OnLButtonDown(nFlags, point);
    }

    40. 如何改变框对话或窗体视窗的背景颜色

    调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。
    BOOL CSampleApp : : InitInstance ( )
    {

    //use blue dialog with yellow text .
    SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 , 255 , 0 ) ) ;

    }
    需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。
    首先,给对话基类增加一人成员变量CBursh :
    class CMyFormView : public CFormView
    {

    private :
    CBrush m_ brush ; // background brush

    } ;
    其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。
    CMyFormView : : CMyFormView ( )
    {
    // Initialize background brush .
    m_brush .CreateSolidBrush (RGB ( 0, 0, 255 ) )
    }
    最后,使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtlColor参量。
    HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor )
    {
    // Determine if drawing a dialog box . If we are , return +handle to
    //our own background brush . Otherwise let windows handle it .
    if (nCtlColor = = CTLCOLOR _ DLG )
    return (HBRUSH) m_brush .GetSafeHandle ( ) ;
    return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor );
    }

    41.如何禁止对话框关闭按钮和浮动工具条上的系统菜单

    1、禁止对话框中的关闭按钮有二种方法。
    第一种方法,用ModiftMenu()涵数来实现:

    CMenu* pMenu = this->GetSystemMenu(FALSE);
    pMenu->ModifyMenu(SC_CLOSE,MF_BYCOMMAND | MF_GRAYED );

    第二种方法,用EnableMenuItem()涵数来实现:

    CMenu* pMenu = this->GetSystemMenu(FALSE);
    pMenu->EnableMenuItem( SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);

    2、禁止浮动工具条上的系统菜单。
    新建一个CToolBar的派生类CxxToolBar,在新类中的左键双击(CxxToolBar::OnLButtonDblClk(...))
    和左键单击(CxxToolBar:: OnLButtonDown(...))涵数中分别加入下面代码既可:
    if (IsFloating()) //工具条正在浮动状态中
    {
      CWnd* pMiniFrame;
      CWnd* pDockBar;

      pDockBar = GetParent();
      pMiniFrame = pDockBar->GetParent();

      //去除其上系统菜单
      pMiniFrame->ModifyStyle(WS_SYSMENU, NULL);

      //重绘工具条
      pMiniFrame->ShowWindow(SW_HIDE);
      pMiniFrame->ShowWindow(SW_SHOW);
    }

    3、禁止窗口最大化按钮
    在PreCreateWindow()涵数中去掉WS_MAXIMIZEBOX风格显示既可。
    BOOL CxxFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
    {
      cs.style &= ~WS_MAXIMIZEBOX;
      return CFrameWnd::PreCreateWindow(cs);
    }

    42.如何拷贝一个工程的对话框资源到另一个工程中?

     有两种方法可以实现:
     
     1)你可以直接拷贝resource,用VC++以文本的方式或者直接用文本编辑器打开.rc文件,将有关的片段从
    一个工程拷贝到另一个工程.你可以通过查找如下字样的片段(此片段用来定义对话框资源)来拷贝你要
    的部分:
     
     IDD_MYDIALOG_ID DIALOG DISCARDABLE 0, 0, 235, 55
     
     这里的IDD_MYDIALOG_ID是你的对话框的ID,将到此片段结尾的部分全拷下来,通常你还要给新的工程
    加一个ID(通过DevStudio的工具或者直接修改resource.h文件).

     2)可以通过DevStudio的copy/paste功能.首先,在编辑器以"auto"模式打开.rc文件,这时resource
    正确的显示出来.然后,选中要拷贝的对话框的ID,在Edit菜单里选Copy或者按住Ctrl+C.然后打开目标
    resource文件,在Edit菜单里选Paste或者按住Ctrl+V.

    43.如何实现点一下对话框外面的区域,自动隐藏对话框?

     [问题提出]
      如果想在点击对话框外面的地方使得对话框关闭,该如何做?

     [解决方法]
      试试下面的代码,原理是在激活对话框时,捕获鼠标的动作,当鼠标点击时判断是否点击在对话框外,是的话就释放对话框.

     [程序实现]
      建立名为My的对话框程序.实现如下步骤:
      在MyDlg.h中加入:

      class CShowWindow1Dlg : public CDialog
      {
       // Construction
       public:
         int m_cx;
         int m_cy;
         ......
      };

      在MyDlg.cpp中:

      //定义消息映象,处理鼠标单击及激活
      BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
        //{{AFX_MSG_MAP(CMyDlg)
        ON_WM_LBUTTONDOWN()
        ON_WM_ACTIVATE()
        //}}AFX_MSG_MAP
      END_MESSAGE_MAP()

      void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
      {
        CRect rect;
        GetClientRect(&rect);
        rect.InflateRect(m_cx, m_cy);
     
        //Release dialog if the user click outside it.
        if(!rect.PtInRect(point))
        {
          EndDialog(IDCANCEL);
        }

        CDialog::OnLButtonDown(nFlags, point);
      }

      void CMyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
      {
        CDialog::OnActivate(nState, pWndOther, bMinimized);

        if( nState == WA_ACTIVE || nState == WA_CLICKACTIVE)
          SetCapture();
        else
          ReleaseCapture();
      }

      BOOL CMyDlg::OnInitDialog()
      {
        CDialog::OnInitDialog();
        .....
        
        OSVERSIONINFO info;
        memset((char*)&info, 0, sizeof(OSVERSIONINFO));
        info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        if(GetVersionEx(&info))
        { //we don't run on Win32s, so check only two values
          if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
          { //On windows 95
           m_cx = GetSystemMetrics(SM_CXFIXEDFRAME);
           m_cy = GetSystemMetrics(SM_CYFIXEDFRAME);
          }
          else
          { //On NT
           m_cx = GetSystemMetrics(SM_CXDLGFRAME);
           m_cy = GetSystemMetrics(SM_CYDLGFRAME);
          }
        }
      }

       说明:
       1)WM_ACTIVATE消息在ClassWizard中没有,按如下步骤添加,右击CMyDlg类,选Add Windows Message Handle,接着在Filter for messages available to中选Window,在New Windows messages/events列表中就会出现WM_ACTIVATE,选中,点击Add Handler
       2)SM_CXDLGFRAME,SM_CYDLGFRAME  NT中取得有WS_DLGFRAMEstyle风格的窗口的高和宽 95中已经废弃而采用SM_CX_FIXEDFRAME和SM_CYFIXEDFRAME

    44. 初始化应用程序的大小

    如果想使应用程序界面(文档)在开始运行是按你的尺寸展现在屏幕上,
     添加代码如下:
     BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
     {
       int xsize=::GetSystemMetrics(SM_CXSCREEN);
       int ysize=::GetSystemMetrics(SM_CYSCREEN);
       cs.cx=xsize*5/10;
       cs.cy=ysize*5/10;
       cs.x=(xsize-cs.cx)/2;
       cs.y=(ysize-cs.cy)/2;  

     }
     其中的5/10是你的初始界面占屏幕的百分比,可以自己修改。如果想使应用程序大小固定添加cs.style&=~WS_THICKFRAME;

    45. 如何得到视图指针?

    [问题提出]
      现在你有一个多线程的Demo,你想在多线程里处理视图指针里的函数,我们给这个函数起个名字:Put();该如何实现呢?
      //有两种方法可以实现你的要求:
      //1)第一种方法:
      //要是多线程不是在App.cpp里出现,那么要在多线程的.cpp中加上extern CYourApp theApp;
      //获得文档模板:
      POSITION curTemplatePos = theApp.GetFirstDocTemplatePosition();
      CDocTemplate *m_doc=theApp.GetNextDocTemplate(curTemplatePos);

      //获得文档:
      curTemplatePos=m_doc->GetFirstDocPosition();
      CYourDoc *m_pdoc=(CA8Doc*)m_doc->GetNextDoc(curTemplatePos);
      
      //获得视图:
      curTemplatePos=m_pdoc->GetFirstViewPosition();
      CYourView *m_pview=(CYourView*)m_pdoc->GetNextView(curTemplatePos);

      //调用视图函数:
      m_pview->Put();

      //2)第二种方法:
      //获得窗体指针:
      CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;

      //获得与该窗体符合的视图:
      CYourView *m_pView = (CYourView *) pFrame->GetActiveView();

      //调用视图函数:
      m_pView->Put();

    46. 如何使我的程序在启动时不创建一个新文档?

    [问题]
    如何使我的程序在启动时不创建一个新文档? 
    [解答]
    在程序的InitInstance中的ProcessShellCommand函数之前加入: cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing

    47. 如何将标题栏上的右键菜单屏蔽掉?

     [解决方法]
      右键菜单是系统菜单,只要将其WS_SYSMENU的属性去掉即可.
     [程序实现]
      int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
      {
         ........
      long style = GetWindowLong(m_hWnd, GWL_STYLE);
         style &= ~WS_SYSMENU;
         SetWindowLong(m_hWnd, GWL_STYLE, style);

      return 0;
      }

    48.如何全屏显示(没有标题,没有菜单,没有工具条)

     [解决方法]
      重载CMainFrame的ActivateFrame函数:
      void CMainFrame::ActivateFrame(int nCmdShow) 
      {
         CRect cRectdesktop;
         WINDOWPLACEMENT windowplacement;
         ::GetWindowRect(::GetDesktopWindow(),&cRectdesktop);
         ::AdjustWindowRectEx(&cRectdesktop,GetStyle(),TRUE,GetExStyle());
         windowplacement.rcNormalPosition=cRectdesktop;
         windowplacement.showCmd=SW_SHOWNORMAL;
         SetWindowPlacement(&windowplacement); 

         CFrameWnd::ActivateFrame(nCmdShow);
      }

    49.如何设置有背景颜色的文本
    (1)[解决方法]
      用到了CDC::SetBkMode();
     
     [程序实现] 
      void CMyView::OnDraw(CDC* pDC)
      {
        CMyDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
        CRect rcView;//加這兩句
        GetClientRect(rcView);
        // TODO: add draw code for native data here
        CString str (_T("Perfect Text...")); 
        pDC->SetBkMode(TRANSPARENT); 
        rcView.OffsetRect (1,1); 
        pDC->SetTextColor(RGB (0,0,0)); 
        pDC->DrawText(str,str.GetLength(),rcView,DT_SINGLELINE | DT_CENTER | DT_VCENTER); 
        rcView.OffsetRect(-1,-1); 
        pDC->SetTextColor(RGB (255,0,0)); 
        pDC->DrawText(str,str.GetLength(),rcView,DT_SINGLELINE | DT_CENTER | DT_VCENTER); 
      }
    (2) 建立名为My的SDI或MDI,并响应WM_ERASEBKGND.
      BOOL CMyView::OnEraseBkgnd(CDC* pDC) 
      {
       // TODO: Add your message handler code here and/or call default
       CBrush Brush (RGB(114,147,171)); 
       // Select the brush into the device context . 
       CBrush* pOldBrush = pDC->SelectObject(&Brush); 
       // Get the area that needs to be erased . 
       CRect ViewClip; 
       pDC->GetClipBox(&ViewClip); 
       //Paint the area. 
       pDC->PatBlt(ViewClip.left,ViewClip.top,ViewClip.Width(),ViewClip.Height(),PATCOPY); 
       //Unselect brush out of device context . 
       pDC->SelectObject (pOldBrush ); 
       // Return nonzero to half fruther processing . 

       return TRUE;
       return CView::OnEraseBkgnd(pDC);
      }
      此方法也适合基类是EditView的SDI或MDI的情况,但是字体的颜色和底色不行.建议用WM_CTLCOLOR.

    50.串太长时往让其末尾显示一个省略号(在SDI或MDI的View中)

     [问题提出]
      如何在串太长时往让其末尾显示一个省略号(在SDI或MDI的View中)?
     [程序实现]
      建立名为My的SDI或MDI工程.
      void CMyView::OnDraw(CDC* pDC)
      {
        CMyDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
        // TODO: add draw code for native data here
        pDC->DrawText(CString("It's a long string,so we will add a '...' at the end."),CRect (110, 110, 180, 130),DT_LEFT | DT_END_ELLIPSIS); 
        //Add ellpsis to middle of string if it does not fit 
        pDC->DrawText(CString("It's a long string,so we will add a '...' at the end."),CRect (110, 140, 300, 160),DT_LEFT | DT_PATH_ELLIPSIS); 
      }

    51. 如何获得其他程序的图标,并显示在View中

     [问题提出]
     有的时候,如:类资源管理器会遇到获得程序图标并显示的操作,如何实现呢?
     [解决方法]
     SDK函数SHGetFileInfo来获得有关文件的很多信息:如大小图标,属性,类型等. 
     [程序实现]
     建立名为My的SDI工程.在OnPaint()函数中加入:
     void CMyView::OnPaint() 
     {
      CPaintDC dc(this); // device context for painting
      HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0); 
      if (hIcon && hIcon!=(HICON)-1) 
      dc.DrawIcon(10,10,hIcon); 

      // TODO: Add your message handler code here
      // Do not call CView::OnPaint() for painting messages
     }
     说明:_T("NotePad.exe")指的是要获得什么程序的图标.
     或者在OnDraw()中(此时必须保证没有OnPaint()函数,想想为何?)
     void CMyView::OnDraw(CDC* pDC)
     {
      CMyDoc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);
      // TODO: add draw code for native data here
      HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0); 
      if (hIcon &&hIcon!=(HICON)-1) 
      pDC->DrawIcon(10,10,hIcon); 
     }

    52 .RichEdit
    在Dialog(FormView中打开)中加入CRichEdit控件后,这个dialog 为什么打不开如何处理?
     [解决方法]
     在函数:InitInstance的第一句加入AfxInitRichEdit();

    53. 如何使FormView中显示dialog时,不是凹的?

     [问题提出]
     为什么FormView中显示dialog时,是凹的,能不能不这样
     [解决方法]
     在Dialog的属性中:
      增加属性WS_BORDER  或者 WS_EX_WINDOWEDGE
     用程序实现:
     pView->ModifyStyle(,WS_BORDER) 或者pView->ModifyStyleEx(,WS_EX_WINDOWEDGE )

    54. 如何改变窗口标题?

     [问题提出]
      在应用程序的不同运行时期,要反映当前状态往往会修改应用程序标题.

     [解决方法]
      在MFC类库中提供了CWnd::SetWindowText函数,通过该函数可以改变任何窗体(包括控件)的标题.
      改变主窗体的标题:
      CWnd *m_pMainWnd;
      m_pMainWnd=AfxGetMainWnd();
      m_pMainWnd->SetWindowText(_T("改变标题"));
      当改变多视MDI的子窗口的标题时,用:
      GetParentFrame()->SetWindowText(_T("MDI Child改变标题"));
      当改变按钮的标题时(假设按钮的ID=IDC_BUTTON1):
      GetDlgItem(IDC_BUTTON1)->SetWindowText(_T("Button 改变标题"));
      运行看看.

    55.图标透明

    (1).Windows中的图标其实是有两个图像组成的,其中一个用于与它要显示的位置的图像做“AND”操作,另一个作“XOR”操作。
    透明:用“白色”AND,用“黑色”XOR
    反色:用“白色”AND,用“白色”XOR
    正常色:用“黑色”AND,用正常颜色XOR.
    (2). WIN9X中好像是对像素的操作实现透明的
    WIN2K中就有API直接实现透明了!
    WIN2K中
    GetWindowLong
    SetWindowLong
    SetLayeredWindowAttributes
    三个API就可以实现透明了!
    (3) 
    ::DrawIconEx(pDC->GetSafeHdc(),point.x,point.y,icon,icosize,icosize,0,NULL,DI_NORMAL);

    56.ASSERT()是干什么用的

    ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。例如,变量n在程序中不应该为0,如果为0可能导致错误,你可以这样写程序: 
      ...... 
      ASSERT( n != 0); 
      k = 10/ n; 
      ...... 
      ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。 
      assert()的功能类似,它是ANSI C标准中规定的函数,它与ASSERT的一个重要区别是可以用在Release版本中。

    56. 将RADIO控件初始状态设置成为选中

    1、"在OnInitialDialog中用CButton::CheckRadioButton(...)
    2、"在OnInitialDialog中用CButton::SetCheck(...)
    3、"关联一个整型值,在构造函数中设为0。

    57.获得视图

    CFrameWnd* pFrameWnd = (CFrameWnd*)theApp.GetMainWnd();
    CMyView* pView = (CMyView*)pFrameWnd->GetActiveView();

    58.如何得到屏幕的真实尺寸

    [问题提出]
    我的屏幕是1024*800,如何得到屏幕的真实大小,我用GetSystemMetrics(SM_CYFULLSCREEN)得到的高度总是小于800
    [问题解答]
    GetSystemMetrics(SM_CYFULLSCREEN)得到的只是屏幕用户区的大小。要得到屏幕的真实大小需要使用
    GetDeviceCaps函数,该API函数原型是这样的:

    int GetDeviceCaps(
     HDC hdc,   // handle to DC
     int nIndex  // index of capability
    );
    ///得到屏幕尺寸的代码如下
    void CMyDlg::OnPaint() 
    {
      CPaintDC dc(this); 
      int cx = ::GetDeviceCaps(dc.m_hDC,HORZRES);///得到宽度
      int cy = ::GetDeviceCaps(dc.m_hDC,VERTRES);///得到高度
      CDialog::OnPaint();

    59. 修改标题栏高度

    NONCLIENTMETRICS nm
    调用SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(nm),&nm,0)
    重设SystemParametersInfo(SPI_SETNONCLIENTMETRICS,sizeof(nm),&nm,0)

    60. 如何实现“气球式”工具提示。

    本程序介绍一个与CToolTipCtrl相似的类CTooolTipWnd。 
    使用该类的方法如下: 
    1. 增加ToolTipWnd.cpp到工程文件。 
    2. 在头文件中添加#include "ToolTipWnd.h" 。 
    3. 在类声明中添加: 
    CToolTipWnd m_BalloonToolTip; 
    4. 在OnInitDialog(对话框)或OnInitialUpdate(表单视)中添加下面代码: 
      m_BalloonToolTip.Create(this); 
      m_BalloonToolTip.AddTool(GetDlgItem(), , [text color]); 
    eg. 
      m_BalloonToolTip.AddTool(GetDlgItem(IDC_EDIT1),"Tooltip", RGB(255,0,0)); 
      第三个参数为可选,缺省为RGB(0, 0, 0)。缺省文本颜色可以用SetDefTextColor进行设置。 
    4. 重载PreTranslateMessage并添加下面代码: 
      if(m_BalloonToolTip) 
        m_BalloonToolTip.RelayEvent(pMsg);
    61. dlg 上建立View的方法:

    OnInitDialog()
    {
     CDialog:;OnInitDialog();

    CRect rectWindows;
    GetWinodwRect(&rectWindows);
    CRuntimeClass *pViewClass=RUNTIME_CLASS(CXXXView);
    CCreateContext *pContext=new CCreateContext;
    pContext->m_pCurrentDoc=NULL;
    pContext->m_pCurrentFrame=NULL;
    pContext->m_pLastView=NULL;
    pContext->m_pNewDocTemplate=NULL;
    pContext->m_pNewViewClass=pViewClass;

    CWnd *pWnd=DYNAMIC_DOWNCAST(CWnd,pviewClass->CreateObject());
    pWnd->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0),this,pContext);
    delete pContext;
    CXXXView *pView=DYUNAMIC_DOWNCAST(CXXXView,pWnd);
    ...............
    }

    62. 窗口最大化、最小化及关闭的消息是什么?如何截获?

    最大化、最小化将发送WM_SYSCOMMAND消息。要处理该消息,可以这么做: 
      1、在Form的头文件中添加: 
       void __fastcall RestrictMinimizeMaximize(TMessage &Msg); 
       
       BEGIN_MESSAGE_MAP 
       MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, RestrictMinimizeMaximize) 
       END_MESSAGE_MAP(TForm) 
      2、在Form的单元文件中添加: 
       
       void __fastcall TForm1::RestrictMinimizeMaximize(TMessage& Msg) 
       { 
       if (Msg.WParam == SC_MINIMIZE) 
       { 
       //catches minimize... 
       } 
       else if (Msg.WParam == SC_MAXIMIZE) 
       { 
       //catches maximize... 
       } 
       TForm::Dispatch(&Msg); 
       // or "else TForm::Dispatch(&Msg)" to trap 
       } 
      关闭窗口的消息为WM_CLOSE,C++Builder提供了OnClose事件。

    63. 如何遍历整个目录树查找文件
      
    在应用程序的开发过程中,会遇到如何查找某一文件以确定此文件路径的问题。利用CFileFind类可以比较方便地在当前目录下进行文件查找,但却不能对其子目录中的文件进行搜寻。而实际应用中往往需要对某一整个目录树,甚至是整个C盘或D盘驱动器进行文件搜寻。通过实践,我们在Visual C++ 6.0中编程实现了如何遍历任意目录树,以查找某一特定的文件。
      在下面的具体陈述中可以看到,在确定要查找的文件名和要进行搜索的目录的名称后,将调用函数Search_Directory进行文件的查找。首先依次查找当前目录下的每一个实体(文件或是子目录),如果是某一子目录,则进入该子目录并递归调用函数Search_Dirctory进行查找,查找完毕之后, 再返回上一级目录;如果不是子目录而是某一文件,则判断其是否就是我们要查找的文件,如果是则输出其完整的文件路径。这样,通过Search_Directory函数的反复递归调用,就可以实现对整个目录,包括子目录的遍历搜索。下面将举例详细讲述如何在VC++中编程实现在整个目录树中的文件查找。
      1. 在Visual C++ 6.0(VC++ 5.0与之类似)中用默认方式创建了一基于对话框的应用程序Search。在主窗口对话框上放置一命令按钮,其Caption为“Search File”,ID为ID_BUTTON_SEARCH。单击此按钮将完成文件的查找工作。
      2. 利用ClassWizard为“Search File”按钮的BN_CLICKED 事件添加处理函数OnButtonSearch,代码如下:

    #include 〈direct.h〉
    #include 〈io.h〉 
    void CSearchDlg::OnButtonSearch() 

      // TODO: Add your control notification handler code here 
      
      char szFilename[80]; 
      // 字符串 szFilename 表示要查找的文件名 

      strcpy(szFilename,"Mytext.txt"); 

      _chdir("d://"); // 进入要查找的路径(也可为某一具体的目录) 
      // 查找文件, 如果查到则显示文件的路径全名 
      Search_Directory(szFilename); 
      // 为CSearchDlg类的一成员函数 
      MessageBox(″查找文件完毕!″); 
      // 显示查找完毕的信息 



      3. 在CSearchDlg类中增加成员函数Search_Directory,它将完成具体的文件查找工作,代码如下:
    void CSearchDlg::Search_Directory(char* szFilename)

      long handle; 
      struct _finddata_t filestruct;
      //表示文件(或目录)的信息
      char path_search[_MAX_PATH]; 
      //表示查找到的路径结果 
      // 开始查找工作, 找到当前目录下的第一个实体(文件或子目录), 
      // "*"表示查找任何的文件或子目录, filestruct为查找结果 
      handle = _findfirst("*", &filestruct); 
      // 如果handle为-1, 表示当前目录为空, 则结束查找而返回 
      if((handle == -1)) return; 
      // 检查找到的第一个实体是否是一个目录(filestruct.name为其名称) 
      if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY ) 
      { 
       // 如果是目录, 则进入该目录并递归调用函数Search_Dirctory进行查找, 
       // 注意: 如果目录名的首字符为'.'(即为"."或".."), 则不用进行查找 
       if( filestruct.name[0] != '.' ) 
       { 
         _chdir(filestruct.name); 
         Search_Directory(szFilename); 
         // 查找完毕之后, 返回上一级目录 
         _chdir(".."); 
       } 
      } 
      else // 如果第一个实体不是目录, 则检查是否是要查找的文件 
      { 
       // stricmp对两字符串进行小写形式的对比, 返回为0表示完全一致 
       if( !stricmp(filestruct.name, szFilename) ) 
       { 
         // 先获得当前工作目录的全路径 
         _getcwd(path_search,_MAX_PATH); 
         // 再获得文件的完整的路径名(包含文件的名称) 
         strcat(path_search,"//"); 
         strcat(path_search,filestruct.name); 
         MessageBox(path_search); //输出显示 
       } 
      } 
      // 继续对当前目录中的下一个子目录或文件进行与上面同样的查找 
      while(!(_findnext(handle,&filestruct))) 
      { 
       if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY ) 
       { 
         if(*filestruct.name != '.') 
         { 
          _chdir(filestruct.name); 
          Search_Directory(szFilename); 
          _chdir(".."); 
         } 
       } 
       else 
       { 
         if(!stricmp(filestruct.name,szFilename)) 
         { 
          _getcwd(path_search,_MAX_PATH); 
          strcat(path_search,"//"); 
          strcat(path_search,filestruct.name); 
          MessageBox(path_search); 
         } 
       } 
      } 
      _findclose(handle); 
      // 最后结束整个查找工作 

      这样我们就可以对整个目录进行遍历搜索,查找某一特定的文件,并输出显示其完整的文件路径。以上的程序在Visual C++ 6.0中已调试通过。

    64. Richedit control的设置背景图片办法

    1:继承CRichEditCtrl::OnEraseBkgnd(CDC* pDC)消息事件中,给Richedit控件绘制上背景图片:m_bmpBackground.DrawDIB(pDC, 0, 0, rc.Width(), rc.Height());当然也可以通过subclass richedit window之后,在回调函数中处理WM_ERASEBKGND消息。
    2:设置了Richedit控件的透明属性;
    3:依照kenwhale所说的,Hook了GDI32.DLL中的ExtTextOut函数,将RichEdit的text-output options去除ETO_OPAQUE style
    。综上所述,即可实现RichEdit控件的背景图片效果。
    据此,我还实现了RichEdit控件背景绘制AVI动画效果。

    65. MFC程序中如何创建多级目录

    BOOL mkdirEx(const char* lpPath)
    {
    CString pathname = lpPath;
    if(pathname.Right(1) != "/")
    pathname += "/" ;
    int end = pathname.ReverseFind('/');
    int pt = pathname.Find('/');
    if (pathname[pt-1] == ':')
    pt = pathname.Find('/', pt+1);
    CString path;
    while(pt != -1 && pt<=end)
    {
    path = pathname.Left(pt+1);
    if(_access(path, 0) == -1)
    _mkdir(path);
    pt = pathname.Find('/', pt+1);
    }
    return true;
    }

    66. 解决外部符号错误:_main,_WinMain@16,__beginthreadex 

    在创建MFC项目时, 不使用MFC AppWizard向导, 如果没有设置好项目参数, 就会在编译时产生很多连接错误, 如error LNK2001错误, 典型的错误提示有:
    libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
    LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
    msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
    nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
    nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
    下面介绍解决的方法:
    1). Windows子系统设置错误, 提示:
    libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
    Windows项目要使用Windows子系统, 而不是Console, 可以这样设置:
    [Project] --> [Settings] --> 选择"Link"属性页,
    在Project Options中将/subsystem:console改成/subsystem:windows 
    2). Console子系统设置错误, 提示:
    LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
    控制台项目要使用Console子系统, 而不是Windows, 设置:
    [Project] --> [Settings] --> 选择"Link"属性页,
    在Project Options中将/subsystem:windows改成/subsystem:console
    3). 程序入口设置错误, 提示:
    msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
    通常, MFC项目的程序入口函数是WinMain, 如果编译项目的Unicode版本, 程序入口必须改为wWinMainCRTStartup, 所以需要重新设置程序入口:
    [Project] --> [Settings] --> 选择"C/C++"属性页,
    在Category中选择Output,
    再在Entry-point symbol中填入wWinMainCRTStartup, 即可
    4). 线程运行时库设置错误, 提示:
    nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
    nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
    这是因为MFC要使用多线程时库, 需要更改设置:
    [Project] --> [Settings] --> 选择"C/C++"属性页,
    在Category中选择Code Generation,
    再在Use run-time library中选择Debug Multithreaded或者multithreaded
    其中,
    Single-Threaded单线程静态链接库(release版本)
    Multithreaded多线程静态链接库(release版本)
    multithreaded DLL多线程动态链接库(release版本)
    Debug Single-Threaded单线程静态链接库(debug版本)
    Debug Multithreaded多线程静态链接库(debug版本)
    Debug Multithreaded DLL多线程动态链接库(debug版本)
    单线程: 不需要多线程调用时, 多用在DOS环境下
    多线程: 可以并发运行
    静态库: 直接将库与程序Link, 可以脱离MFC库运行
    动态库: 需要相应的DLL动态库, 程序才能运行
    release版本: 正式发布时使用
    debug版本: 调试阶段使用 
    67. 创建包含多个子目录的目录
    void CreateAllDirectories(CString strDir)
    {
    //remove ending / if exists
    if(strDir.Right(1)=="//")
     strDir=strDir.Left(strDir.GetLength()-1); 

    // base case . . .if directory exists
    if(GetFileAttributes(strDir)!=-1) 
     return;

    // recursive call, one less directory
    int nFound = strDir.ReverseFind('//');
    CreateAllDirectories(strDir.Left(nFound)); 

    // actual work
    CreateDirectory(strDir,NULL); 
    }
    68. ReverseFind()
    #include <STDIO.H>
    #include <AFX.H>
    int main()
    {
      CString s;
      s.Format("abcdefghijk");
      int nPos = s.ReverseFind('a');
      printf("nPos is %d/n",nPos);
      return 0;
    }
    其中,'a'对应的nPos是0,'h'对应的nPos是7,以此类推。但是:s.ReverseFind('a')和s.Find('a')的结果是一样的。
    问题是:ReverseFind() 和 Find() 有什么区别呢:
    对于ReverseFind(),查找顺序是从后往前,找到后的nPos是按前后顺序排列的。
    而Find()是从前往后查的,找到后的nPos也是按前后顺序排列的。
    69. MDI中如何只屏蔽掉子框架的右上角的关闭按钮
    int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
      if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
    。。。
      CMenu* pSysMenu = GetSystemMenu(FALSE);
      pSysMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND |MF_DISABLED|MF_GRAYED);
      return 0;
    }
    70. 程序如何删除自己
    /
     
    int WINAPI WinMain(HINSTANCE h, HINSTANCE b, LPSTR psz, int n) {
      
    // Is this the Original EXE or the clone EXE?
    // If the command-line 1 argument, this is the Original EXE
    // If the command-line >1 argument, this is the clone EXE
     
    if (__argc == 1) {
     
    // Original EXE: Spawn clone EXE to delete this EXE
    // Copy this EXEcutable image into the user''s temp directory
     
    TCHAR szPathOrig[_MAX_PATH], szPathClone[_MAX_PATH];
    GetModuleFileName(NULL, szPathOrig, _MAX_PATH);
    GetTempPath(_MAX_PATH, szPathClone);
    GetTempFileName(szPathClone, __TEXT("Del"), 0, szPathClone);
    CopyFile(szPathOrig, szPathClone, FALSE);
     
    //***注意了***:
    // Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE
    HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL, OPEN_EXISTI
    NG, FILE_FLAG_DELETE_ON_CLOSE, NULL);
     
    // Spawn the clone EXE passing it our EXE''s process handle
    // and the full path name to the Original EXE file.
    TCHAR szCmdLine[512];
    HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId());

    wsprintf(szCmdLine, __TEXT("%s %d /"%s/""), szPathClone, hProcessOrig, szPat
    hOrig);
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi;
    CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
    CloseHandle(hProcessOrig);
    CloseHandle(hfile);
     
    // This original process can now terminate.
    } else {
    // Clone EXE: When original EXE terminates, delete it
    HANDLE hProcessOrig = (HANDLE) _ttoi(__targv[1]);
    WaitForSingleObject(hProcessOrig, INFINITE);
    CloseHandle(hProcessOrig);
    DeleteFile(__targv[2]);
    // Insert code here to remove the subdirectory too (if desired).
     
    // The system will delete the clone EXE automatically
    // because it was opened with FILE_FLAG_DELETE_ON_CLOSE
    }
    return(0);
    }
      这一段程序思路很简单:不是不能在运行时直接删除本身吗?好,那么程序先复制(CLONE)一个自己,用复制品起动另一个进程,然后自己结束运行,则原来的EXE文件不被系统保护.这时由新进程作为杀手删除原来的EXE文件,并且继续完成程序其他的功能。

      新进程在运行结束后,复制品被自动删除。这又是值得介绍的一个把戏了,注意: 

    // Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE
    HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL,OPEN_EXISTIN
    G, FILE_FLAG_DELETE_ON_CLOSE, NULL);
      这里面的FILE_FLAG_DELETE_ON_CLOSE标志,这个标志是告诉操作系统,当和这个文件相关的所有句柄都被关闭之后(包括上面这个CREATEFILE创建的句炳),就把这个文件删除。几乎所有的临时文件在创建时,都指明了这个标志。另外要注意的是:在复制品进程对原始程序操刀之前,应该等待原进程退出.在这里用的是进程同步技术.用HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE,GetCurrentProcessId());得到原进程句柄.SYNCHRONICE标志在NT下有效,作用是使OpenProcess得到的句柄可以做为同步对象.复制品进程用WaitForSingleObject函数进行同步,然后一个DeleteFile,以及进行其它销毁证据(比如删目录)的工作,一切就完事了。
     
      程序是基于CONSOLE的,通过传入的参数确定是原始的进程还是复制品新进程,并且得到需要操作的目标文件的信息(主要是路径),复制品放在系统的TEMP目录(GetTempPath得到),你也可以随便找个你认为安全的地方(比如:WINDOWS/SYSTEM32等等)。这里面没有甚么深的技术.再看其他的一些实现删除自己的例子,比如说在进程退出前,用fwrite等方法输出一个.BAT文件,在里面写几句DEL,然后WINEXEC一下这个BAT文件即可.玩儿过DOS的虫虫大多都会。

    71. 隐藏标题栏和菜单栏
    隐藏标题栏 ModifyStyle(WS_CAPTION,0)
    隐藏菜单栏 SetMenu(NULL)
    72. InflateRect
    InflateRect这个函数用于增大或减小一个矩形的大小.
    如m_graphRect.InflateRect(-70, -30, -30, -50);
    将矩形左边坐标加70,上面加30,右边减30,下面减50。
    73. 怎么让无模式对话框显示在主窗口后面
    要解决这个问题的关键在于CDialog的Create并不能建立一个无属主的窗口.必须用另外方式建窗口.  
      
     比如你的对话框类叫CDlgNoOwner,在CMainFrame中加一个CDlgNoOwner类的成员变量,  
     弹出这个对话框的消息处理函数为  
      
     void  CMainFrame::OnNoowner()   
     {  
    CDlgNoOwner  *m_dlgTest=new  CDlgNoOwner(this); 
     HWND  hwndDlg=::CreateDialog(AfxGetInstanceHandle(),MAKEINTRESOURCE(CDlgNoOwner::IDD),NULL/*owner*/,NULL/*dlgproc*/);  
     //注意此处DLGPROC为NULL,并不要紧,因为接下要subclass啦  
     m_dlgTest->SubclassWindow  (hwndDlg);//挂接到成员变量!  
     m_dlgTest->ShowWindow  (SW_SHOW);  
     //这时可以看到一个"自由"的对话框弹出,和你的主窗口是平起平坐的.  
     }  
      
     当然不要忘了在对话框关闭时DestroyWindow()..那都是在对话框类中的标准处理了.
    74. 隐藏窗口(子窗口没有焦点时)

    在程序启动时  InitDialog  中使用  SetWindowPos  将窗体设置到屏幕以外
    然后再隐藏
    1.在OnInitDialog()函数里设置定时器:(WINDOWS  API里面响应消息WM_INITDIALOG)  
      
     SetTimer(1,  1,  NULL);  
      
     2.添加处理WM_TIMER的消息处理函数OnTimer,添加代码:  
      
     if(nIDEvent  ==  1)  
      
     {  
      
     DeleteTimer(1);  
      
     ShowWindow(SW_HIDE);  
      
     }  
    75.修改视图背景
    How do I change the background color of a view?

    To change the background color for a CView, CFrameWnd, or CWnd object, process the WM_ERASEBKGND message. The following code shows how: 

    BOOL CSampleView::OnEraseBkgnd(CDC* pDC)
    {
      // Set brush to desired background color.
      CBrush backBrush(RGB(255, 128, 128));
      // Save old brush.
      CBrush* pOldBrush = pDC->SelectObject(&backBrush);
      CRect rect;
      pDC->GetClipBox(&rect);   // Erase the area needed.
      pDC->PatBlt(rect.left, rect.top, rect.Width(), 
      rect.Height(), PATCOPY);
      pDC->SelectObject(pOldBrush);
      return TRUE;
    }

    I solved the problem like this:

    HBRUSH dlgtest::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
      switch (nCtlColor)
      {
        case CTLCOLOR_BTN:
        case CTLCOLOR_STATIC:
        {
          pDC->SetBkMode(TRANSPARENT);
        }
        case CTLCOLOR_DLG:
        {
          CBrush*   back_brush;
          COLORREF  color;
          color = (COLORREF) GetSysColor(COLOR_BTNFACE);
          back_brush = new CBrush(color);
          return (HBRUSH) (back_brush->m_hObject);
        }
      }
      return(CFormView::OnCtlColor(pDC, pWnd, nCtlColor));
    }
    76. 如何实现点击对话框外的地方使对话框到主窗口的后面
    只能将桌面做为父窗口
    pMDlg = new CMDlg;
    pMDlg->Create(IDD_M_DIALOG,CWnd::GetDesktopWindow()/* 设置父窗口 */);
    pMDlg->ShowWindow(SW_SHOW); 
    然后在任务栏里隐藏对话框程序
    如何让对话框应用程序在在任务栏上不出现,并且不隐藏窗口。
    [解决方法]
      把对话框的扩展属性修改成为WS_EX_TOOLWINDOW。
    [程序实现]
      把对话框的属性设置成为toolwindow,然后在需要的地方执行本代码。
      DWORD Style = ::GetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE);
      Style = WS_EX_TOOLWINDOW ;
      AfxGetMainWnd()->ShowWindow(FALSE);
      ::SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,Style); 
      AfxGetMainWnd()->ShowWindow(TRUE);
    77. 想在程序一启动时就自动关闭窗口,不在任务栏里显示
    用CTRL+W打开ClassWizard;
    点击Class Info页,类名是工程名Dlg,
    再在左下方的"Filter"中选择"Windows";
    回到Message Maps页,就可以看到消息中有WM_WINDOWPOSCHANGING,
    加入代码,如上所示.
    这样运行*.EXE,不但看不到主界面,任务栏也没有,就是任务管理器中的"应用程序"中也不列出,那该如何关闭它?
    在任务管理器的"进程"中可以找到它,这是黑客程序常用的方法.
    如果需要的话,连"进程"中也看不到.这样要终止它就是问题了.
    78.修改打印预览的ToolBar

    为AFX_IDD_PREVIEW_TOOLBAR这个ID创建一个DialogBar。则系统就会用新创建的DialogBar代替系统默认的那个

    79. 如何实现SDI与MDI的转换?

    我想将一个编好的SDI应用程序转换为MDI,很明显要有多处的改变。
    你可以这样做:建立一个继承于CMDIChidWnd的类,不防设为CChldFrm.在CWinApp中作如下变化。

    InitInstance()
    {
    . ...
      //instead of adding CSingleDocTemplate
      // Add CMultiDocTemplate.
      pDocTemplate = new CMultiDocTemplate(
          IDR_MAINFRAME,
          RUNTIME_CLASS(CSDIDoc),
          RUNTIME_CLASS(CChldFrm),
    // For Main MDI Frame change this frame window from
    // CFrameWnd derivative ( i.e. CMainFrame )
    // to your CMDIChildWnd derived CChldFrm.
          RUNTIME_CLASS(CSDIView));
    /// After this it is required to create the main frame window
    // which will contain all the child windows. Now this window is
    // what was initially frame window for SDI.
      CMainFrame* pMainFrame = new CMainFrame;
      if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
          return FALSE;
       m_pMainWnd = pMainFrame;
    .....
    }
    在从CMDIFrameWnd中继承的类CMainFrame代替CFramWnd后,所有的类都将从CMDIFrame继承,而不是CFrameWnd,编译运行后你就会发现程序已经从SDI变换到MDI。
    注意:在CMainFram中必须将构造函数从private改为public.否则会出错。

    80. CDC中的竖排文本?

    在OnDraw成员函数中我想让文本竖直对齐,但CDC类似乎不支持该处理
    方法一:如果你的竖直对齐是指旋转文本的话,下面的代码会对你有帮助:该代码检查一个Check box控制,查看文本是否需要旋转.
    // m_pcfYTitle is a CFont* to the selected font.
    // m_bTotateYTitle is a bool (==TRUE if rotated)
    void CPage1::OnRotateytitle()
    {
    LOGFONT lgf;
    m_pcfYTitle->GetLogFont(&lgf);
    m_bRotateYTitle=
        ((CButton*)GetDlgItem(IDC_ROTATEYTITLE))->GetCheck()>0;
    // escapement is reckoned clockwise in 1/10ths of a degree:
    lgf.lfEscapement=-(m_bRotateYTitle*900);
    m_pcfYTitle->DeleteObject();
    m_pcfYTitle->CreateFontIndirect(&lgf);
    DrawSampleChart();
    }
    注意如果你从CFontDialog中选择了不同的字体,你应该自己设定LOGFONT的lfEscapement成员.将初始化后的lfEscapement值传到CFontDialog中.
    方法二:还有一段代码可参考:
    LOGFONT LocalLogFont;
    strcpy(LocalLogFont.lfFaceName, TypeFace);
    LocalLogFont.lfWeight = fWeight;
    LocalLogFont.lfEscapement = Orient;
    LocalLogFont.lfOrientation = Orient;
    if (MyFont.CreateFontIndirect(&LocalLogFont))
      {
      cMyOldFont = cdc->SelectObject(&MyFont);
      }

    81. 如何用键盘滚动分割的视口?

    我的问题是当我用鼠标滚动分割窗口时,视口滚动都很正常,但用键盘时,却什么也没有发生.
    在你的视图继承类中加入如下两个函数,假定该类为CScrollerView:
    void CScrollerView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
    {
        BOOL processed;
        for (unsigned int i=0;i< nRepCnt&&processed;i++)
            processed=KeyScroll(nChar);
        if (!processed)
          CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
    }
    BOOL CScrollerView::KeyScroll(UINT nChar)
    {
        switch (nChar)
            {
            case VK_UP:
                OnVScroll(SB_LINEUP,0,NULL);
                break;
            case VK_DOWN:
                OnVScroll(SB_LINEDOWN,0,NULL);
                break;
            case VK_LEFT:
                OnHScroll(SB_LINELEFT,0,NULL);
                break;
            case VK_RIGHT:
                OnHScroll(SB_LINERIGHT,0,NULL);
                break;
            case VK_HOME:
                OnHScroll(SB_LEFT,0,NULL);
                break;
            case VK_END:
                OnHScroll(SB_RIGHT,0,NULL);
                break;
            case VK_PRIOR:
                OnVScroll(SB_PAGEUP,0,NULL);
                break;
            case VK_NEXT:
                OnVScroll(SB_PAGEDOWN,0,NULL);
                break;
            default:
                return FALSE; // not for us
                   // and let the default class
                   // process it.
            }
      return TRUE;
    }

    82. 如何改变默认的光标形状?

    我试着将光标改变为其它的形状和颜色,但却没有变化.
    在对话框/窗口/你需要的地方加上对WM_SETCURSOR消息的处理.
    BOOL MyDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
    {
      // TOD Add your message handler code here and/or call default
      ::SetCursor(AfxGetApp()->LoadCursor(IDC_MYCURSOR));
      return TRUE;
      //return CDialog::OnSetCursor(pWnd, nHitTest, message);
    }
    你没有成功的原因是因为窗口类光标风格不能为NULL.

    83. 如何选择CTreeCtrl中的节点文本进行编辑?

    在向CTreeCtrl中加入一项后,有什么方法可以编辑该节点的文本呢?
    首先设置你的CcompTreeCtrl具有TVS_EDITLABELS属性.在设计时用控件属性来设置在运行时用GetStyle()/SetStyle()成员函数来设置.然后请看下述代码:
    HTREEITEM CCompTreeCtrl::AddSet()
    {
    static int setCnt =3D 1;
    HTREEITEM hItem;
    CString csSet;
    //create text for new note: New Set 1, New Set 2 ...
    csSet.Format( _T( "New Set %d" ), setCnt++ );
    hItem =3D InsertItem( csSet, IMG_CLOSEDFOLDER, IMG_CLOSEDFOLDER );
    if( hItem !=3D NULL )
          EditLabel( hItem );
    return hItem;
    }

    84. CListCtrl中选择变化时如何获得通知?

    我在Report View中使用了一个CListCtrl(自绘制类型),我想知道什么时候选择项发生了改变.
    在选择项变化时,可以使用按钮有效或失效,按如下操作:
     加入LVN_ITEMCHANGED消息处理.
    void CYourClassNameHere::OnItemchangedEventList(NMHDR* pNMHDR, LRESULT* pResult)
    {
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    *pResult = 0;
    if (pNMListView->uChanged == LVIF_STATE)
    {
     if (pNMListView->uNewState)
      GetDlgItem(IDC_DELETE)->EnableWindow(TRUE);
     else
      GetDlgItem(IDC_DELETE)->EnableWindow(FALSE);
    }
    }

    85. List控件中整栏选择?

    我在处理List控件时碰到了麻烦,我想创建一个ListView,来依据Tree控件的选择同时在ListView和ReportView中显示列表的信息.以下是相关的代码:
    // Set full line select
    ListView_SetExtendedListViewStyle(m_plstCustomers->GetSafeHwnd(),
    LVS_EX_FULLROWSELECT);
    按如下方法处理:
    // -------------------- begin of snippet --------------------------------
    bool CCommCtrlUtil32::ListCtrl_ModifyExtendedStyle(CListCtrl& p_rListCtrl,
                      const DWORD p_dwStyleEx,
                      const bool p_bAdd)
    {
      HWND t_hWnd = p_rListCtrl.GetSafeHwnd();
      DWORD t_dwStyleEx = ListView_GetExtendedListViewStyle(t_hWnd);
      if(p_bAdd)
      {
        if(0 == (p_dwStyleEx & t_dwStyleEx))
        {
          // add style
          t_dwStyleEx |= p_dwStyleEx;
        }
      }
      else
      {
        if(0 != (p_dwStyleEx & t_dwStyleEx))
        {
          // remove style
          t_dwStyleEx &= ~p_dwStyleEx;
        }
      }
      ListView_SetExtendedListViewStyle(t_hWnd, t_dwStyleEx);
      return true;
    }

    86. 如何限制mdi子框架最大化时的大小?

    用ptMaxTrackSize代替prMaxSize,如下所示:
    void CChildFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
    {
      // TOD Add your message handler code here and/or call default
      CChildFrame::OnGetMinMaxInfo(lpMMI);
      lpMMI->ptMaxTrackSize.x = 300;
      lpMMI->ptMaxTrackSize.y = 400;
    }

    87. 怎样实现3D效果?

    在对话框中怎样实现Edit和Listboxes控件的3D效果?(环境95/NT VC5.0)
    1). 使用带WS_EX_CLIENTEDGE标志的::CreateWindowEx来替换::CreateWindow 或者用CWnd::CreateEx替换CWnd::Create.
    2).在建立控件之后,调用ModifyStyleEx(0, WS_EX_CLIENTEDGE).

    88. How do I update the text of a pane in a status bar?

    By default, a CStatusBar pane is not enabled when the pane is created. To activate a pane, you must call the ON_UPDATE_COMMAND_UI() macro for each pane on the status bar and update the panes. Because panes do not send WM_COMMAND messages, you cannot use ClassWizard to activate panes; you must type the code manually. For example, suppose one pane has ID_INDICATOR_PAGE as its identifier and that it contains the current page number in a document. To make the ID_INDICATOR_PAGE pane display text, add the following to a header file (probably the MAINFRM.H file):

    afx_msg void OnUpdatePage(CCmdUI *pCmdUI);

    Add the following to the application message map:

    ON_UPDATE_COMMAND_UI(ID_INDICATOR_PAGE, OnUpdatePage)

    Add the following to a source code file (probably MAINFRM.CPP):

    void CMainFrame::OnUpdatePage(CCmdUI *pCmdUI)
    {
      pCmdUI->Enable();
    }

    To display text in the panes, either call SetPaneText() or call CCmdUI::SetText() in the OnUpdate() function. For example, you might want to set up an integer variable m_nPage that contains the current page number. Then, the OnUpdatePage() function might read as follows:

    void CMainFrame::OnUpdatePage(CCmdUI *pCmdUI)
    {
      pCmdUI->Enable();
      char szPage[16];
      wsprintf((LPSTR)szPage, "Page %d", m_nPage);
      pCmdUI->SetText((LPSTR)szPage);
    }

    This technique causes the page number to appear in the pane during idle processing in the same manner that the application updates other indicators.

    89. 动态修改对话框的大小

     [问题提出]
      关于如何动态改变对话框的大小,我做了个Demo,大家看看.

     [程序实现]
       //本函数使用方法: 
       //第一个参数:如果是TRUE表示显示扩展的对话框,如果是FALSE,表示缩小对话框。 
       //第二个参数:表示本对话框的HWND, 
       //第三个参数:表示缩小后大小的控件的ID
      void COptionDlg::ExpandBox(BOOL fExpand, HWND hwnd, int nIDDefaultBox)
      {
         CWnd *pWndBox=GetDlgItem(nIDDefaultBox);
         RECT rcDefaultBox,rcChild,rcIntersection,rcWnd;
         pWndBox->GetWindowRect(&rcDefaultBox);
         HWND hwndChild = ::GetTopWindow(hwnd);
         for (; hwndChild != NULL; hwndChild = ::GetNextWindow(hwndChild,GW_HWNDNEXT)) 
         {
             ::GetWindowRect(hwndChild, &rcChild);
             if (!IntersectRect(&rcIntersection, &rcChild, &rcDefaultBox))
                  ::EnableWindow(hwndChild, fExpand);
         }
         ::GetWindowRect(hwnd, &rcWnd);
         if (GetWindowLong(hwnd, GWL_USERDATA) == 0)
         {
             SetWindowLong(hwnd, GWL_USERDATA,
                  MAKELONG(rcWnd.right - rcWnd.left, 
                  rcWnd.bottom - rcWnd.top));
             ::ShowWindow(pWndBox->m_hWnd, SW_HIDE);
         }
         ::SetWindowPos(hwnd, NULL, 0, 0,
             rcDefaultBox.right - rcWnd.left,
             rcDefaultBox.bottom - rcWnd.top,
             SWP_NOZORDER | SWP_NOMOVE);
         if(fExpand)
         {
             DWORD dwDims = GetWindowLong(hwnd, GWL_USERDATA);
             ::SetWindowPos(hwnd, NULL, 0, 0,
                  LOWORD(dwDims), HIWORD(dwDims), SWP_NOZORDER | SWP_NOMOVE);
             ::SendMessage(hwnd, DM_REPOSITION, 0, 0);
         }
      }

    90. 用DoModal()调用模态对话框,总是显示在正中,我重载了它,并添加了MoveWindow(),可是其m_hWnd是一串零,调用失败。请问有何方法可使调用的模态对话框显示于自定义位置?多谢
      我不清楚你把MoveWindow()加在什么地方了,正确的方法是在OnInitDialog中添加MoveWindow,如: 
       MoveWindow(0, 1, 300, 200); 
      需要注意的是前两个参数不能都为0。如果你确实希望把窗口放在(0, 0)处,可以在对话框设计窗口的属性中选中Absolute Align,然后再加入 
       MoveWindow(0, 0, 300, 200); 
      为什么会是这样?你看了MFC的源程序就会明白。原来MFC在调用你的OnInitDialog之后,会调用CDialog::CheckAutoCenter()(

    展开全文
  • VC++之MFC教程

    万次阅读 2018-01-28 21:27:36
    VC++之MFC教程 初步使用MFC (1)File-New新建对话框程序 (2)设置控件类型和属性,LIST属性设置为报告(Report): (3)在对话框文件First32Dlg.cpp中修改初始化程序: BOOL CFirst32Dlg::...
  • VC6.0(完整绿色版)

    2020-07-09 23:30:05
    vc6.0_cn_full(完整绿色版)(支持XP、Win7、Win8、Win10)
  • VC++6.0安装下载

    万次阅读 2018-09-09 17:44:36
    https://pan.baidu.com/s/1msw9MVSMqahiIKU-f2gz8g
  • 关于python需要vc++14.0 的解决

    万次阅读 2018-04-10 00:48:11
    简单来说,就是逃避,逃避可耻但有用。直接https://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载需要的对应的whl文件(注意...gt; pip install +’whl路径‘就欧ok暂时解决的一些问题 据说驱动 精灵上有这个运行库...
  • 孙鑫《VC++深入详解》完整版PDF 下载

    千次阅读 2016-09-09 17:10:41
    非常不错的书,结合孙鑫视频看,效果很好。下载地址: ...(链接更新时间:2015-08-28 00:59:03 一两年...当当购买链接:VC++深入详解附: 孙鑫MFC视频教程:http://v.dxsbb.com/jisuanji/555/ 如果链接无效,直接百度
  • python 安装twisted库时提示缺少VC++ 14.0 (解决方案)

    万次阅读 多人点赞 2018-03-04 12:49:04
    说明:出现这种问题,不需要去安装VC++14.0 ,只需要去python库上下载相应的包安装即可。1.在python库中下载twisted相应的包(.whl文件)网址:https://www.lfd.uci.edu/%7Egohlke/pythonlibs/2.从cmd中进入相应...
  • python 安装库时提示缺少VC++ 14.0

    万次阅读 2018-07-16 14:26:36
    安装Twisted库,还要安装future库Unofficial Windows Binaries for Python Extension Packageshttps://www.lfd.uci.edu/~gohlke/pythonlibs/.whl文件安装pip install ***.whl官方的库https://pypi.org/安装:...
  • VS 2010 配置VC++ 目录

    万次阅读 2011-11-17 11:38:37
    VS 2010在“工具->选项->项目和解决方案->VC++ 目录”不再提供设置,如下图:  但是每个工程都要在“项目->属性->配置属性->VC++ 目录”中一一设置如OpenCV之类的公共库文件目录是件很麻烦的事,一番搜索才知道...
  • 如图所示, c/c++, 附加库目录,代表的是c/c++文件编译时所需要的头文件,而资源编译时也是需要附加包含库目录的, 而vc++的包含目录,代表的是全局项目的包含目录
  • VC++2010注册密钥

    万次阅读 多人点赞 2019-04-25 20:36:43
    6VPJ7-H3CXH-HBTPT-X4T74-3YVY7
  • VC++6.0中创建新工程

    千次阅读 2017-01-02 03:57:58
    VC++6.0中创建新工程
  • 使用VC++6.0创建MFC对话框程序

    千次阅读 2018-10-08 21:12:05
    使用VC++6.0创建MFC对话框程序  
  • vc++2010下第一个窗体应用程序

    万次阅读 2011-07-10 22:05:05
    调试了好久,问了n多人,百度了n多网页,最后还是从在线msdn上找到了参考。 具体实现为: 1.首先创建项目,选择【文件】->【新建】->【项目】,如图1所示。 ...2.在出现的【新建项目】内选择【Windows窗体应用程序...
1 2 3 4 5 ... 20
收藏数 139,691
精华内容 55,876
关键字:

vc++