本系列文章基于 《Windows程序设计(第5版 珍藏版)》(美国)佩措尔德,译者是方敏、张胜、梁路平,清华大学出版社,存在自行增删部分。
该书从Windows 底层的 API 开始学习,涵盖基础知识和中高级主题,全面地介绍了Windows 程序设计所涉及的细枝末节,旨在帮助读者从高屋建瓴的角度,建立完整的知识体系。
全书共 3 部分 23 章。第1~12章 着重介绍基础知识,第13~18章 的主题为图形,第19~23章 涉及更多高级主题。
第Ⅰ部分 基础知识
第1章 起步
第2章 Unicode简介
第3章 窗口与消息
第4章 文本输出
第5章 绘图基础
第6章 键盘
第7章 鼠标
第8章 计时器
第9章 子窗口控件
第10章 菜单和其他资源
第11章 对话框
第12章 剪贴板
第Ⅱ部分 关于图形的那些事儿
第13章 使用打印机
第14章 位图和Bitblt
第15章 与装置无关的位图
第16章 调色盘管理器
第17章 文字和字体
第18章 METAFILE
第Ⅲ部分 高级主题
第19章 多文档界面
第20章 多任务和多线程
第21章 动态连结程序库
第22章 声音与音乐
第23章 领略 Internet
搭建开发环境
本系列文章使用 C 语言,开发环境:Windows 7 旗舰版,Microsoft Visual C++ 6.0 企业版。
Microsoft Visual C++ 6.0 企业版 下载
解压后,进入文件夹内,点击 AUTORUN.EXE 进行安装。
无毒,建议把360关了,老提醒些有的没的,一般就是下一步下一步,没什么难的。
测试VC 6++
安装好了后,我们进行一个简单的测试,测试VC 6++是否正常运作
点击文件,新建,选择工程中的Win32 Console Application(Win32控制台程序)
选择 一个“Hello World”程序
初始文件结构如下:
进入Test.cpp。编译,出现错误。
C1083: Cannot open precompiled header file: ‘Debug/Test.pch’: No such file or directory 报错
错误原因
预编译头文件还没有编译
解决方法
右键点击项目工程中的该cpp文件,选择setting(设置),在c/c++栏,,选择PreCompiled headers(预编译的头文件),然后设置第一项(选择不使用预编译头选项)。
再次编译,问题解决
VC6++打开,添加文件,会崩溃 的问题
点击打开文件,或者添加文件,会导致崩溃。
错误原因
VC6与新版本windows不兼容
解决方法
(1)下载 FileTool.dll 文件,将下载的FileTool.rar文件解压得到FileToll.dll,然后将FileToll.dll放到VC目录下的 \Common\MSDev98\AddIns 文件夹中,如图:
(2)打开VC6,点击“工具”菜单,选择“定制”,打开定制对话框,如图:
(3)在“定制”对话框中选择“附加项和宏文件”,勾选“File Tool……”项(如果没有该项的话,点击“浏览”,定位到刚才的FileTool.dll文件并打开,就会出现该项),完成后点击关闭,如图:
(4)关闭“定制”对话框后,就会出现下图所示的两个按钮,分别是对应“打开”和“向工程中添加文件”的功能。
现在就可以正常使用了,但是点击原来的“打开”或者Ctrl+O依旧会崩溃(没啥影响)
强迫症患者可以继续去该Blog解决问题->
http://www.cnblogs.com/leftshine/p/5211605.html
第一个 Windows 程序
这里简单介绍一下 Microsoft Visual C++ 6.0。
工程(Project):VC6 以工程为单位对整个程序开发过程涉及到的资源、比如代码文件、图标文件等进行管理,扩展名为 dsw ,一个完整程序的新建、打开或者保存是对工程文件进行的,代码文件只是工程文件中的一部分。
工作区(Workspace):当一个项目比较大,由多个工程组成时,可以将其归属于一个工作区,新建项目时,可以指定该项目是否属于当前所在的工作区,如果不属于而是一个新项目,则 VC6 会自动新建一个工作区包含该项目。工作区扩展名为 .dsw。工作区同一时刻只能有一个活动项目,通过在项目上点击右键可以将其设置为活动项目。
代码文件:用于存储程序的文件,C++ 代码文件的扩展名为 .cpp ,C 语言代码文件的扩展名为 .c ,存储函数或者变量声明的头文件扩展名一般为 .h 。(cpp 文件中可以写 c 语言代码,c 文件中不可以写 c++ 代码。即向下兼容,而不向上兼容)
调试(DEBUG):输入代码、编译、连接、运行并不断修正错误的整个过程。
发布(RELEASE):指程序完成代码的编写和功能调试,最终编译和分发给用户的过程。
-
Console 和 windows :
- Console (windows 控制台程序):指没有图形界面的字符程序,通常用于学习基本语法和无需复杂界面的计算程序
- windows (此处一般指windows 程序):通常使用 MFC微软基础类库,或者 Win32 API 实现图形界面。
基本上我们学习的 C语言编写程序,一般都是控制台程序(黑框框),很少涉及到图形界面的 windows 应用。接下来以简单的 hello world 程序,体会 Console windows控制台程序 和 windows程序 的不同。
p.s :Microsoft Visual C++ 6.0,简称 VC6.0,是微软于1998年推出的一款C++集成开发环境 IDE,同时集成了MFC 6.0。MFC 是以C++类的形式封装的Windows32 API 。
Console windows 控制台程序(字符模式)
最简单的 hello world 程序。
打开 VC6++,点击文件菜单->新建。选择工程选项,Win32 Console Application(控制台程序),填写完相关信息后,点击确定。
选择一个空工程,点击完成。
再点击确定。
至此空工程创建成功,点击 FileView 文件视窗,可以看到工程中的文件结构。选择 Source Files 源文件,点击文件菜单,点击新建,选择文件中的 C++ source File C++源文件。填写相关信息后,点击确定。
现在往 hello world.cpp 中写代码。
#include<stdio.h>
int main()
{
printf("hello,world\n");
return 0;
}
运行截图:
Windows 程序(图形化模式)
对应控制台中的 hello world 程序。
点击文件菜单中,选择新建,选择工程选项卡下的,Win32 Application windows 应用程序,填写完工程名称后,点击确认。
选择一个空工程,点击完成。
点击确定。
至此空工程创建成功,点击 FileView 文件视窗,可以看到工程中的文件结构。选择 Source Files 源文件,点击文件菜单,点击新建,选择文件中的 C++ source File C++源文件。填写相关信息后,点击确定。
现在往 hello world.cpp 中写代码。
#include<windows.h>
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
MessageBox(NULL,TEXT("Hello World"),TEXT("helloMsg"),0);
return 0;
}
运行截图:
从结构上来看,windows 程序和 控制台程序 相差无几,头文件 stdio.h 被换成了 windows.h,程序入口 main 被改成了 WinMain,C 输出库函数 printf 也被 Windows API 函数 MessageBox 所替代。但是这个程序中还出现了些陌生的大写标识符。
现在我们从头剖析这个程序。
头文件
几乎所有用 C 语言编写的 Windows 程序中都有的预处理器指令:
#include<windows.h>
windows.h 是一个最重要的头文件,它囊括了其他的 windows 头文件,其中的某些头文件又包含另外的一些头文件。下列是几个最重要也是最基本的头文件:
- windef.h:基本数据类型定义
- winnt.h:支持 Unicode的类型定义
- winbase.h:内核函数
- winuser.h:用户界面函数
- wingdi.h:图形设备接口函数
程序入口:WinMain
正像 main 是 C 程序的入口(控制台程序的入口),Windows 程序的入口是 WinMain。
函数原型如下:
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow
)
参数解释:
hinstance:应用程序当前实例的句柄。句柄就是一个数值,用来标识某些东西。
hPrevlnstance:应用程序的先前实例的句柄。对于同一个程序打开两次,出现两个窗口第一次打开的窗口就是先前实例的窗口。对于一个32位程序,该参数总为NULL。
如果需要检测另外一个实例是否已经存在,则使用CreateMutex函数创建一个独一无二的名字。即使互斥名已经存在,CreateMutex函数也是成功的,但是GetLastError函数将返回 ERROR_ALREADY_EXISTS,这就表明应用程序有另外一个实例存在,因为它首先创建了互斥名。
lpCmdLine:指向应用程序命令行的字符串的指针,不包括执行文件名。获得整个命令行,参看GetCommandLine。
lpCmdLine是一个以空终止的字符串,指定传递给应用程序的命令行参数。例如:在D盘下有一个sunxin.txt文件,当我们用鼠标双击这个文件时将启动记事本程序(notepad.exe),此时系统会将D:\sunxin.txt作为命令行参数传递给记事本程序的WinMain函数,记事本程序在得到这个文件的全路径名后,就在窗口中显示该文件的内容。要在VC++开发环境中向应用程序传递参数,可以单击菜单【Project】→【Settings】,选择“Debug”选项卡,在“Program arguments”编辑框中输入你想传递给应用程序的参数。
nCmdShow:指明窗口如何显示。该参数可以是下列值之一:
- SW_HIDE:隐藏窗口并且激活另外一个窗口。
- SW_MINIMIZE:最小化指定的窗口,并且激活在系统表中的顶层窗口。
- SW_RESTORE:激活并显示窗口。如果窗口已经最小化或最大化,系统将以恢复到原来的尺寸和位置显示窗口(与SW_SHOWNORMAL相同)。
- SW_SHOW:激活一个窗口并以原来的尺寸和位置显示窗口。
- SW_SHOWMAXIMIZED:激活窗口并且将其最大化。
- SW_SHOWMINIMIZED:激活窗口并将其最小化(以图标显示)。
- SW_SHOWMINNOACTIVE:将一个窗口显示为图标。激活窗口维持活动状态。
- SW_SHOWNA:以窗口的当前状态显示窗口。激活窗口保持活动状态。
- SW_SHOWNOACTIVATE:以窗口的最近一次的尺寸和位置显示窗口。不激活窗口。
- SW_SHOWNORMAL:激活并显示窗口。如果窗口最大化或最小化,系统将其恢复到原来的尺寸和位置(与SW_RESTORE相同)。
MessageBox 函数
MessageBox指的是显示一个模态对话框,其中包含一个系统图标、 一组按钮和一个简短的特定于应用程序消息,如状态或错误的信息。消息框中返回一个整数值,该值指示用户单击了哪个按钮。
函数原型:
int WINAPI MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
参数解释:
hWnd:此参数代表消息框拥有的窗口。如果为NULL,则消息框没有拥有窗口。
lpText:消息框的内容。如果使用了Unicode库,则把文本变成:
TEXT(/*sometext*/)
lpCaption:消息框的标题。如果使用了Unicode库,则把文本变成:
TEXT(/*sometext*/)
uType:指定一个决定对话框的内容和行为的位标志集。此参数可以为下列标志组中标志的组合。指定下列标志中的一个来显示消息框中的按钮以及图标。如下所示:
//按钮
#define MB_OK 0x00000000L
#define MB_OKCANCEL 0x00000001L
#define MB_ABORTRETRYIGNORE 0x00000002L
#define MB_YESNOCANCEL 0x00000003L
#define MB_YESNO 0x00000004L
#define MB_RETRYCANCEL 0x00000005L
//图标
#define MB_ICONHAND 0x00000010L
#define MB_ICONQUESTION 0x00000020L
#define MB_ICONEXCLAMATION 0x00000030L
#define MB_ICONASTERISK 0x00000040L
#define MB_USERICON 0x00000080L
//图标声明
#define MB_ICONWARNINGMB_ICONEXCLAMATION
#define MB_ICONERRORMB_ICONHAND
#define MB_ICONINFORMATIONMB_ICONASTERISK
#define MB_ICONSTOPMB_ICONHAND
//默认按钮声明
#define MB_DEFBUTTON1 0x00000000L
#define MB_DEFBUTTON2 0x00000100L
#define MB_DEFBUTTON3 0x00000200L
#if(WINVER>=0x0400)
#define MB_DEFBUTTON4 0x00000300L//如果支持第四个MessageBox按钮的话,定义DEFButton4
#endif
//对话框模型定义
#define MB_APPLMODAL 0x00000000L
#define MB_SYSTEMMODAL 0x00001000L
#define MB_TASKMODAL 0x00002000L
#define MB_HELP 0x00004000L//是否拥有帮助按钮
//特殊声明
#define MB_NOFOCUS 0x00008000L
#define MB_SETFOREGROUND 0x00010000L
#define MB_DEFAULT_DESKTOP_ONLY 0x00020000L
#define MB_TOPMOST 0x00040000L
#define MB_RIGHT 0x00080000L
#define MB_RTLREADING 0x00100000L
具体可参见 https://baike.baidu.com/item/MessageBox
源代码下载
见 chap 01 中。