SDK入门

SDK入门

以下内容是鄙人在今天学SDK的过程中,下载过的一片未曾谋面的大神的文章,觉得写的甚是好啊,让我这个长得很黑的小白不禁惊喜,这里就像远方的好人拜谢啦(鞠躬!!!)。不管怎么说,我都觉得好的东西应该拿出来大家一块分享,看这篇文档的时候,我目前是实在不敢在正文乱改一个字,一个是因为自己的水平太次,另一个是人家写的太专业,生怕改动会破坏它原本的准确性。(不过我打算以后要拿出来按照自己的理解和自己的语言风格改改,方便自己理解,当然这都是后话了)


关于SDK

 

1、Windows SDK入门浅谈 — 写给初学者

2、什么是Windows SDK

3、不要被第一个Windows程序吓住

4、学习的方法

5、几种Windows编程方法的辨析及其它

6、Windows SDK编程初探

7、Windows SDK编程之建立控件

 

 

 

 

 

 

 

 

 

 

 

 

 

1、Windows SDK入门浅谈 — 写给初学者

 

前言

 

   如果你是一个编程初学者,如果你刚刚结束C语言的课程。你可能会有点失望和怀疑:这就是C语言吗?靠它就能编出软件?无法想象Windows桌面上一个普通的窗口是怎样出现在眼前的。从C语言的上机作业到Windows编程确实有比较大的gap。或许你已经看了programmingWindows的前三章,但是对于那个hello windows程序甚为迷惘。希望hfire的这篇文章能帮你填补这个gap,并提供一些学习的经验。为什么是浅谈,因为hfire知道的也不够深,肯定会有错误,请批评指正。

 

程序与运行时环境及操作系统

 

  当你用Turbo C编写了一个C程序,然后编译连结它,得到了一个可执行文件。在Dos的命令提示符下键入这个exe文件的文件名,然后它就执行了。表面看事情就是这些。作为一个应用程序员,我们不用考虑背后的事情,但是有一个简单的事实我们必须清楚的认识:程序不只是靠自己运行,它需要运行时环境的配合。考虑一下用一个printf函数显示一个字符串的过程。显然这个函数不是你自己写的。或许你听说过C-Runtime Library,C运行时库,没错,你的程序只有依靠它才能运行。printf的代码就在C运行时库中,因此你可以轻松的调用它而不管它是怎么实现的。但是,C运行时库也会调用一些别的函数,这些函数是由操作系统提供的,称为中断服务程序,而操作系统的中断服务程序会进一步的调用BIOS中断服务程序。可以看出,程序的运行是由一层一层的服务支撑起来的。在这里面,操作系统担当了非常重要的角色。它提供了程序员可以直接使用的例程,也可以称为Application Programming Interface (应用程序编程界面,API) 。Dos中一般没有API的说法,Dos的编程界面是由中断服务程序充当。在Windows中编程就要常常和API打交道。32位Windows的API有2000多个,一方面它提供了功能强大的编程界面,另一方面它使初学者望而却步。

 

 

 

 

Windows操作系统基本常识

 

  Windows是一个单用户多任务图形化操作系统。所谓单用户,指同时只能由一个用户(一个人)通过Windows系统操作电脑;所谓多任务,指同时可以有多个进程并发执行。既然Windows系统有这些特点,那么Windows编程就会体现这些特点。为了做到多任务,Windows程序使用消息机制,有我的消息我才干活,没我的消息就把CPU让给别人;为了做到图形化,Windows程序必须显示窗口并自己绘制客户区,就连显示字符串也必须画到客户区上。还有一点,Windows广泛使用动态链接。Windows的API就放在动态链接库中,以供程序运行时调用。在Windows98中有32位的gdi32.dll,user32.dll,kernel32.dll和16位的gdi.exe,user.exe,krnl386.exe,API就存在于这些动态链接库中。

 

2、什么是Windows SDK

 

微软每推出一个重要的windows版本,一般都会同时推出一个SDK(Software DevelopmentKit)。SDK包含了开发该windows版本所需的windows函数和常数定义、API函数说明文档、相关工具和示例。SDK一般使用C语言,但不包括编译器。高版本VC++包括了SDK所有的头文件、帮助、示例和工具,不需要再安装SDK,低版本如VC++5.0则需要安装SDK。从windows 98开始,windows SDK叫PlatformSDK(http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en),包含最新的windows API函数的有关声明、例子。

  用VC编写windows程序有两种方式:windowsc方式(SDK)和C++方式(对SDK函数进行包装,如VC中的MFC、BCB中的VCL)。SDK编程就是直接用windows API进行编程。API由上千个API函数组成(win95中有两千多个),而MFC是API的封装,结合面向对象的继承、多态组成一个个类,共有一百多个类组成。

  SDK是Software Development Kit的缩写,中文意思是“软件开发工具包”。这是一个覆盖面相当广泛的名词,可以这么说:辅助开发某一类软件的相关文档、范例和工具的集合都可以叫做“SDK”。具体到我们这个系列教程,我们后面只讨论广义SDK 的一个子集——即开发 Windows 平台下的应用程序所使用的 SDK。

  其实上面只是说了一个 SDK 大概的概念而已,理解什么是 SDK 真有这么容易吗?恐怕没这么简单!为了解释什么是SDK 我们不得不引入 API、动态链接库、导入库等等概念。^_^,不要怕,也就是几个新的名词而已,我也是到了大学快结束的时候才体会到其实学习新知识就是在学习新名词、新概念和新术语。

  首先要接触的是“API”,也就是 Application Programming Interface,其实就是操作系统留给应用程序的一个调用接口,应用程序通过调用操作系统的 API 而使操作系统去执行应用程序的命令(动作)。其实早在 DOS 时代就有 API 的概念,只不过那个时候的 API 是以中断调用的形式(INT 21h)提供的,在 DOS 下跑的应用程序都直接或间接的通过中断调用来使用操作系统功能,比如将 AH 置为 30h 后调用 INT 21h 就可以得到 DOS 操作系统的版本号。而在 Windows 中,系统 API 是以函数调用的方式提供的。同样是取得操作系统的版本号,在 Windows 中你所要做的就是调用GetVersionEx() 函数。可以这么说,DOS API 是“Thinking in 汇编语言”的,而 WindowsAPI 则是“Thinking in 高级语言”的。DOS API 是系统程序的一部分,他们与系统一同被载入内存并且可以通过中断矢量表找到他们的入口,那么 Windows API 呢?要说明白这个问题就不得不引入我们下面要介绍得这个概念——DLL。

  DLL(又是一个缩写,感觉 IT 这个行业里三字头缩写特别多),即 DynamicLink Library(动态链接库)。我们经常会看到一些 .dll 格式的文件,这些文件就是动态链接库文件,其实也是一种可执行文件格式。跟 .exe 文件不同的是,.dll 文件不能直接执行,他们通常由 .exe 在执行时装入,内含有一些资源以及可执行代码等。其实 Windows 的三大模块就是以 DLL 的形式提供的(Kernel32.dll,User32.dll,GDI32.dll),里面就含有了 API 函数的执行代码。为了使用DLL 中的 API 函数,我们必须要有 API 函数的声明(.H)和其导入库(.LIB),函数的原型声明不难理解,那么导入库又是做什么用的呢?我们暂时先这样理解:导入库是为了在 DLL 中找到 API 的入口点而使用的。

  所以,为了使用 API 函数,我们就要有跟 API 所对应的 .H 和 .LIB 文件,而 SDK 正是提供了一整套开发 Windows 应用程序所需的相关文件、范例和工具的“工具包”。到此为止,我们才真正的解释清楚了 SDK 的含义。

  由于 SDK 包含了使用 API 的必需资料,所以人们也常把仅使用 API 来编写 Windows 应用程序的开发方式叫做“SDK 编程”。而 API 和 SDK 是开发 Windows 应用程序所必需的东西,所以其它编程框架和类库都是建立在它们之上的,比如 VCL 和 MFC,虽然他们比起“SDK 编程”来有着更高的抽象度,但这丝毫不妨碍它们在需要的时候随时直接调用 API 函数。

  

说说SDK

  时下学计算机的大多想学编程,且大部分都是在Windows下工作的,而目前学得最热门的是VC,大多数人一开始就开始学习VC,VC是以C++为语言基础的开发工具,而C++是C语言的扩充,故要学好VC最好是先学好C和C++。

  用VC编写Windows程序有两种:1. Windowsc方式(SDK),2. C++方式:即对SDK函数进行包装,如VC的MFC,BCB的VCL等。SDK编程就是直接调用Windows的API进行编程,平时人们常说"用 SDK写程序"就是指用Windows的API函数来写程序,API由上千个API函数组成(Win95的API有两千多个)。而MFC是API的封闭,结合面向对象程序设计的继承性和多态性组成一个个的"类",共由一百多个类组成。尽管MFC比SDK方便,但要深入VC,直接去学MFC却是不明智的选择。只有在熟悉了MFC的运行机制的情况下,才有可能深入下去。所以学VC最好是先学用SDK编写程序,在此期间掌握Windows操作系统的工作原理和各API函数的应用,然后再深入MFC。

  编程环境

  我们仍然用VC6的IDE(集成开发环境)来编写SDK程序,启动VC6后选择File菜单的New...选项,在出现的New对话框的Projects标签内选择Win32 Application,然后在ProjectsName指定项目的名字,在Location中指定路径后按OK按钮,在出现的对话框中,如果你想要用C语言来写程序可以选择An emtpy project,如果你想创建一个带有WinMain入口函数和普通参数的设定的项目,可以选择A simple Win32 application,如果您想创建一个简单典型的“Hello World!”Win32SDKapplication应用程序,可以选择A typical"Hello World!" application。确定项目类型后按Finish完成。

  在VC6环境下,你依然可以使用资源编辑器和ClassWizar等工具完成程序的编写。用SDK编写程序关键是能够了解程序的来龙去脉。如果不了解,当然那样效率会很低,不比VB、PB那么快,任何东西都是有得有失,如你熟悉用SDK写程序后,对MFC会比较容易上手的,关键要熟悉C++的三大特性。

SDK即software develope kit(软件开发工具包),它包含了进行Windows软件开发的文档和API函数的输入库、头文件(因为API在动态链接库中,这些动态链接库是系统的组成部分因此不用再提供,而输入库和头文件则必须,这样才能在你的程序中使用API函数)。早期SDK是一个单独发放的包,现在在Visual C++和其他一些开发环境中已经包含了它。如果你已经安装了VC++那么就可以开始编写Windows程序了。随着Windows系统的发展,SDK的内容越来越多,我们只要抓住最基本的方面。至于其他专门的主题,就根据自己的兴趣和技术方向进一步学习了。

 

3、不要被第一个Windows程序吓住

 

  如果你已经开始,你的教材应该是那本经典的programmingwindows (petzold)或者是一本相似的书。但无论哪本书,一开始你都会面对一个基本的Windows SDK程序,这个程序有几十行。尽管也不算长,但比C版的hello world长多了。更糟的是,里面充斥着奇怪的变量类型和常量定义,不过先不用被它吓住,让我们看看这里面有些什么。首先会有一个#include <windows.h> ,嗯,没什么奇怪的,这和#inclde <stdio.h>没什么两样。然后是一个函数声明:LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 有点困惑了,一下子就出来了好几个“生词”,而且函数名前面有两个修饰符也是以前没有遇到的。好在我们还可以辨认出这是一个函数声明。再往下看是WinMain函数,又是一堆生词,我猜想你可能已经开始郁闷了。想一遍看懂这个程序确实困难,所以看不懂也没关系。看不下去了可以看看书上的讲解。这篇文章并不是要完整分析这个程序的,hfire不可能有petzold讲的好。在这里hfire帮你分析一下一些陌生的东西。

  首先说Windows的数据类型。尽管这些数据类型看上去很陌生,其实它们是由C的基本数据类型define的。比如UINT就是unsinged int,PSTR就是pointer to string 的意思,猜猜就知道是char * 。Windows还有很多系统定义的结构体,比如WNDCLASS,MSG等,这些东西见的多了就自然明白了。Windows还有一个重要的概念,句柄。通过句柄就可以操作Windows对象。HWND,HINSTANCE,HDC等都是句柄。

  再说说Windows程序的结构。一般有一个WinMain函数作为程序的入口点,在WinMain里面定义窗口类,进行消息循环。消息循环就是那个普通的while循环,在其中接收消息、分发消息。然后是窗口函数WndProc,名字可以自己定。在其中用一个大的switch结构检索消息,在每个case下面写处理消息的代码。最简单的Windows SDK程序只要写这两个函数就够了。等你的程序写长了,就要把特定的消息处理代码写成函数,以便在处理消息时调用,甚至你可以使用C++来写程序。等你熟悉这种结构以后,就可以任意发挥了。

  其他的不想说太多,学SDK很重要的是不要期望在开始时把每行代码都搞清楚。

 

4、学习的方法

 

  当然是多写程序了。最好每个主题都写一个。从一开始的窗口,文本显示到图形显示、控件、对话框,多写就能领会Windows编程的内涵。当第一部分学的差不多了,可以写一个综合点的程序。最后你会发现你可以写很长的程序了,1000多行也不算长,但对于当时学C时是难以想象的。还有重要的是多上一些专门的网站,比如VC知识库(www.vckbase.com)和VC之路(有一本很好的教程,不过现在网站的东西都没了,正在恢复),另外www.csdn.net也是一个不错的地方。

 

5、几种Windows编程方法的辨析及其它

 

  很多初学者往往会将Windows编程和VC++混为一谈。打开VC++的新建项目,可以看到VC++支持很多种工程。包括命令行的,MFC的,还有就是Win32 Application,即SDK程序。使用VC++未必是编写SDK程序,编写SDK程序也未必要用VC++。编写Windows程序的方法也不止SDK一种,还包括使用类库如MFC,OWL,使用快速开发工具如VB,Delphi。这些方法各有各的用处。使用SDK无疑是最麻烦的了,我们学习SDK也并非是为了用它来编软件,虽然它可以,主要是为了对Windows编程有比较清晰的认识,这样你使用MFC时就可以做到“胸中自有沟壑”。

 

 

 

 

 

 

6、Windows SDK编程初探

第一章 Windows程序的框架

 

要点:程序的主函数,消息处理函数

 

     Windows程序具有相对稳定的结构,也就是说Windows程序是有一定的框架的,程序员要做的事情就是用特定的内容来填充这个框架。

 

     Windows程序的主函数:这个函数就像我们学习C语言时程序的主函数main()的功能是一样的,他代表了程序的入口。但是这个函数看上去比main()似乎繁的多,如果是第一次看见这个函数肯定会感觉一头雾水,但是不要紧我们来看看这个函数各个参数的意义,(其实开始的时候完全可以不理会他们的意义)hInstance是本实例的句柄,句柄可以理解为操作系统管理使用我们的应用程序的别名,它跟指针类似但又不同于指针,它的意义只有操作系统知道,也就是说操作系统通过hInstance就可以找到我们现在的这个程序。hPrevInstance是前一个实例的句柄。szCmdLine:是命令行参数,iCmdShow是窗口的显示方式。现在我们没有必要清除每个参数的具体意义,在接下来的学习中我们用的最多的就是hInstance这个参数,但也不多,而且我们使用vc++时,无论有哪种程序生成方式这个函数一般都会自动生成。

 

int WINAPI WinMain(HINSTANCEhInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)

 

     主函数是windows程序框架的主要部分,由于windows程序是基于消息处理的,所以消息处理函数也算作是程序框架的一部分。说到消息,我觉得从基本的c编程转到windows编程最难的一点可能就是理解windows消息机制,虽然说是机制但不必觉得高深莫测,其实很简单,举个例子来说吧:在一个应用程序中有一个按钮,当按钮被按下时,我们已经习惯的程序会产生一个动作,在这样一个简单的过程中大部分事情是操作系统替我们完成了,检测按钮的动作,并将这个动作表现出来:按钮的按下、起来;按钮被按下时它会向他所在的程序发送一个消息“我被按下了”,程序中有一个消息处理函数,捕捉到这个消息,接着转而处理它:也就是调用相关的函数。

 

     那么我们就接着看一下消息处理函数,消息处理函数其实是一个消息循环,是一个回调函数,什么是回调函数暂不管它,只管理解为,函数由你定义而不归你调用,是由操作系统来调用的。下面来看一下,消息处理函数的原型及其结构:

 

LRESULT CALLBACK WndProc(HWND hwnd,UINTmessage,WPARAM wParam,LPARAM lParam)

{

  switch(message)

     {

        case...

        case...//这些分支语句用来分别处理不同的消息

     }

returnDefWindowProc(hwnd,message,wParam,lParam);

/*这个函数是系统默认的消息处理函数,也就是说,我们的窗口程序的消息处理函数处理的只是我们感兴趣的消息,即上面的case语句,对于其他的消息我们还是使用系统默认的消息处理函数。我们的消息处理函数是要在我们的窗口主程序中登记的,登记为我们自定义的消息处理函数之后,系统的消息就有它来处理了。所以,在本函数的最后要使用该默认函数,否则其他的消息,本程序就无法处理了。*/

}

 

   了解了消息处理函数,我们继续来看程序的主函数,它是程序的容器,程序的主窗体要在其中建立,程序的消息处理函数也要在其中设置。在主体函数中我们要做的就是两件事,一件是注册窗口类,另外一件是建立窗口。所谓注册窗口类就是通过填写一个WNDCLASS结构,我们的窗口就算基本成型,然后要向系统注册(注册过程系统也提供了相应的函数,当然技术差不多了以后也可以自己写注册过程)。窗口注册完毕,接下来的任务就是真正的来建立这个窗口,建立的时候前面注册的窗口类的名称作为参数传入,当然该窗口有自定义的消息处理函数的话,这时也要将这个函数传入。

        这样,我们就了解了Windows程序的框架,现在我再给出一个比较经典的Windows SDK程序的例子来看看我们的框架。

 

 

Windowssdk基本结构

客户写一个消息处理函数,在窗口建立前,将消息处理函数与窗口关联。这样,每当有消息产生时,就会去调用这个消息处理函数。

  通常情况下,客户都不会处理全部的消息,而是只处理自己感兴趣的消息,其他的,则送回到系统的缺省消息处理函数中去。

LRESULT CALLBACK WndProc (HWND hwnd, UINTmessage, WPARAM wParam, LPARAM lParam)

{

switch (message)

{

case ...

...

case ...

...

}

return DefWindowProc (hwnd, message,wParam, lParam) ;

}

 

  三、窗口的建立

  客户需要自己建立窗口,建立后会得到系统返回的窗口句柄(HWND),后继的针对窗口的操作都针对句柄进行。

  1.注册窗口类

  建立窗口前,需要制定好这个窗口的相关属性,最主要的就是将自己定义的消息处理函数与窗口关联,其他的属性还包括:菜单、图标等等。

  这个属性指定步骤是通过指定"窗口类"来完成的。

  对于自己建立的窗口,这个"窗口类"需要自己制定,也即自己填充一个WNDCLASS结构,然后向系统注册。

  对于一些特殊窗口,如按钮等控件,他们的行为是系统制定好了的,所以不需要自己注册,直接使用对应的“窗口类”名称就行了。

  2.建立窗口

  建立窗口时,注册的"窗口类"名称作为参数传入。

  这样,当有针对该窗口的消息时,将调用“窗口类”中指定的消息处理函数,在其中得到处理。

 

  四、消息循环

  系统会将针对这个程序的消息依次放到程序的“消息队列”中,由程序自己依次取出消息,在分发到对应的窗口中去。因此,建立窗口后,将进入一个循环。

  在循环中,取出消息、派发消息,循环往复,直到取得的消息是退出消息。

  循环退出后,程序即结束。

#include "stdafx.h"

#include <windows.h>

//一、消息处理函数

//参数:窗口句柄,消息,消息参数,消息参数

LRESULT CALLBACK WndProc(HWND hwnd, UINTmessage, WPARAM wParam, LPARAM lParam)

{

 //处理感兴趣的消息

 switch (message)

 {

  case WM_DESTROY:

   //当用户关闭窗口,窗口销毁,程序需结束,发退出消息,以退出消息循环

   PostQuitMessage (0) ;

   return 0 ;

 }

 //其他消息交给由系统提供的缺省处理函数

 return ::DefWindowProc(hwnd, message, wParam, lParam) ;

}

 

//二、应用程序主函数

//参数:实例句柄、前一个实例的句柄、命令行参数、窗口显示方式

int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{

 //1.注册窗口类

 static TCHARszAppName[] = TEXT ("HelloWin") ; //窗口类名称

 //定制"窗口类"结构

 WNDCLASS wndclass ;

 wndclass.style =CS_HREDRAW | CS_VREDRAW ;

 wndclass.lpfnWndProc =WndProc ; //关联消息处理函数

 wndclass.cbClsExtra = 0;

 wndclass.cbWndExtra = 0;

 wndclass.hInstance =hInstance ; //实例句柄

 wndclass.hIcon =LoadIcon (NULL, IDI_APPLICATION) ; //图标

 wndclass.hCursor =LoadCursor (NULL, IDC_ARROW) ; //光标

 wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH); //画刷

 wndclass.lpszMenuName =NULL ;

 wndclass.lpszClassName= szAppName; //类名称

 //注册

 if (!RegisterClass(&wndclass))

 {

  MessageBox (NULL, TEXT("RegisterClass Fail!"),

  szAppName,MB_ICONERROR) ;

  return 0 ;

 }

 

 //建立窗口

 HWND hwnd ;

 hwnd = CreateWindow(szAppName, //窗口类名称

 TEXT ("The HelloProgram"), //窗口标题

 WS_OVERLAPPEDWINDOW, //窗口风格

 CW_USEDEFAULT,

 CW_USEDEFAULT,

 CW_USEDEFAULT,

 CW_USEDEFAULT,

 NULL,

 NULL,

 hInstance, //实例句柄

 NULL);

 

 ShowWindow (hwnd,iCmdShow) ;

 UpdateWindow (hwnd) ;

 

 //消息循环

 MSG msg ;

 while (GetMessage(&msg, NULL, 0, 0)) //从消息队列中取消息

 {

  TranslateMessage(&msg) ; //转换消息

  DispatchMessage(&msg) ; //派发消息

 }

 return msg.wParam ;

}

 

 

//example.cpp

#include //一定要包含该头文件

LRESULT CALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);//消息处理函数的声明,定义放在主函数后面

int WINAPI WinMain(HINSTANCEhInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)

{

  static TCHAR szAppName[]=TEXT("Hello");//注册的窗口类的名称,此处为"Hello"

  WNDCLASS wndclass;//定义了一个窗口类

  wndclass.style=CS_HREDRAW|CS_VREDRAW;

   wndclass.lpfnWndProc=WndProc;//此处关联了定义的消息处理函数

  wndclass.cbClsExtra=0;

  wndclass.cbWndExtra=0;

  wndclass.hInstance=hInstance;//实例句柄

  wndclass.hIcon=NULL;//窗口的图标,我们这里不设置

  wndclass.hCursor=LoadCursor(NULL,IDC_ARROR);//设置光标

  wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//画刷

  wndclass.lpszMenuName=NULL;

  wndclass.lpszClassName=szAppName;//类名称

 

  if(!RegisterClass(&wndclass))//注册窗口

     {

 

        MessageBox(NULL,TEXT("窗口注册失败"),szAppName,MB_ICONERROR);

        return 0;

     }

 

   //下面开始建立窗口

  HWND hwnd;

  hwnd=CreateWindow(szAppName,TEXT("The Hello Program"),

                                      CW_OVERLAPPEDWINDOW,

                                      CW_USEDEFAULT,

                                       CW_USEDEFAULT,

                                      CW_USEDEFAULT,

                                      CW_USEDEFAULT,

                                       NULL,

                                      hInstance,

                                       NULL);

 

  ShowWindow(hwnd,iCmdShow);

  UpdateWindow(hwnd);

   //接下来是消息循环,程序不断的从消息队列中取消息,让消息处理函数处理

  while(GetMessage(&msg,NULL,0,0))

   {

     TranslateMessage(&msg);

     DispatchMessage(&msg);

   }

  return msg.wParam;

}

//消息处理函数定义

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM)//此例子中我们只是处理简单的消息

{

  switch(message)

   {

     case WM_DESTROY:

           PostQuitMessage(0);

           return 0;

   }

  return ::DefWindowProc(hwnd,message,wParam,lParam);

}

 

 

 

 

 7、Windows SDK编程之建立控件

 

一、概述

 

  控件是子窗口,它们是系统已经定义好的窗口类,因此不需要注册、也不需要写消息处理函数。

 

  在主窗口得到WM_CREATE消息时,建立子窗口即可。

 

  二、实例

//参数:窗口句柄,消息,消息参数,消息参数

LRESULT CALLBACK WndProc(HWND hwnd, UINTmessage, WPARAM wParam, LPARAM lParam)

{

 //处理感兴趣的消息

 switch (message)

 {

  case WM_CREATE:

   CreateWindow(TEXT("BUTTON"),//控件"类名称"

   TEXT("按钮(&A)"),

   WS_CHILD | WS_VISIBLE|BS_PUSHBUTTON, 10, 10, 100, 100, hwnd, (HMENU)1000, //控件ID

((LPCREATESTRUCT) lParam)->hInstance, //实例句柄

NULL);

 

   return 0;

  case WM_DESTROY:

   //当用户关闭窗口,窗口销毁,程序需结束,发退出消息,以退出消息循环

   PostQuitMessage (0) ;

   return 0 ;

 }

 //其他消息交给由系统提供的缺省处理函数

 return :efWindowProc(hwnd, message, wParam, lParam) ;

}

 

  三、关于WM_CREATE消息

  WM_CREATE 的lParam参数将会传入一个建立时信息结构指针(LPCREATESTRUCT)。结构中包含了一些有用信息(窗口建立时的参数)。

 

typedef struct tagCREATESTRUCT {

 LPVOID lpCreateParams;

 HINSTANCE hInstance; //实例句柄

 HMENU hMenu;

 HWND hwndParent;

 int cy;

 int cx;

 int y;

 int x;

 LONG style;

 LPCTSTR lpszName;

 LPCTSTR lpszClass;

 DWORD dwExStyle;

} CREATESTRUCT, *LPCREATESTRUCT; 

四、控件与父窗口的协作

  1.控件上发生动作时,将向父窗口发送通知消息WM_COMMAND。

WM_COMMAND:

HIWORD(wParam):通知码(notification code)

LOWORD(wParam):控件ID

(HWND)lParam: 控件句柄 

 

  除了WM_COMMAND外,每种控件还有可能有其他的通知消息(如WM_DRAWITEM)。

 

  2.父窗口需要控制控件时,向控件发控件消息。

  事先应记录下控件句柄,或由ID获取控件句柄

 

  3.备注:

  各种控件的通知消码和控制消息可由

MSDN-> Platform SDK-> User InterfaceServices->Windows User Interface->Controls

  查得。

 

  五、控件"类名称"

  1.标准控件

  BUTTON :按钮

  COMBOBOX :复合框

  EDIT :编辑

  LISTBOX :列表

  RichEdit :Rich Editversion 1.0

  RICHEDIT_CLASS :RichEdit version 2.0

  SCROLLBAR :滚动条

  STATIC :静态

 

  2.外壳附带的公用控件

  注:建立前需要用InitCommonControlsEx进行初始化

INITCOMMONCONTROLSEX icex;// Ensure thatthe common control DLL is loaded.

icex.dwSize = sizeof(INITCOMMONCONTROLSEX);

icex.dwICC = ICC_LISTVIEW_CLASSES;

InitCommonControlsEx(&icex);

 

HWND hWndListView =CreateWindowEx(0,WC_LISTVIEW,//WC_LISTVIEW不需要加引号

TEXT(""),

WS_CHILD | WS_VISIBLE|WS_BORDER | LVS_ICON| LVS_EDITLABELS | WS_EX_CLIENTEDGE ,

10,

10,

100,

100,

hwnd,

(HMENU)1000, //控件ID

((LPCREATESTRUCT) lParam)->hInstance, //实例句柄

NULL);

}

ANIMATE_CLASS

DATETIMEPICK_CLASS

HOTKEY_CLASS

MONTHCAL_CLASS

PROGRESS_CLASS

REBARCLASSNAME

STATUSCLASSNAME

TOOLBARCLASSNAME

TOOLTIPS_CLASS

TRACKBAR_CLASS

UPDOWN_CLASS

WC_COMBOBOXEX

WC_HEADER

WC_IPADDRESS

WC_LISTVIEW

WC_PAGESCROLLER

WC_TABCONTROL

WC_TREEVIEW

 

  3.特殊窗口

  MDIClient :MDI客户区窗口

ComboLBox :The class for the list boxcontained in a combo box.

 

DDEMLEvent :Windows NT/2000: The class forDDEML events.

Message :Windows 2000: The class for amessage-only window.

#32768 :The class for a menu.

#32769 :The class for the desktop window.

#32770 :The class for a dialog box.

#32771 :The class for the task switchwindow.

#32772 :Windows NT/2000: The class for icontitles. 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值