《白手起家Win32SDK应用程序》(完整版+目录).docx_第1页
《白手起家Win32SDK应用程序》(完整版+目录).docx_第2页
《白手起家Win32SDK应用程序》(完整版+目录).docx_第3页
《白手起家Win32SDK应用程序》(完整版+目录).docx_第4页
《白手起家Win32SDK应用程序》(完整版+目录).docx_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

白手起家Win32SDK应用程序目 录白手起家Win32SDK应用程序1第一篇、预备知识2第二篇、创建Win32工程和主函数6第三篇、增加一个回调函数8第四篇、注册一个窗口类10第五篇、利用已注册的窗口类来创建一个窗口15第六篇、显示你创建的窗口19第七篇、获取消息及对消息缺省处理21第八篇、关闭窗口的同时退出程序25第九篇、窗口标题栏上显示自定义图标(手动编辑代码)28第一篇、预备知识白云小飞1 说在前面由于VC6及MFC的特点,我们许多人从标准C+学习到VC6MFC应用程序的编程学习的过度会有一个很大的夸跃,从而感到非常的吃力。究其原因之一:MFC类库设计虽然精巧,但我们在使用MFC设计程序时,会发现MFC到处是API函数的影子。MFC并没有象Delphi的VCL类库,VB的控件库一样封装得让人几乎完全不用知道还有Win32API函数及其操作原理,所以要想利用VC6的MFC编程,我认为就一定要先学习如何直接用Win32API函数来编程。对API编程中的一些关键的概念和原理要有一定认识,这样才会有一个比较平滑的过渡。以上就是我写这个系列的初衷。2 我假设你已有的知识:这里我假设你已经掌握了如下的知识,如果你在如下方面知识有点不太清楚,那要去补一补罗,否则你看到相关的内容时会有麻烦的。下面说是我对你知识的假设:2.1 Windows系统的文件、文件夹、路径的概念2.2 C语言的基本知识(基本以等级考试二级C语言为准,还要有所扩充)2.2.1 指针的概念。2.2.2 函数指针概念。2.2.3 各种自定义类型(最重要的是struct类型)的概念。2.2.4 要知道函数的各种参数传递形式(值、地址、引用传递)。2.2.5 typedef及其应用。2.2.6 #include及其应用。2.2.7 十进制、二进制、十六进制。2.2.8 按位与、或、非运算的实质。2.2.9 宏定义概念、使用及意义。(每个人总是学完了C或C+语法后才会开始用VC6进行Windows编程学习的。但是你的基础又是如何呢?这是一个关键。因此我对你的C知识做了具体的假设。)2.3 会安装VC6.0并安装到一台机上2.4 VC6编译界面的各组成部分及基本操作(至少会用VC6写控制台程序)。2.5 VC6调试中至少要会设置断点哦。(呵呵!我的要求不过份吧!)3 还必须预备的知识:以上知识是你看本系列的前提,不过我还要给你预备一下我们再这个阶段学习中会遇到的新东西。3.1 你将会接触到的Win32API函数库:以前的DOS下或Windows的控制台程序下,你要在显示器上输出文字,要用printf(),或cout的函数对象来完。但如果你要显示一个图形或图象或为你的程序设计一个图形化的操作界面等等的,那可就惨了,一切都要你自已完成。复杂得很了!(唉!谁叫DOS是字符界面的操作系统呢!)现在好了,在Windows下编程你可就轻松得多了。因为Windows操作系统都为我们准备好了,它提供给我们多达数千个函数(啊!我要昏倒了。这么多的函数要学。),我们通过这些函数来操作Windows系统提供给我们的各种功能。比如我要在桌面上创建并显示一个窗口。就只要调用几个相关的被称为API的函数,让Windows来帮助我们完成这些事。我们是通过这些函数与Windows系统交互的,所以这些函数被称作Win32应用程序接口函数,简称Win32API函数。请不用害怕哟!其实,这么多的函数我们不必都马上一一学过,只要掌握了不多的具有代表性的函数的使用方法,并知道大体API函数都提供了哪些功能就可以了。以后要用时再去查。Window拥有现成的各种各样的系统功能,供我们的程序调用。那么又是通过什么方式来调用这些系统功能呢?原来,Window还现成提供一个接口,好让我们的程序来使用这些系统功能,这个结口就是Win32API函数了(注:API是应用程序接口的英文缩写)。Win32API函数是我们的应用程序与Windows系统交互的唯一途径。我并不打算这时就介绍任何一个具体的API函数。你现在只要知道你又要接触一个函数库了被称为Win32API的函数库,如同你以前所学的C/C+函数库。哈哈,这真是太好了,我们不用再象DOS一样,自已来完成程序界面的绘制了。我们现在又增加一个全新的函数库,只要调用几个相关API函数,剩下的一切由Windows来完成就可以啦!(当然还有很多其它功能。)3.2“新”的数据类型:学完C、C+之后,我们就可以开始进入VC6的Windows编程学习了。但是在接下来的学习中我们会发现在Windows编程中有许多“新”的数据类型。看下面:BOOL、BYTE、INT、UINT、WORD、DWORD、FLOAT、CHAR、LPSTR、HINSTANCE、HWND、HMENU、HICON等等。你看这些大写的数据类型,你以前有见过吗?还有很多哦!我们以后的学习过程中还会见到的。(呵呵!你可要有思想准备了!)这真是让我们初学者迷惑呀!难道VC6中对C/C+的基本数据类型又有重大的扩充了吗?其实不用害怕,只是用新瓶装旧酒而已了。在VC6的windef.h头文件中已有这些定义:typedef intBOOL;typedef unsigned charBYTE;typedef intINT;typedef unsigned intUINT;typedef unsigned shortWORD;typedef unsigned longDWORD;typedef floatFLOAT;在winnt.h中有typedef long LONG;typedef char CHAR;typedef CHAR *LPSTR, *PSTR;你看其中(粗体字)CHAR只不过是char 的别名而已,也就是说它们是等价的。只要你包含了相关的头文件,然后你就可以这样申明一个变量:INT i;/等同于int i;CHAR a;/等同于char a;LPSTR pa;/等同于char *pa;明白了吗?我想你一定会问:为什么要这样转义呢?我们直接用int 、unsighed int、char等等不就行了吗?我一句两句也说不清,你只要知道,微软这样做一定是要道理的。哦!还有这些HINSTANCE、HWND、HMENU、HICON我没说呢!今后你还会见到许多这样以H为开头的数据类型,下面就让我在下一节的“句柄”概念中说给你听。3.3 “句柄”概念由windows系统创建出来的或加载的对象(如应用程序进程、线程、窗口、菜单、图标、光标等等的对象),windows系统都会分配给它们一个唯一的标识值,作为这些对象的标志,称之为句柄。我们程序中对这些对象的操作其实就是对其句柄的操作。请记住,句柄就是这些对象的“代号”了。在编程序中,我们需要用相应的句柄变量来保存这些句柄值,那么用什么类型的句柄变量呢?就是我们前面提到过的HINSTANCE、HWND。像其它变量一样(如:int a;)申明句柄变量,如下:HINSTANCEhst;/hst变量可以保存某个应用程序实例(即一个进程)的句柄。HWNDhwFirst;/hwFrist变量可以保存某个窗体句柄。HMENU hMenu;/hMenu变量可以保存某个菜单句柄。HICON hIcon;/hIcon变量可以保存某个图标句柄。具体的使用让我以后再慢慢与你道来啦。那么这些类型的实质又是什么?目前,它们都只是一个int类型(小语:我听说微软也许以后会改变它的类型)。不过不管怎样,你现在只要把HINSTANCE、HWND、HMENU、HICON当做是一个独立的数据类型就可以了。3.4 消息标识Windows系统是一个基于消息的系统。这样的机制导致我们的程序与以往DOS下的程序流程会有很大的不同。(这可是很考我们的智慧喽!)从软件使用者角度看一个Win32窗口程序运行的过程:1) 我们运行一个应用程序,程序创建并显示一个我们想要的程序窗口。2) 当我们对窗口进行操作时(如单击、双击、右击、按下键盘、最大化、最小化、关闭窗口等等),程序会完成特定的操作,如:单击最大化、最小化按钮时,窗口会最大化、最小化操作;对窗口中菜单项的选取时,会完成该菜单的相应功能。从程序员的角度看一个Win32窗口程序运行的过程:1) 我们运行一个应用程序,程序中我们通过Win32API函数创建并显示一个我们想要的程序窗口。(由我们的程序来调用函数实现)2) 当我们对窗口进行操作时(如单击、双击、右击、按下键盘、最大化、最小化、关闭窗口等等),窗口会自动产生一系列相应的消息(这是由操作系统实现的)。3) 具体地讲:当我们改变窗口大小时,会产生WM_SIZE消息;单击关闭按钮关闭窗口时,会产生WM_CLOSE消息;选取某一菜单项时,会产生WM_COMMAND消息;按下键盘时,会产生WM_CHAR、WM_KEYDOWN、WM_KEYUP消息;单击鼠标左键时,会产生WM_LBUTTONUP、WM_LBUTTONDOWN消息等等。啊,很多很多,我也不必全部罗列出来了。(我说过了,这些都是由操作系统实现的)4) windows系统会将这些消息排入我们窗口所在线程的消息队列中(你会明白线程是什么吗?)(也由Window操作系统实现),这样我们的程序才有机会获取并处理这些产生的消息。5) 我们的程序可以通过Window操作系统提供的API函数来获取这些消息及相关的信息。然后通过我们学过的条件判断语句来判断是什么消息及其相关的操作信息并可编写相应的程序代码,从而实现对窗口操作的不同反应。(由我们的程序来实现)看上述的过程描述,你可能要有点的抽象思维能力了。你现在只要有对程序流程有如上的大体认知就可以了。慢慢地我会将上述流程变成确实的程序代码噢!(等等,还是有个问题:这些WM_CLOSE、WM_COMMAND、WM_CHAR、WM_KEYDOWN、WM_KEYUP、WM_LBUTTONUP、WM_LBUTTONDOWN等等的以WM_开头的消息到底又是什么东西呢?)看VC6的头文件winuser.h中的片段:#define WM_CLOSE0x0010#define WM_LBUTTONDOWN0x0201#define WM_LBUTTONUP0x0202#define WM_LBUTTONDBLCLK0x0203#define WM_RBUTTONDOWN0x0204#define WM_KEYDOWN0x0100#define WM_KEYUP0x0101#define WM_CHAR0x0102#define WM_INITDIALOG0x0110#define WM_COMMAND0x0111#define WM_SYSCOMMAND0x0112哦!这些WM_开头的所谓的消息只不过是一系列16进制整型数值的符号常量而已。每一个不同的整型数值代表着一个窗口某一操作的标识,因此我们将这些数值或者说以WM_开头的符号常量称之为消息了。也就说,我们在窗口中作各种不同的操作,Windows系统会产生各种相应的数值。我们就是通过条件语句比较这些数值来判断我们在窗口中所做的操作的。3.5 资源标识(你看我没完没了地介绍一个个概念,觉得烦不烦?不用你说,我自已也有点烦了。唉!不过这些似乎是必要的,所以我不得不坚持下去。不过,还好,剩下的不多了。)那么VC6中资源是什么一种概念呢?我们的程序中可能要用到各种图标(*.ico文件)、各种形状的鼠标(*.cur文件)、各种图像(*.bmp/*.gif等等)、各种声音(*.wav等)、各种菜单,这些就是我们这里所说的资源了。每一个要用到资源,我们都要给它分配一个编号或名称,作为这个资源的标识。之后我们的程序只是通过这个编号或名称来访问这些资源了。所以这些编号或名称我们称之为资源标识。好了,现在你也只要有了一个大体的映象就可以了,具体的形式和应用让我慢慢再与你说了。(各位可以提出你的疑问,白云小飞一定会尽力回复的。)啊!终于结束冗长的概念解说了,看到这里,请先回顾一下我们前面讲的东西。然后嘛我们可以开工啦!。第二篇、创建Win32工程和主函数白云小飞1 在D:创建一个空的工程(工程名为MyApp)要编写一个程序,我们就要首先用VC6应用程序向导创建一个工程,下面我将给你创建一个空工程(也就是没有任何源文件及代码的工程)1.1 操作:=文件-新建-”工程”标签-位置:”D:”(你可以设置你想要创建的位置)-工程名:MyApp(你可以自己指定其它名)-选择”创建新的工作空间”-确定-一个空工程-完成1.2 请查看指定位置下生成的文件:打开D:MyApp我们发现,它在D:下生成了一个MyApp文件夹。并在MyApp文件夹下生成了几个文件,如下:MyApp.dspMyApp.dswMyApp.ncbMyApp.opt其中,MyApp.dsp是项目文件和MyApp.dsw是工作区文件,它们是不能删除。项目文件的作用:生成一个EXE或DLL程序的所有相关源文件、有头文件的位置信息都记录在MyApp.dsp项目文件中。工作区文件的作用:如果一个复杂的软件工程可能是由多个EXE和多个DLL程序组成,这样每个项目文件的位置信息又记录在MyApp.dsw工作区文件中。当然,我们的这个工程只有一个EXE程序,所以只有一个项目,这个项目文件MyApp.dsp也同样要记录在MyApp.dsw中了。MyApp.ncb和MyApp.opt虽删除后会自动生成,但是还是请不要这样做哦!以后我还会说它们的作用。我们下次要编辑源程序时,只要打开工作区文件MyApp.dsw就可。2 在D:MyApp下创建一个C+源文件,文件名为MyAppMain(当然你也可以自己定义一个文件名),并同时加入到MyApp工程中2.1 操作:=文件-新建-”文件”标签-选”添加到工程”-选”MyApp”-文件名:MyAppMain-”位置”默认-确定2.2 查看指定生成的文件:可以看到,在D:MyApp文件夹下生成了MyAppMain.cpp源文件。3 在MyAppMain.cpp文件中输入一个主函数3.1 代码如下:#include #includeint WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hprevinstance,LPSTR lpcmdline,int ncmdshow)/ 将会在这里输入主函数的代码return 0;3.2 包含必要的头文件:首先你只要包含下面两个头文件就可,因为它们已经包含了绝大多数的MyApp应用程序必要的头文件。#include #include3.3 主函数名:函数头定义的书写格式很有趣:int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hprevinstance,LPSTR lpcmdline,int ncmdshow)写成四行,其实没什么,只不过写在一行里太长了,如下:int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance,LPSTR lpcmdline,int ncmdshow)并且写成上面的四行反而可读性更强,所以以后你会经常看到这样书写的。WinMain函数相当于Dos下的main函数,Windows应用程序的主函数不用main而是用WinMain。一个程序必有并只能有一个WinMain函数。这个主函数可以写在本工程中的任何一个.cpp文件中。3.4 参数:hinstance:类型是HINSTANCE,这种类型就是前面我们可是提到过的应用程序句柄啦。hinstance的值就是你的当前应用程序进程的句柄。你的程序每次运行,它的hinstance值是不会一样的。不过我们并不关心hinstance的值是多少。我们只要知道hinstance里的值就是代表本应用程序进程的句柄值就可以了。我们等一会儿就会用到它了,请看好哦!hprevinstance:现在已经不用了。我们可以完全不理它。lpcmdline:这是一个命令行参数。与main(int argc,char *argv)中的命令行参数相似。由于与本题无关,我们也不可完全不理它,对此不再进一步讨论下去。至于它的数据类型LPSTR,我在前面已经说明了,它其实就是char *类型。ncmdshow:一个整型值。启动过程中被传递给应用程序,带有如何打开应用程序主窗口的信息。这样,程序的使用者有了一点点的控制应用程序如何启动的能力了。作为一个程序员,如果想忽略它也可以,想使用它也行。哦,那我们这里也先忽略它了。3.5 返回值:是一个int值,当我们的程序正常结束退出时,一定要返回一个0值。所以我们的WinMain函数体内最后有return 0;了3.6 函数名前的WINAPI是什么?最后还有一个要说明的就是WINAPI。这是什么呢?在VC6的Windef.h头文件中是如下定义的:#define WINAPI_stdcall也就是WINAPI等于_stdcall了。你知道吗,凡是提供给Windows操作系统调用的函数都得是_stdcall调用的。WinMain主函数当然是由Windows系统调用的,因此定义WinMain前要用_stdcall(即WINAPI)修饰。(你会明白函数调用方式的具体含义吗?不知道也没关系,现在只要记得WINAPI要放在WinMain前就行了。)另外说明一点,int 与WINAPI哪个在前哪个在后都是可以的。好了,我们现在对主函数定义处的各个部分有了必要的了解。你可以休息一会儿,然后回顾一下我们前面操作的过程:想想我们在本篇中做了哪些事?生成了哪些文件?这些文件是什么作用的?主函数定义的各个部分是什么作用?如果你已经对上面所做的感到比较清晰,那太好了,Come on!我们继续吧!第三篇、增加一个回调函数白云小飞1 请再创建一个函数。LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)/这里可以输入响应消息的代码return 0;此函数人称回调函数也称自定义窗口过程函数。但其实它与我们一般函数无异,你千万不要把这个函数想得太复杂了啊!记住,函数名WinProc及各参数变量名是可以由你来指定,但是参数类型、个数、顺序、及返回值类型是不能改变的。那么,这个函数是干什么的啊?它是一个用来与某窗口关联的函数。当我们在窗口上的每一个操作,都会调用这个函数。这在个函数里,我们可以写上代码来完成我们在窗口上操作的相应功能。先来看参数部分:UINT msg :UINT类型不是我们在前面也见过吗?就是unsigned int类型了。每次程序运行时用户在窗口上操作所产生的消息都会通过msg传递进来。msg里保存的值就是我们对窗口操作时产生的消息值(即WM_CLOSE、WM_CHAR、WM_COMMAND、的值)。HWIND hwnd :哦!这是我在第一篇中讲过的一个窗口句柄类型的变量。我们可以通过传入的hwnd的值知道msg中的消息对应的是哪一个窗口。 WPARAM wparam , LPARAM lparam :wparam和lparam这两个参数变量的类型分别是WPARAM和LPARAM。呵呵,我不是说过,你还会见到许多“新”的数据类型的吗?你可要有心理准备噢。在windef.h中有定义:typedef UINT WPARAM;/看,WPARAM其实就是unsigned int。typedef LONG LPARAM;/看,LPARAM其实就是long类型typedef LONG LRESULT;/LRESULT与LPARAM一样也是长整型long返回值:类型为LRESULT,看windef.h中的定义可以知道是一个长整型long现在你大体知道这些就行了。至于更进一步的认识,让我们先放到一边去吧!CALLBACK:这又是什么呢?在windef.h中的定义如下:#define CALLBACK_stdcall#define WINAPI_stdcall哦!它与WINAPI是一样的,也是_stdcall了,这个WinProc函数是提供给操作系统调用的。我说过操作系统调用的函数都得在前加_stdcall。(那为什么不直接用_stdcall呢?)呵呵,这至少可以增加代码的可读性及易改性。我猜也许你还会继续下一个疑问:那我又如何具体地使用这个函数呢?慢慢来,现在你只要输入到你的.cpp文件中就可以了。到此为止,我们的MyAppMain.cpp文件代码如下:/Begin MyAppMain.cpp#include #includeLRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)/这里可以输入响应消息的代码return 0;int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hprevinstance,LPSTR lpcmdline,int ncmdshow)/ 将会在这里输入主函数的代码return 0;/End MyAppMain.cpp目前为止,这个程序还是一个什么事都没做的Win32应用程序。当然它是不会显示任何窗口的,不过我会一点一点地完善它的。最后请再认真浏览一下上述代码吧!重点回顾各参数的类型和作用。第四篇、注册一个窗口类白云小飞一 创建并显示一个窗口的“遐想”。? 首先,要显示的窗口在哪里呢?要想显示你自己的窗口,显然你得事先创建一个自己的窗口。当你想要一个窗口时,Window系统才会为你创建窗口。不要时,Window再销毁这个窗口。噢,这是多么相当然的一种机制啊,你说是吧!也就是说我们得先创建一个窗口才能显示。(否则哪里来的窗口给你显示呢?)? 其次,你想创建什么样的窗口呢?那么,创建什么样的窗口呢?创建前,Window系统可不知道你要的是什么类型的窗口啊(比如标题栏上显示什么图标,鼠标形状是什么,窗口背景颜色等等)。这些类型信息应在你创建前事先告诉Window系统。可以采用这种方法:就是我们事先写一份要创建窗口的类型申请表,提交(注册)给Window系统。然后在创建时,可以让Windows按这个申请表来创建你所要的窗口了。也就是说我们还应该先提交一个申请表,申请成功后再根据这个表创建一个窗口。依据上述的理由,我假想了以下几个步骤要做:第一 你得先填写一份你想创建的窗口类的“申请表”。第二 然后将这“申请表”通过一个API函数提交给Windows系统(即注册到Windows系统中)。第三 如果提交(注册)成功,就说明Window系统通过了你的“申请表”,Windows系统中就有了一份你所申请的窗口类(注:这个注册成功的已经注册在系统中的“申请表”我们称之为窗口类)。这样你就可以利用这个申请成功的窗口类,通过一个专门的API函数让Windows系统创建一个或多个的同一窗口类的窗口。第四 创建成功后,我们有了窗口。但是,虽然窗口已存在在内存中,并不一定就马上显示在屏幕上(这根据你的意愿了),所以之后的某时你可以用一个API函数来让Windows系统显示刚才创建的窗口。Window系统就是这样设计的噢!(呵呵,这样设计不算坏,我可以接受。)以上就是创建一个窗口的大致过程。请记住,在Window系统下你的程序要显示一个你想自定的窗口总是得经历如此步骤的。还要记住一点,我们的代码只是通过调用Window系统所提供的API函数来完成对窗口间接的管理。实际上窗口的管理操作都由Window系统直接完成的。好,让我们在本篇中先来完成第一、二步骤吧!二 第一步 填写一份“申请表”1 用什么来作为这种“申请表”呢?我想,C语言中的struct结构体类型的变量来充当这个“申请表”是再合适不过的了。呵呵,真是这样,VC6下早已为我们准备好了这样的“申请表”了。那就是WNDCLASSEX(我们称之为窗口类结构体)。看看这个WNDCLASSEX结构体的底细吧!在windef.h中已经有定义:(下面所列的与真实文件中会有点不同,但目前你只要理解我这份就可以了。)typedef struct tagWNDCLASSEX UINTcbSize;/用来保存本结构体的所占字节数UINTstyle;/窗口类型风格。/比如,可设置“若移动窗口宽度时,则刷新整个窗口。WNDPROClpfnWndProc; /回调函数指针,用以指向前面那个回调函数。intcbClsExtra;/略,我们可不必使用它,只要赋值为0就可intcbWndExtra;/略,同上HINSTANCEhInstance;/窗口所属的应用程序实例句柄。HICONhIcon;/大图标,(这个图标会显示在窗口的哪里呢?)HICONhIconSm;/小图标,(这个又会显示在窗口的哪里呢?)HCURSORhCursor;/鼠标句柄,用以指定鼠标移入窗口时的样式HBRUSHhbrBackground;/用来刷背景颜色的画刷句柄,/窗口的颜色就会按这个显示。LPCSTRlpszMenuName;/用来指向菜单资源名称字符串的指针,/可让你的窗口有一个菜单。LPCSTRlpszClassName;/用来指向窗口类名字符串的指针/作为这个窗口类的标识 WNDCLASSEX哦!是一个有12个成员变量的struct结构体的类型。(看来我们又要一个一个耐心地搞定它。)2 创建一个“申请表”现在就先让我用这个WNDCLASSEX结构体申明一个变量吧!(看粗体字部分)HWND hWnd;MSG msg;WNDCLASSEX winclass;/变量名可由你自己定。顺便解释一下:这里我顺便地同时申明了hWnd的窗口句柄变量,用以保存将要创建出来的窗口的句柄。还申明了一个msg:它的类型是MSG,也是一个已预定义好的结构体,用来保存窗口操作的各种消息信息。好了好了,以后再说这两个东东啦。3 填写“申请表”接下来就到了填写这个“申请表”的时候啦!也就是要对winclass这个结构体变量的各成员赋值。winclass.cbSize = sizeof (WNDCLASSEX);这是将本结构体的大小(占字节数)赋值给其成员变量cbSize,一定要这样做哦!好处是:以后Windows系统只要访问cbSize就可知道wndclass的大小了,就不必每次都要用sizeof(WNDCLASSEX)来获取大小。(哦,不错,这真是一个很值得学习的做法)winclass.stype=CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLICKS;我们这里将这四个值同时赋值给成员变量stype。新问题:CS_VREDRAW、CS_HREDRAW、CS_OWNDC、CS_DBLCLICKS是什么啊!stype是一个UINT即unsigned int的类型(共32位二进制位)。stype的可能值为如下的组合:表 二.3窗口类的类型标志标识描述CS_HREDRAW若移动或改变了窗口宽度,则刷新整个窗口CS_VREDRAW若移动或改变了窗口高度,则刷新整个窗口CS_OWNDC为该类中的每个窗口分配一个单值的设备描述表CS_DBLCLKS当用户双击鼠标时向窗口程序发送一个双击的信息,同时,光标位于属 于该类的窗口中CS_PARENTDC略CS_NOCLOSE禁止系统菜单上的关闭命令CS_SAVEBITS略关于更详细的类型标志描述,请自行参考相关书籍。你可能看完后仍还不能完全明白这些窗口类的类型标志的意思。没有关系,它不妨碍我们对整个程序框架的理解(我们可是要善于把握轻重缓急噢!),现在你只要按我上面赋值就可以了。还有一个问题:符号“|”是按位或的运算符,即表示CS_VREDRAW、CS_HREDRAW、CS_OWNDC、CS_DBLCLICKS的值同时都赋值给stype(只能解释到这里了,如果还不太明白“|”的运算,请自己去看关于C语言中“按位或”的相关知识了。)winclass.lpfnWndProc=WinProc;lpfnWndProc是一个函数指针(第一篇我已经说过你要对函数指针有一定认识。),它是WNDPROC函数类型,这个函数类型在winuser.h文件中已有定义。如下:typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);发现没有,WNDPROC类型的格式与我在第三篇中写的那个自定义窗口过程函数的格式是一样的。现在我们将我们的这个函数WinPro的地址赋值给lpfnWndProc函数指针变量。将前面的那个回调函数WinProc的首地址赋值给成员变量lpfnWndProc。这样这个窗口类就与这个回调函数相关联起来了。这里,你可能有个疑问:为窗口类指定一个窗口过程函数有什么用处呢?这是Window系统的消息机制的关键。但我现在不想说太多,因为真的现在无法说清楚的。只有等到我将整个程序框架建立起来后,我们再来理解它吧。(唉!我知道这种说了却又没能完全说清楚的情况不应该有,但真的是不得不为之啊!)wndclass.hInstance = hinstance;第二篇中可是说过主函数参数中hinstance的值就是本应用程序实例句柄值,我们现在将这个hinstance的句柄值赋值给wndclass.hInstance。这样,由这个窗口类结构创建的窗口就与本程序实例相关联了。wndclass.cbClsExtra=0;wndclass.cbWndExtra =0;我们现在只是对cbClsExtra和cbWndExtra两个成员简单赋值为0。你现在也不用管它们是做什么的。可以保证绝大多数的程序只要这样就行。wndclass.hCursor =LoadCursor(NULL, IDC_ARROW);hCursor是一个鼠标光标句柄变量,用来为这个窗口类指定一个鼠标句柄值(也就是想让这个窗口显示一个什么样的鼠标形状了)。LoadIcon(NULL, IDC_ARROW);这个函数是加载一个光标给hCursor的。你现在只要造就输入就可,其它的以后我再说了。wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);hIcon和hIconSm都是图标句柄变量,前一个是用以指定大图标,后一个是用以指定小图标。hIconSm中设置的图标会显示在你的窗口的标题栏左边。hIcon中设置的图标是会显示在哪儿啊?不好意思,我真的不知道。如果有人知道,请告之,本人非常感谢!关于LoadIcon函数,它是加载一个图标给hIcon及hIconSm的。现在你只要造就输入就可以了。wndclass.lpszMenuName =NULL;lpszMenuName是一个字符串指针,这是用来指向一个菜单资源名字符串。我们这个窗口暂时不要菜单,所以这里先指定NULL。wndclass.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);hbrBackground是一个画刷句柄变量(类型HBRUSH)(呵呵,又一个新句柄。)。窗口客户区的背景颜色是用这个变量指定的画刷来刷的。看不明白(HBRUSH)GetStockObject(BLACK_BRUSH)这个函数没有关系,这里它提供了一个白色画刷给我们。你现在只要造就输入就可以。wndclass.lpszClassName =WINCLASS1;lpszClassName是一个字符串指针,它是为这个窗口类(申请表)指定个字符串,这个字符串作为这个窗口类的名称。这里我们指定”WINCLASS1”字符串作为这个窗口类的名称。(要注意一点的是,一个程序中如果申请(注册)了多个窗口类,那么每个窗口类的这个字段值是不能相同的。)到此为止,我们终于(有点稀里糊涂地)结束了这个结构体各成员变量的赋值了。以上成员变量赋值代码汇总如下:wndclass.cbSize = sizeof(WNDCLASSEX);wndclass.cbClsExtra=0;wndclass.cbWndExtra =0;wndclass.lpfnWndProc = WinProc;wndclass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLKS;wndclass.hInstance = hinstance;wndclass.hCursor =LoadCursor(NULL, IDC_ARROW);wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);wndclass.lpszMenuName = NULL;wndclass.hbrBackground =(HBRUSH) GetStockObject(BLACK_BRUSH);wndclass.lpszClassName =WINCLASS1;好了,我们已经填好了我们想要创建的窗口的“申请表”了,现在可以透一口气了!然后再继续,因为我们的任务还没用完成呢!三 第二步 提交“申请表”给Window系统到了提交“申请表”的时候了。我们现在要将wndclass中的各项数据信息提交(注册)到Windows系统中。有一个API函数是专门用来注册窗口类信息的,原型如下:ATOM WINAPI RegisterClassEx(CONST WNDCLASSEX *);参数是WNDCLASSEX *类型的指针,只要将要注册的WNDCLASSEX结构体变量地址代入就行。返回值是一个ATOM类型,其实它也是一个unsigned short类型的别名而已。如果注册不成功则程序返回0值,否则表示注册成功。(注:我们暂时不关心其它返回值的意义。)所以我们注册窗口类的代码可以如下:if (!RegisterClassEx(&winclass)return 0;/不成功程序就直接结束了四 最后总括代码本篇中所增加的全部代码现总括如下(粗体字部分):WINAPI int WinMain(HINSTANCE hinstance,HINSTANCE hprevinstance,LPSTR lpcmdline,int ncmdshow)HWND hWnd; /窗口句柄变量MSG msg; /消息结构体变量WNDCLASSEX wndclass;/窗口类结构体变量/以下是对wndclass各成员赋值wndclass.cbSize = sizeof(WNDCLASSEX);wndclass.cbClsExtra=0;wndclass.cbWndExtra =0;wndclass.lpfnWndProc = WinProc;wndclass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLKS;wndclass.hInstance = hinstance; wndclass.hCursor =LoadCursor(NULL, IDC_ARROW);wndclass.hIcon =LoadIcon(NULL,IDI_APPLICATION); wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION) ; wndclass.lpszMenuName = NULL;wndclass.hbrBackground =(HBRUSH) GetStockObject(BLACK_BRUSH);wndclass

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论