您正在查看: VC 分类下的文章

第0章你一定要知道(导读)

第0章 你一定要知道(导读)

这本书适合谁

深入浅出mfc是一本介绍mfc(Microsoft Foundation Classes)程序设计技术的书籍。对于Windows 应用软件的开发感到兴趣,并欲使用Visual C++ 整合环境的视觉开发工具,以MFC为程序基础的人,都可以从此书获得最根本最重要的知识与实例。

如果你是一位对Application Framework和面向对象(Object Oriented)观念感兴趣的技术狂热份子,想知道神秘的Runtime Type Information、Dynamic Creation、Persistence、Message Mapping 以及Command Routing 如何实现,本书能够充分满足你。事实上,依我之见,这些核心技术与彻底学会操控MFC乃同一件事情。

全书分为四篇:

第一篇【勿在浮砂筑高台】提供进入 MFC 核心技术以及应用技术之前的所有技术基础,包括:

win32 程序观念 :message based,event driven,multitasking, multithreading, console programming。

C++ 重要技术:类与对象、this 指针与继承、静态成员、虚函数与多态、模板(template)类、异常处理(exception handling)。

MFC 六大技术之简化仿真(Console 程序)

第二篇【欲善工事先利其器】提供给对Visual C++ 整合环境全然陌生的朋友一个导引。这一篇当然不能取代 Visual C++ User's Guide 的地位,但对整个软件开发环境有全盘以及概观性的介绍,可以让初学者迅速了解手上掌握的工具,以及它们的主要功能。

第三篇【浅出 MFC 程序设计】介绍一个 MFC 程序的生死因果。已经有 MFC 程序经验的朋友,不见得不会对本篇感到惊艳。根据我的了解,太多人使用 MFC 是「只知道这么做,不知道为什么」;本篇详细解释 MFC 程序之来龙去脉,为初入 MFC 领域的读者奠定扎实的基础。说不定本篇会让你有醍醐灌顶之感。

第四篇【深入 MFC 程序设计】介绍各式各样 MFC 技术。「只知其然 不知其所以然」的不良副作用,在程序设计的企图进一步开展之后,愈来愈严重,最终会行不得也!那些最困扰我们的 MFC 宏、MFC 常数定义,不得一窥堂奥的 MFC 黑箱作业,在本篇陆续曝光。本篇将使您高喊:Eureka!

阿基米得在洗澡时发现浮力原理,高兴得来不及穿上裤子,跑到街上大喊:Eureka(我找到了)。

范例程序方面,第三章有数个Console程序(DOS-like 程序,在Windows系统的DOS Box 中执行),模拟并简化Application Framework 六大核心技术。另外,全书以一个循序渐进的Scribble 程序(Visual C++ 所附范例),从第七章开始,分章探讨每一个MFC应用技术主题。第13章另有三个程序,示范 Multi-View 和 Multi-Document 的情况。

14章~16 章是第二版新增内容,主题分别是MFC 多线程程序设计、Custom AppWizard、以及如何使用Component Gallery 提供的ActiveX controls 和components。

你需要什么技术基础

从什么技术层面切入Windows软件开发领域?C/SDK?抑或C++/MFC?这一直是个引起争议的论题。就我个人观点,C++/MFC 程序设计必须跨越四大技术障碍:

1. 面向对象观念与C++ 语言。

2. Windows 程序基本观念(程序进入点、消息流动、窗口函数、callback...)。

3. Microsoft Foundation Classes(MFC)本身。

4. Visual C++ 整合环境与各种开发工具(难度不高,但需熟练)。

换言之,如果你从未接触C++,千万不要阅读本书,那只会打击你学习新技术的信心而已。如果已接触过C++ 但不十分熟悉,你可以一边复习C++ 一边学习MFC,这也是我所鼓励的方式(很多人是为了使用MFC 而去学习C++ 的)。C++ 语言的继承(inheritance)特性对于我们使用MFC尤为重要,因为使用MFC 就是要继承各个类并为己用。所以,你应该对C++ 的继承特质(以及虚函数,当然)多加体会。我在第2章安排了一些C++ 的必要基础。我所挑选的题目都是本书会用到的技术,而其深度你不见得能够在一般 C++ 书籍中发现。

如果你有C++ 语言基础,但从未接触过Win16 或 win32 程序设计,只在 DOS 环境下开发过软件,我在第1章为你安排了一些 Win32 程序设计基础。这个基础至为重要,只会在各个 Wizards上按来按去,却不懂所谓 message loop 与 window procedure 的人,不可能搞定 Windows 程序设计——不管你用的是MFC或OWL或Open Class Library,不管你用的是Visual C++或Borland C++或VisualAge C++。

名词界定:

API—Application Programming Interface 系统开放出来,给程序员使用的接口,就是API。一般人的观念中API是指像 C 函数那样的东西,不尽然!DOS 的中断向量(interrupt vector)也可以说是一种API,OLE Interface(以 C++ 类的形式呈现)也可以说是一种 API。不是有人这么说吗:MFC 势将成为 Windows 环境上标准的 C++ API(我个人认为这句话已成为事实)。

SDK—Software Development Kit 原指软件开发工具。每一套环境都可能有自己的SDK,例如Phar Lap的386|DOS Extender 也有自己的SDK。在Windows这一领域,SDK原是指Microsoft 的软件开发工具,但现在已经变成一个一般性名词。凡以Windows raw API 撰写的程序我们通常也称为SDK程序。也有人把Windows API称为SDK API。Borland 公司的C++ 编译器也支持相同的SDK API(那当然,因为Windows只有一套)。本书如果出现「SDK 程序」这样的名词,指的就是以 Windows raw API 完成的程序。

MFC—Microsoft Foundation Classes 的缩写,这是一个架构在Windows API之上的C++ 类库(C++ Class Library),意图使 Windows 程序设计过程更有效率,更符合面向对象的精神。MFC 在争取成为「Windows 类库标准」的路上声势浩大。Symantec C++以及WATCOM C/C++已向微软取得授权,在它的软件开发平台上供应 MFC。Borland C++也可以吃进MFC程序代码——啊,OWL 的地位益形尴尬了。

OWL—Object Windows Library 的缩写,这也是一个具备Application Framework 架势的 C++ 类库,附含在 Borland C++ 之中。

Application Framework—在面向对象领域中,这是一个专有名词。关于它的意义,本书第5章有不少介绍。基本上它可以说是一个更有凝聚力,关联性更强的类库。并不是每一套C++类库都有资格称为Application Framework,不过MFC和OWL都可入列,IBM 的 Open Class Library 也是。Application Framework 当然不一定得是C++类库,Java和 delphi 应该也都称得上。

为使全书文字流畅精简,我用了一些缩写字:

API - Application Programming Interface

DLL - Dynamic Link Library

GUI - Graphics User Interface

MDI - Multiple Document Interface

MFC - Microsoft Foundation Class

OLE - Object Linking & Embedded

OWL - Object Windows Library

SDK - Software Development Kit

SDI - Single Document Interface

UI - User Interface

WinApp : Windows Application

以下是本书使用之中英文名词对照表:

Control 控制组件,如 Edit、ListBox、Button...。

drag & drop 拖放(鼠标左键按下,选中图示后拖动,然后放开)

Icon 图标(窗口缩小化后的小图样)

linked-list 串列

listbox 列表框、列表清单

notification 通告消息(发生于控制组件)

preemptive 强制性、先占式、优先权式

process 进程(一个执行起来的程序)

queue 队列

template C++ 有所谓的class template,一般译为类模板;Windows 有所谓的dialog template,我把它译为对话框模板;MFC 有所谓的Document Template,我没有译它(其义请见第7章和第8章)

window class 窗口类(不是一种C++ 类)

window focus 窗口焦点(拥有焦点之窗口,将可以获得键盘输入)

class 类

object 对象

constructor 构造函数

destructor 析构函数

operator 运算符

override 改写

overloading 重载 ,亦有他书译为「过荷」

Encapsulation 封装

Inheritance 继承

Dynamic Binding 动态联编 ,亦即后期联编(late binding)

virtual function 虚函数

Polymorphism 多态 ,亦有他书译为「同名异式」

member function 成员函数

data member 成员变量,亦有他书译为「数据成员」

Base Class 基类,亦即父类

Derived Class 派生类,亦即子类

本书符号习惯

斜体字表示函数、常数、变量、语言保留字、宏、识别代码等等,例如:

CreateWindow 这是Win32 函数

Strtok 这是C Runtime函数库的函数

WM_CREATE 这是Windows消息

ID_FILE_OPEN 这是资源识别代码(ID)

CDocument::Serialize 这是MFC类的成员函数

m_pNewViewClass 这是MFC类的成员变量

BEGIN_MESSAGE_MAP 这是MFC宏

Public 这是C++语言保留字

第一篇 勿在浮砂築高台

MFC 编程经验

mfc 编程经验

Visual C++ 资源

mfc 编程经验

大家分享一下如何用MFC做实际项目的经验
希望大家一起分享一下如何用MFC做实际项目的经验,中秋凑个热闹。呵呵。
1、界面风格和控件
2、消息循环、多线程、数据库相关
3、数据结构和算法相关
4、其他

回复人:ejiue

初学MFC的时候,大家最先接触的就是界面吧。
虽然说界面不是特别重要,但确实让人头痛。
弄来弄去,大多是控件搞不定。(在这个版这样的问题好多:))
至于消息循环机制,我觉得我们用到不多。
MFC都帮我们做好了。不过有一些注意事项。
上一次我做多线程的时候死锁了,阿行大哥就是用消息机制帮我解决的。
另外,rtdb大哥还赠了我1000分,使我能够继续提问。(太感谢了)
这个版好心人不少。感谢之余,我在这里也和大家分享一下。

1、
刚开始的时候,为了把界面做得好看,
我在www.codeproject.com和www.codeguru.com上面找到了一些好用的控件。
如ButtonST、TruecolorToolbar、GradientProgressCtrl、CoolToolbar等
控件。可能大家也用过。它们都很好用,而且有演示程序下载,边学边用,
用对比法和增减法,这两个方法学MFC挺管用的。
后来在www.vkbase.com看到了一个换肤的ActiveX控件,很好用。
做出来的界面特好看。大家去下载看看。
可惜对组合框等控件支持不够。(可能是小弟不会:))

后来做数据库的时候,我公司的高手说选择越简单的控件越好。
我刚开始用DataGrid,直接绑定数据库。
他们建议用原始的Grid控件,独立于具体的数据库。
Grid控件没有(也不需要!)编辑和组合框支持。编辑的时候跳出对话框来解决。

现在我做的一个项目的界面是单文档多个formview切换。(这个界面挺古老的吧)
曾经用过属性页控件,现在用了Tab控件和对话框嵌入,感觉这个挺好的。

遇到控件问题的时候,我常看msdn,上面的实例真好。
现在有问题来msdn,我都是先搜索一下,其实大多数问题都已经有帖子解答。
这样可以节省自己和别人的时间。
记住每个控件都是一个窗口是有帮助的。

2、
多线程的时候尤其要注意一个问题:MFC帮我们开的线程是界面线程。
如果我们以后再开的线程是工作者线程,那么界面主线程不能阻塞。
如果界面主线程阻塞了,相当于消息泵阻塞了。
我上次犯的错误就是让其他工作者线程发一个消息来让主线程解除阻塞。结果死锁。
解决方法是将其他线程改为界面线程。
还有一个问题,创建新线程的时候要小心,它有一个CRuntimeClass的参数。
它要CreateObject()创建一个新的线程,然后把线程指针返回。
CSerialPortEx
 g_pPort = new CSerialPortEx;
CRuntimeClass IOClass  = g_pPort->GetRuntimeClass();
g_pPort = (CSerialPortEx
)AfxBeginThread(IOClass);
上面的代码将使g_pPort无法访问CSerialPortEx内部的变量。
通过增加一个临时变量来解决。如下:
CSerialPortEx TempPort = new CSerialPortEx;
CRuntimeClass
 IOClass  = TempPort->GetRuntimeClass();
g_pPort = (CSerialPortEx)AfxBeginThread(IOClass);
delete TempPort;
类似的场合不少。如在用对话框嵌入标签的时候再一次创建了对话框。
出现了实际上存在两个对话框,无法访问原来对话框上的控件。
现在我一看到CRuntimeClass
就会特别小心。
我在解决这些问题的时候用的方法是调试和增减法。并不是从书上得来。
如果有差错,请各位指出来。呵呵。
还有一个问题是进度条对话框上的控件不能及时显示,(消息循环暂时受阻塞)
阿行大哥用在用户代码中加入消息循环解决。也可以开一个线程。

数据库我都没有怎么做过。我的项目不大。
想请教各位设计的时候需要什么考虑,还有上面说的“使用简单的控件”是否合理。
有没有必要自己写一个数据库类,用SQL语句进行访问。

3、
数据结构我学得太烂了,现在非常后悔。不过只得加把劲了。
幸亏我现在只用到链表和数组。呵呵。
我觉得链表和数组都有欠缺。
象我的项目,串口数据在不停的上来,根据上来的数据监控下面机器的状态。
如果用数组,长度是固定的。
如果用链表,有可能用户暂时不在监控界面。(假设长达几个小时)
几个小时之内的数据用链表一直来存储着。
然后等用户一切换回监控,就一下子从头到尾刷新?!
如果什么都不用,直接用后一个状态覆盖前一个,那么就无法显示一系列的过程。
正在考虑用一个固定长度的链表。

4、
还有其他没考虑到的地方,大家提出来讨论吧。

vc做程序最重要的就是小心,小心再小心,每做一步自己都要多运行几遍,分别在debug,release模式下运行运行,
看看有没有内存泄漏,越界等错误,等到最后才发现那就惨了

1。程序运行稳定,尽量用老办法,不了解的函数不要随便用。
2。功能要简单实用。
3。不要追求功能的完美。完美的功能是不可能的。
4。程序一有bug,必须纠正后才能前进

//--------------------------------------------------------------------------
回复人: jnxulei(石头) 

1、调试程序的时候有简单到复杂:碰到程序运行出错时,可以先把一些程序注释掉,只留很少的一部分,确保程序的正确运行,然后再逐段逐段代码的释放,很容易发现问题所在。

2、单独做试验:对程序中用到的一些独立的模块和功能,如果不是太熟悉或则把握不准,可以单独的写一个小的程序去做试验,验证用法以及结果。不要在很大的工程中调试某些独立的模块。

3、仔细认真地作试验。在研究一个新的控件或功能时,要象对待正式程序一样认真的对待,否则如果出现错误,你就有可能得出一个错误的结论,一旦用到整个的程序中就会是一个很难发现的错误,浪费大量的时间去查找其他的代码。

4、有时候错误的程序会莫名其妙的运行正常,但你并没有找到出错的原因。这时千万不要高兴太,应该继续调试和试验,一定要把错误找出来。只要你找不出来,这个错误就是一个炸弹,不一定什么时候发作。

5、进行数据库操作的时候,碰到比较复杂的SQL语句,最好先在数据库中执行测试你的SQL语句,以保证该语句的正确性。

6、建议在操作数据库的时候使用“事务处理”,否则程序在运行时(特别在网络中)会遇到意想不到的问题,如:网络不稳定可能会使你的操作只执行一部分。

7、长期连续运行的程序中,一些复杂的功能不要在定时器(OnTimer)中完成,而尽量使用线程完成,我的感觉是,放在线程中要比定时器稳定的多。(只是我自己的看法)

vc编程经验总结

虚拟按键的总结

虚拟按键的总结

Visual C++ 资源

虚拟按键的总结

http://expert.csdn.net/Expert/topic/2425/2425502.xml
主  题:  虚拟按键的总结: 
作  者:  zhucde (【风间苍月】) 
描述:
符号常量   十六进制值  指定的鼠标或键盘按键
VK_LBUTTON   01  鼠标左键
VK_RBUTTON   02  鼠标右键
VK_CANCEL   03     Control-break 过程
VK_MBUTTON     04      鼠标中键
VK_BACK   08  BACKSPACE 键
VK_TAB    09  TAB 键
VK_CLEAR   0C  CLEAR 键
VK_RETURN   0D  ENTER 键
VK_SHIFT   10  SHIFT 键
VK_CONTROL   11  CTRL 键
VK_MENU   12  ALT 键
VK_PAUSE   13  PAUSE 键
VK_CAPITAL   14  CAPS LOCK 键
VK_ESCAPE   1B  ESC 键
VK_SPACE   20  SPACEBAR
VK_PRIOR   21  PAGE UP 键
VK_NEXT   22  PAGE DOWN 键
VK_END    23  END 键
VK_HOME   24  HOME 键
VK_LEFT   25  LEFT ARROW 键
VK_UP    26  UP ARROW 键
VK_RIGHT   27  RIGHT ARROW 键
VK_DOWN   28    DOWN ARROW 键
VK_SELECT   29  SELECT 键
VK_EXECUTE   2B  EXECUTE 键
VK_SNAPSHOT   2C PRINT SCREEN键(用于Windows 3.0及以后版本)
VK_INSERT   2D  INS 键
VK_DELETE   2E  DEL 键
VK_HELP   2F  HELP键
/////////////////////
对于非小键盘上的数字键和字母键,直接在单引号中加入该键就行.
比如: a 键:'A'
      1 键:'1'
/////////////////////////////////
VK_LWIN   5B  Left Windows 键 (Microsoft自然键盘)
VK_RWIN   5C  Right Windows 键 (Microsoft自然键盘)
VK_APPS   5D  Applications 键 (Microsoft自然键盘)
VK_NUMPAD0   60  数字小键盘上的 

vc编程经验总结

用MFC做实际项目的经验

mfc做实际项目的经验

Visual C++ 资源

mfc做实际项目的经验

http://expert.csdn.net/Expert/topic/2247/2247433.xml
主  题:  【中秋凑个热闹】大家分享一下如何用MFC做实际项目的经验 
作  者: ejiue (车马炮、将士相、卒杀) 
希望大家一起分享一下如何用MFC做实际项目的经验,中秋凑个热闹。呵呵。
1、界面风格和控件
2、消息循环、多线程、数据库相关
3、数据结构和算法相关
4、其他

初学MFC的时候,大家最先接触的就是界面吧。虽然说界面不是特别重要,但确实让人头痛。弄来弄去,大多是控件搞不定。(在这个版这样的问题好多:))至于消息循环机制,我觉得我们用到不多。MFC都帮我们做好了。不过有一些注意事项。上一次我做多线程的时候死锁了,阿行大哥就是用消息机制帮我解决的。
另外,rtdb大哥还赠了我1000分,使我能够继续提问。(太感谢了)这个版好心人不少。感谢之余,我在这里也和大家分享一下。
1、
刚开始的时候,为了把界面做得好看,我在www.codeproject.com和www.codeguru.com上面找到了一些好用的控件。如ButtonST、TruecolorToolbar、GradientProgressCtrl、CoolToolbar等控件。可能大家也用过。它们都很好用,而且有演示程序下载,边学边用,用对比法和增减法,这两个方法学MFC挺管用的。后来在www.vkbase.com看到了一个换肤的ActiveX控件,很好用。做出来的界面特好看。大家去下载看看。可惜对组合框等控件支持不够。(可能是小弟不会:))
后来做数据库的时候,我公司的高手说选择越简单的控件越好。我刚开始用DataGrid,直接绑定数据库。他们建议用原始的Grid控件,独立于具体的数据库。Grid控件没有(也不需要!)编辑和组合框支持。编辑的时候跳出对话框来解决。
现在我做的一个项目的界面是单文档多个formview切换。(这个界面挺古老的吧)曾经用过属性页控件,现在用了Tab控件和对话框嵌入,感觉这个挺好的。
遇到控件问题的时候,我常看msdn,上面的实例真好。现在有问题来msdn,我都是先搜索一下,其实大多数问题都已经有帖子解答。这样可以节省自己和别人的时间。记住每个控件都是一个窗口是有帮助的。
2、
多线程的时候尤其要注意一个问题:MFC帮我们开的线程是界面线程。如果我们以后再开的线程是工作者线程,那么界面主线程不能阻塞。如果界面主线程阻塞了,相当于消息泵阻塞了。我上次犯的错误就是让其他工作者线程发一个消息来让主线程解除阻塞。结果死锁。
解决方法是将其他线程改为界面线程。
还有一个问题,创建新线程的时候要小心,它有一个CRuntimeClass的参数。它要CreateObject()创建一个新的线程,然后把线程指针返回。
CSerialPortEx
 g_pPort = new CSerialPortEx;
CRuntimeClass IOClass  = g_pPort->GetRuntimeClass();
g_pPort = (CSerialPortEx
)AfxBeginThread(IOClass);
上面的代码将使g_pPort无法访问CSerialPortEx内部的变量。通过增加一个临时变量来解决。如下:
CSerialPortEx TempPort = new CSerialPortEx;
CRuntimeClass
 IOClass  = TempPort->GetRuntimeClass();
g_pPort = (CSerialPortEx)AfxBeginThread(IOClass);
delete TempPort;
类似的场合不少。如在用对话框嵌入标签的时候再一次创建了对话框。出现了实际上存在两个对话框,无法访问原来对话框上的控件。现在我一看到CRuntimeClass
就会特别小心。我在解决这些问题的时候用的方法是调试和增减法。并不是从书上得来。如果有差错,请各位指出来。呵呵。
还有一个问题是进度条对话框上的控件不能及时显示,(消息循环暂时受阻塞)阿行大哥用在用户代码中加入消息循环解决。也可以开一个线程。
数据库我都没有怎么做过。我的项目不大。想请教各位设计的时候需要什么考虑,还有上面说的“使用简单的控件”是否合理。有没有必要自己写一个数据库类,用SQL语句进行访问。
3、
数据结构我学得太烂了,现在非常后悔。不过只得加把劲了。幸亏我现在只用到链表和数组。呵呵。我觉得链表和数组都有欠缺。象我的项目,串口数据在不停的上来,根据上来的数据监控下面机器的状态。如果用数组,长度是固定的。如果用链表,有可能用户暂时不在监控界面。(假设长达几个小时)几个小时之内的数据用链表一直来存储着。然后等用户一切换回监控,就一下子从头到尾刷新?!如果什么都不用,直接用后一个状态覆盖前一个,那么就无法显示一系列的过程。正在考虑用一个固定长度的链表。
4、
还有其他没考虑到的地方,大家提出来讨论吧。
真诚的感谢msdn和vc版,感谢各位热心的朋友。各位中秋愉快,呵呵。
回复人: ejiue(车马炮、将士相、卒杀) 
对了,前几步是需求和设计。我是初学者,所以在细节上已经折腾半死了。不过公司很小,对用户需求没有做调查。我的项目的设计方案是公司的高手做的。可扩展性很好。设计模式刚看,看不懂,但是有收获。前一阵子把一些写得乱七八糟的类修改了一下。
这里提一个简单的类的设计问题吧。项目要用到一个协议类,根据协议字典来解析数据。那么查字典来确定数据帧的这个函数应该放在哪里?作为字典类的接口是可以的,并且在需要访问协议的类组合一个协议变量。另外,专门写一个访问类也可以。这是不是类似于迭代器的概念?如果让你们来写,会选择什么方案呢?

楼上的各位,发表一下个人的心得好吗?我是抛转引玉啊。
你们也发表一下,让后面有更多的人分享和发表心得,不就更能学习到东东?
回复人: wuchuncai(1234567)
1。程序运行稳定,尽量用老办法,不了解的函数不要随便用。
2。功能要简单实用。
3。不要追求功能的完美。完美的功能是不可能的。
4。程序一有bug,必须纠正后才能前进
版主点评:
作出一个能用起来顺手的程序是不简单的,要靠你千遍万遍的调试、修改

vc编程经验总结

直接运行一个资源中的程序

直接运行一个资源中的程序

Visual C++ 资源

直接运行一个资源中的程序

bool Run()
   {
       CFile f; 
       char* pFileName = "Execution.exe";
       if( !f.Open( pFileName, CFile::modeCreate | CFile::modeWrite, NULL ) )
       {
              AfxMessageBox("Can not create file!");
              return 0;
       }
        CString path = f.GetFilePath();
       HGLOBAL hRes;
       HRSRC hResInfo;
     //获取应用实例 
       HINSTANCE insApp = AfxGetInstanceHandle();
     //寻找EXE资源名
       hResInfo = FindResource(insApp,(LPCSTR)IDR_EXE4,"EXE");
       hRes = LoadResource(insApp,hResInfo );   // Load it
       DWORD dFileLength = SizeofResource( insApp, hResInfo );  //计算EXE文件大小
       f.WriteHuge((LPSTR)hRes,dFileLength);  //写入临时文件
       f.Close();
       HINSTANCE HINSsd = shellExecute(NULL, "open",path, NULL, NULL, SW_SHOWNORMAL);> //运行它.  
       return 1;
}

vc编程经验总结