(全)windows+sdk编程系列文章
- 格式:doc
- 大小:2.20 MB
- 文档页数:303
SDK编程讲座之第四讲:Windows基础结构(2)(转载)本例用MM_ANISOTROPIC模式。
这种模式把逻辑单位映射成任意的物理单位,X轴和Y轴成任意比例。
2. GetMapMode函数语法:DWORD SetViewPortOrg(HDC hDC)说明: 该函数取得当前设备描述表的映射模式。
3. SetViewPortOrg函数语法:DWORD SetViewPortOrg(HDC hDC,int x,int y)说明: 该函数为hDC设置视口原点。
返回低字节是原点X坐标,高字节为原点Y坐标。
三、画图函数GDI提供各种各样的输出操作,从画线到写字应有尽有。
为了画线、钜形、圆、扇形和写字,可相应地调用一些函数。
这些函数使用已选择的笔和刷画边框,并填写图形内部区,以及使用已选择的字体写字。
1. 画点函数SetPixel画点函数SetPixel的原型为:COLORREF SetPixel(HDC hDC,int x,int y,COLORREF cclrref);该函数把X和Y指定的点置为clrref指定的颜色。
2. 画线函数LineT o与移动函数MoveToLineT o函数用来画线,并且通常与MoveTo函数配合使用,如画一条从点(10,70)到点(250,100)的线:MoveTo(hDC,10,70);LineT o(hDC,250,100);3. 画钜形函数RectangleRectangle函数用来画钜形。
它使用已选择的笔画边框,使用已选择的刷子填满钜形内部。
下面的例子画一个左上角位于点(10,20),右下角位于点(40,100)的钜形:Rectangle(hDC,10,20,40,100);4. 画圆或椭圆函数EllipseEllipse函数用来画圆或椭圆。
它使用已选择的笔画框,使用已选择的刷填满圆或椭圆的内部。
下面的例子画一个用点(10,20)和点(40,100)构成钜形框中的椭圆:Ellipse(hDC,10,20,40,100);5. 画圆弧函数ArcArc函数用来画一段弧,这段弧由包围它的钜形和弧的开始点和结束点共同定义。
在上一章的基础上,一样一样地学习SDK编程的内容,大家只要跟着教程多动手,多看帮助。
这三章攻克之后,后面就不难了。
一、注册窗口类
“ATOM MyRegisterClass(HINSTANCE hInstance)”中的ATOM是无符号整数类型,参数hInstance是当前窗口的句柄,这里的关键是API函数RegisterClassEx(&wc),先看一下这个函数的原型。
这个函数的参数是一个结构体,你想要申请一个什么样的窗口,要事先设置好,然后传给这个函数。
下面再看一下WNDCLASSEX的结构。
窗口式样style的值可用下表的值组合起来设置,窗口处理函数名lpfnWndProc
和hInstance不能设置错。
光标有2个hIcon和hIconSm,当取不到值时自动分配一个系统缺省值。
光标hCursor可选择下面的光标ID设置到结构体中去。
关于图标、背景、菜单后面有专门章节介绍。
下面在上一章的基础之上,修改部分数据,看看有什么变化。
二、初始化窗口
InitInstance()函数中,CreateWindow()函数创建一个窗口,这儿说的窗口是广义的窗口,事实上按钮也是窗口,也是由这个函数创建的。
其中最关键的是第三个参数,先看一下函数原型。
窗口式样有以下几种,先用简单易懂的值试一试,然后再逐步深入。
动手做是学习的关键。
下面我们在上一个例子的基础上修改2个地方,看看有什么变化。
运行之后窗口变成了最小化。
10章用鼠标作图
一、捕获、释放光标
上一章的程序在鼠标控制方面还有问题,之所以用它作例子,完全是为了让大家将鼠标事件搞明白,这一章,我们就来纠正这些问题点。
首先要掌握ClipCursor()函数,这个函数将可以将光标限定在窗口有效区内,注意:这个函数的参数用的矩形座标是整个屏幕的座标,这是因为鼠标是全屏动作的。
因此,我们还必须学会将窗口有效区座标转换为屏幕座标。
ClientToScreen()函数可以实现这一目的,不过这一函数在MFC中的参数和SDK 中的参数不一样,MFC中转换的是一矩形块,而SDK转换的是一个点。
所以,SDK编程中,下面例子是先转换窗口有效区的(0,0)点,再计算出矩形右下角的点。
二、消除移动轨迹
上例中,想要画一条线(即鼠标按下到松开的一条线),结果却将鼠标移动的“轨迹”画了出来,这些“轨迹”必须擦掉。
VC不提供擦掉已经画好的图案的功能,所谓“擦掉”,就是选用某种方式重画,使得看上去象重画一样。
通过SetROP2()函数就可以实现这个功能,这个函数将反转屏幕颜色,这样第二次画时就恢复为原来的颜色。
注:SetROP2()函数这是设置画图模式的函数,是设置前景与背景的关系。
三、鼠标松开后的处理
上例画线部分基本可以说大功告成,但多画几条交叉线,仔细一看便发现交差点有的地方变成空白。
原因其实很简单,第一根线为黑色,第二根线在交差点处反转后自然是空白。
另外,如果最终想画成兰色的粗线的话,该怎么办?
这很简单,只要在鼠标松开时再画一次,这时可以设置颜色和粗细,另外,作图模式也得改为正常模式。
windows sdk编程系列文章 --- 直接从硬盘扇区读取文件内容2008-09-05 15:43理论:基本概念就是通过文件句柄获取文件所在的簇列表。
然后直接打开硬盘,根据簇所在的位置,直接读取文件数据。
方法1:可以通过打开"\\\\.\\PHYSICALDRIVE0",读取MBR,然后根据MBR中的DPT,找到活动分区的偏移,定位到DBR。
然后将要定位簇的文件打开,获取文件句柄,将文件句柄传递给DeviceIoControl的FSCTL_GET_RETRIEVAL_POINTERS功能,就可以得到RETRIEVAL_POINTERS_BUFFER结构。
方法2:直接打开"\\\\.\\c:"就是定位到DBR了。
然后跟上面同样的操作。
对于一些基本概念,MBR, DPT,DBR,以及fat32和ntfs的文件结构,可以参考下面的链接了解。
/html/magnetism/200806/17-55.html代码:(vc6, ntfs 见光盘DirectAccessFile#define _WIN32_WINNT 0x0400#include#include#includeULONGLONG *GetFileClusters(PCHAR lpFileName,ULONG *ClusterSize,ULONG *ClCount,ULONG *FileSize{HANDLE hFile;ULONG OutSize;ULONG Bytes, Cls, CnCount, r;ULONGLONG *Clusters = NULL;BOOLEAN Result = FALSE;LARGE_INTEGER PrevVCN, Lcn;STARTING_VCN_INPUT_BUFFER InBuf;PRETRIEVAL_POINTERS_BUFFER OutBuf;CHAR Name[7];DWORD SecPerCl;DWORD BtPerSec;Name[0] = lpFileName[0];Name[1] = ':';Name[2] = 0;GetDiskFreeSpace(Name, &SecPerCl, &BtPerSec, NULL, NULL;*ClusterSize = SecPerCl * BtPerSec;hFile = CreateFile(lpFileName, FILE_READ_ATTRIBUTES,FILE_SHARE_READ |FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL, OPEN_EXISTING, 0, 0;if (hFile != INVALID_HANDLE_VALUE{*FileSize = GetFileSize(hFile, NULL;OutSize = sizeof(RETRIEVAL_POINTERS_BUFFER + (*FileSize / *ClusterSize * sizeof(OutBuf->Extents;OutBuf = (RETRIEVAL_POINTERS_BUFFER *malloc(OutSize;InBuf.StartingVcn.QuadPart = 0;if (DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, &InBuf,sizeof(InBuf, OutBuf, OutSize, &Bytes, NULL{*ClCount = (*FileSize + *ClusterSize - 1 /*ClusterSize;Clusters = (ULONGLONG *malloc(*ClCount *sizeof(ULONGLONG;PrevVCN = OutBuf->StartingVcn;for (r = 0, Cls = 0; r < OutBuf->ExtentCount; r++{Lcn = OutBuf->Extents[r].Lcn;for (CnCount = (ULONG(OutBuf->Extents[r].NextVcn.QuadPart - PrevVCN.QuadPart;CnCount; CnCount--, Cls++, Lcn.QuadPart++Clusters[Cls] = Lcn.QuadPart;PrevVCN = OutBuf->Extents[r].NextVcn;}}free(OutBuf;CloseHandle(hFile;}return Clusters;}void Read(PCHAR lpSrcName{ULONG ClusterSize, BlockSize;ULONGLONG *Clusters;ULONG ClCount, FileSize, Bytes;HANDLE hDrive;ULONG r;PVOID Buff;LARGE_INTEGER Offset;CHAR Name[7];Clusters = GetFileClusters(lpSrcName, &ClusterSize, &ClCount, &FileSize;if (Clusters{Name[0] = '\\';Name[1] = '\\';Name[2] = '.';Name[3] = '\\';Name[4] = lpSrcName[0];Name[5] = ':';Name[6] = 0;hDrive = CreateFile(Name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0;if (hDrive != INVALID_HANDLE_VALUE{Buff = malloc(ClusterSize;for (r = 0; r < ClCount; r++, FileSize -= BlockSize{Offset.QuadPart = ClusterSize *Clusters[r];SetFilePointer(hDrive, Offset.LowPart,&Offset.HighPart, FILE_BEGIN;ReadFile(hDrive, Buff, ClusterSize,&Bytes, NULL;BlockSize = FileSize < ClusterSize ? FileSize : ClusterSize;}free(Buff;CloseHandle(hDrive;}free(Clusters;}}void main({Read("c:\\windows\\system32\\comctl32.dll";}分析:GetFileClusters 函数用于获取文件占用的簇列表,以及每个簇占用字节数,文件占用的簇数,文件大小等信息。
windows sdk编程系列文章 ---- 位图2008-04-23 21:34为微软windows操作系统编写的应用程序可以使用两种图像工具来存储图像:元文件和位图,在这一课,我们将学习怎样在程序中使用位图,更准确地说,我们要学习的是怎样在一个窗口的客户区显示位图。
理论:位图就是存贮于电脑中的图片。
位图文件有相当多的格式(如.BMP.JPG.GIF.PIC 等)但Windows仅支持Windows Bitmap Graphics 格式,即BMP文件。
本课所指的位图也是BMP 文件。
使用位图最简单的方法就是把它定义在资源文件(.rc)中。
定义的方法有两种。
第一种方法是把它定义为整数宏,具体如下:#define IDB_MYBITMAP 100IDB_MYBITMAP BITMAP"c:\project\example.bmp"第一行我们定义了一个值为100的整数宏。
第二行我们把这个整数宏指向所要定义的位图,这样,编译器就能知道位图所在的路径。
另一种方法是给它起一个名字,也就是把它定义为字符串,具体如下:MyBitMap BITMAP"c:\project\example.bmp"两种方法效果是一样的。
选择哪一种方法,视乎在程序中你喜欢用整数宏还是用字符串来指向位图。
现在我们已经把位图定义在资源文件中,下一步就是把它显示在窗口的客户区上。
在程序中,我们使用API函数LoadBitmap 取得位图句柄。
下面是LoadBitmap 函数的原型:HBITMAP LoadBitmap(HINSTANCE hInstance, LPCTSTR lpBitmapName);该函数返回一个位图句柄。
函数有两个参数,其中hInstance 是程序句柄。
lpBitmapName 是位图名字的指针(适用于第二种定义方法)。
如果你使用了第一种定义方法,你可以填入指向位图的值或整数宏(对应上例这个值就是100,整数宏是IDB_MYBITMAP)。
2《白手起家Win32SDK应用程序》第二篇创建Win32工程和主函数第二篇创建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源文件。
windows sdk编程系列文章 ---- 管道2008-04-17 22:58这一讲将探索一下管道,看看它是什么、有什么用。
为使之更加生动有趣,我将用怎样改变 Edit 控件的背景色和文本颜色来说明此技术。
理论:管道,顾名思义就是有两个端的通道。
可以使用管道在进程间、同一进程内进行数据交换,就像手提式无线电话机一样。
把管道的一端给另一方,他就可以借助管道和你通讯了。
有两种管道,即有名管道和匿名管道。
匿名管道就是没有名字的管道了,也就是说在使用它们时不需要知道其名字。
而有名管道正好相反,在使用前必须知道其名字。
也可以根据管道的特性来分类,即是单向的还是双向的。
单向管道,数据只能沿一个方向移动,从一端流向另一端,而双向管道数据可以在两端间自由交换。
匿名管道通常是单向的而有名管道通常是双向的。
有名管道常用于一个服务器联络多个客户端的网络环境。
这一讲将详细讨论一下匿名管道。
匿名管道主要目的是作为父进程与子进程、子进程之间通讯的联结通路。
在处理控制台问题时,匿名管道是相当有用的。
控制台应用程序就是使用控制台作为输入和输出的一种 Win32 应用程序。
一个控制台就像一个 DOS 窗口。
但控制台应用程序的的确确是32位的应用程序,它可以向其它图形程序一样使用 GUI 函数,只不过它碰巧使用了控制台罢了。
控制台应用程序有三个用于输入输出的标准句柄,它们是标准输入、标准输出和标准错误句柄。
标准输入用于从控制台读或取信息而标准输出用于往控制台写或打印信息。
标准错误用于汇报输出不能重定向的错误。
控制台应用程序可以通过调用函数 GetStdHandle 来获得这三个句柄。
一个图形应用程序没有控制台,如果在其中调用GetStdHandle 就会返回错误;如果的确要使用控制台,可以调用AllocConsole 来分配一个新的控制台以使用,但当处理完成时,别忘了调用 FreeConsole 来释放控制台。
匿名管道用得最多的功能就是重定向子进程的标准输入和标准输出。
WindowsSDK编程API⼊门系列(转)之⼀ -那‘烦⼈’的Windows数据类型原创⽂章,转载请注明作者及出处。
⾸发Hello Everybody This is beyondcode⼤家好再次⾃我介绍⼀下我是beyondcode, 这次⼼⾎来潮, 计划着做⼀系列关于Windows API 编程的教程,⽤于帮助⼀些在Windows API编程上有疑惑的,纳闷的,迷惑的新⼿朋友们。
先解释⼀些术语或名词吧 SDK是Software Development Kit的简写,也就是软件开发包的意思,其中就包含了我们写程序要⽤到的⼀些头⽂件,库,⼯具,帮助⽂档之类的。
Windows API编程是指调⽤Windows的接⼝函数来进⾏程序的编写,例如MessageBox就是⼀个API函数或者说接⼝函数。
怎么说都可以,⾃⼰理解就⾏。
如果你连这个都不太懂,我想也不会搜到这篇⽂章了吧~·为什么做这个系列教程呢,请听我⼀⼀道来先,最近遇到⼀些事⼀些⼈,让我真的感觉在这⽅⾯的引导⼊门⽂章真的很是匮乏,加上Windows SDK头⽂件中那些复杂,庞⼤,'烦⼈'的宏定义与数据类型定义,对于⼀个新⼿来说(我所说的新⼿不单只刚接触编程的,还特指那些在其他语⾔领域有⽐较⾼造诣的朋友) ⼀个纯SDK写的helloworld程序都算是⼀个有些困难和挑战的任务了吧。
本着帮助别⼈,⾼兴⾃⼰的原则,我有了这个打算,当然对⾃⼰以前所学,所经历做⼀次回忆,也是这次计划的⼀部分。
声明⼀下,本系列教程是⾯向⼴⼤初次接触WIN32 SDK程序编写的新⼿朋友们的,如果你是⾼⼿,⼀笑⽽过吧~当然,除了⼀笑⽽过,也多谢你们提出指正⽂章中的错误,以免我误⼈⼦弟啊~~谢谢Ok 废话不多说,进⼊正题,今天第⼀篇,讲什么? 对于⼀个新⼈来说,第⼀次接触SDK编程或者说API编程,什么最迷惑你们的,我们讲它,我觉得Windows SDK中那'烦⼈'的数据类型定义和宏定义应该算这个很⾓⾊吧。
windows sdk编程系列文章---- 消息框在本课中,我们将用C语言写一个 Windows 程序,程序运行时将弹出一个消息框并显示"hello world"。
理论:Windows 为编写应用程序提供了大量的资源。
其中最重要的是Windows API (Application Programming Interface)。
Windows API是一大组功能强大的函数,它们本身驻扎在 Windows 中供人们随时调用。
这些函数的大部分被包含在几个动态链接库(DLL)中,譬如:kernel32.dll、 user32.dll 和 gdi32.dll。
Kernel32.dll中的函数主要处理内存管理和进程调度;user32.dll 中的函数主要控制用户界面;gdi32.dll中的函数则负责图形方面的操作。
除了上面主要的三个动态链接库,您还可以调用包含在其他动态链接库中的函数,当然您必须要有关于这些函数的足够的资料。
动态链接库,顾名思义,这些 API 的代码本身并不包含在 Windows 可执行文件中,而是当要使用时才被加载。
为了让应用程序在运行时能找到这些函数,就必须事先把有关的重定位信息嵌入到应用程序的可执行文件中。
这些信息存在于引入库中,由链接器把相关信息从引入库中找出插入到可执行文件中。
您必须指定正确的引入库,因为只有正确的引入库才会有正确的重定位信息。
当应用程序被加载时 Windows 会检查这些信息,这些信息包括动态链接库的名字和其中被调用的函数的名字。
若检查到这样的信息,Windows 就会加载相应的动态链接库,并且重定位调用的函数语句的入口地址,以便在调用函数时控制权能转移到函数内部。
如果从和字符集的相关性来分,API 共有两类:一类是处理 ANSI 字符集的,另一类是处理 UNICODE 字符集的。
前一类函数名字的尾部带一个"A"字符,处理UNICODE的则带一个"W"字符(我想"W"也许是代表宽字符的意思吧)。
我们比较熟悉的ANSI字符串是以 NULL 结尾的一串字符数组,每一个ANSI字符是一个 BYTE 宽。
对于欧洲语言体系,ANSI 字符集已足够了,但对于有成千上万个唯一字符的几种东方语言体系来说就只有用 UNICODE 字符集了。
每一个 UNICODE 字符占有两个 BYTE 宽,这样一来就可以在一个字符串中使用 65336 个不同字符了。
几乎每一个API都有处理这两种字符集的形式,例如:MessageBoxA和MessageBoxW, 其中MessageBoxA是适用于处理ANSI字符集的API。
MessageBoxW是适用于UNICODE字符集的API。
在c中为了调用方便,对这两个API进行了宏定义。
统一使用MessageBox 。
编译的时候会根据编译设置决定是使用MessageBoxA还是使用MessageBoxW。
下面摘自WINUSER.H中关于MessageBox 的定义。
WINUSERAPIintWINAPIMessageBoxA(HWND hWnd ,LPCSTR lpText,LPCSTR lpCaption,UINT uType);WINUSERAPIintWINAPIMessageBoxW(HWND hWnd ,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);#ifdef UNICODE#define MessageBox MessageBoxW#else#define MessageBox MessageBoxA#endif其中WINUSERAPI 是一个宏,该宏定义了其修饰的函数是从其他库中导入的,还是自身定义的。
#if !defined(_USER32_)#define WINUSERAPI DECLSPEC_IMPORT#else#define WINUSERAPI#endif为了两种字符集都可以支持,在处理字符时,我们使用_T("")宏。
该宏会根据你的设置,将你的字符串转变为相应的字符集。
例子:(见光盘Helloword)#include "windows.h"#include "tchar.h"int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ){MessageBox(NULL,_T("hello world"),_T("My First Windows Program"),MB_OK);return 1;}分析:当我们在工程中Settings里面设置如下图所示的UNICODE,_UNICODE时,代码中的_T("hello world")和_T("My First Windows Program")编译时都转化为unicode字符。
MessageBox也会使用MessageBoxW函数。
如果按照下图的设置,使用_MBCS. 代码中的_T("hello world")和_T("My First Windows Program")编译时都转化为ANSI字符。
MessageBox也会使用MessageBoxA函数。
windows sdk编程系列文章---- 简单窗口程序理论:Windows 程序中,在写图形用户界面时需要调用大量的标准 Windows Gui 函数。
其实这对用户和程序员来说都有好处,对于用户,面对的是同一套标准的窗口,对这些窗口的操作都是一样的,所以使用不同的应用程序时无须重新学习操作。
对程序员来说,这些 Gui 源代码都是经过了微软的严格测试,随时拿来就可以用的。
当然至于具体地写程序对于程序员来说还是有难度的。
为了创建基于窗口的应用程序,必须严格遵守规范。
作到这一点并不难,只要用模块化或面向对象的编程方法即可。
下面我就列出在桌面显示一个窗口的几个步骤:1.得到您应用程序的句柄(对于C程序,可选);2.得到命令行参数(如果您想从命令行得到参数,可选);3.注册窗口类(必需,除非您使用 Windows 预定义的窗口类,如 MessageBox 或 dialog box;4.产生窗口(必需);5.在桌面显示窗口(必需,除非您不想立即显示它);6.刷新窗口客户区;7.进入无限的获取窗口消息的循环;8.如果有消息到达,由负责该窗口的窗口回调函数处理;9.如果用户关闭窗口,进行退出处理。
相对于单用户的 DOS 下的编程来说,Windows 下的程序框架结构是相当复杂的。
但是 Windows 和 DOS 在系统架构上是截然不同的。
Windows 是一个多任务的操作系统,故系统中同时有多个应用程序彼此协同运行。
这就要求 Windows 程序员必须严格遵守编程规范,并养成良好的编程风格。
例子:(见光盘FirstWindow)#include "Windows.h"#include "tchar.h"HWND hWinMain;TCHAR szClassName[] = _T("MyClass");TCHAR szCaptionMain[] = _T("My First Window!");TCHAR szText[] = _T("Win32 program, Simple and powerful !");WNDCLASSEX stdWndClass;//如果有消息到达,由负责该窗口的窗口回调函数处理LRESULT CALLBACK ProcWinMain( HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam){switch(Msg){//如果用户关闭窗口,进行退出处理case WM_CLOSE:{DestroyWindow(hWinMain);PostQuitMessage(NULL);}break;default:return DefWindowProc(hWnd, Msg, wParam, lParam );}return 0;}int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){MSG stMsg;WNDCLASSEX stdWndClass;RtlZeroMemory(&stdWndClass, sizeof(stdWndClass));stdWndClass.hCursor = LoadCursor(0,IDC_ARROW);stdWndClass.cbSize = sizeof(stdWndClass);stdWndClass.style = CS_HREDRAW|CS_VREDRAW;stdWndClass.lpfnWndProc = ProcWinMain;stdWndClass.hbrBackground = (HBRUSH)COLOR_WINDOW;stdWndClass.lpszClassName = szClassName;stdWndClass.hInstance = hInstance;//注册窗口RegisterClassEx(&stdWndClass);//产生窗口hWinMain = CreateWindowEx(WS_EX_CLIENTEDGE,szClassName,szCaptionMain,\WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL);if(!hWinMain)return 0;//在桌面显示窗口ShowWindow(hWinMain,SW_SHOWNORMAL);//刷新窗口客户区UpdateWindow(hWinMain);//进入无限的获取窗口消息的循环while(GetMessage(&stMsg,NULL,0,0)){TranslateMessage(&stMsg);DispatchMessage(&stMsg);}return stMsg.wParam;}分析:看到一个简单的 Windows 程序有这么多行,您是不是有点想撤? 但是您必须要知道的是上面的大多数代码都是模板而已,模板的意思即是指这些代码对差不多所有标准 Windows 程序来说都是相同的。