WIN32 SDK界面编程
在介绍win32 sdk界面编程,先需要了解win32 编程。熟悉win32编程之后,就可以轻松进行win32 界面编程。
一、什么是win32 编程
Win32编程,指的是用Window提供的API(Application Programming Interface)为Window编写应用程序。 之所以称之为Win32,是因为现在的Window都是32位的(现在已经有64位的吧!但是最普遍是32位).win32 是指Window都是32位的操作系统,例如98、XP、2000、2003等操作系统, win32编程就是在这些系统下的编程 ,运用Window提供的API(Application Programming Interface)为Window编写应用程序。
win32编程可以用C来完成,主要是通过windows的API来工作.但是API上千个,想全部掌握很难,建议安装一个MSDN随时查看.书籍方面又Petzeld的Windows程序设计,上下两册,讲的比较全面,但是内容很多. 建议你先学C++,估计你是对控制台那个黑屏厌烦的,但是进入windows后你会发现,它比DOS的还烦!Win32编程,指的是用Window提供的API(Application Programming Interface)为Window编写应用程序。 之所以称之为Win32,是因为现在的Window都是32位的(现在已经有64位的吧!但是最普遍是32位)。大家都知道,Window是由GDI.DLL、USER.DLL、KERNEL.DLL三大主要部分组成的。那么学习Win32编程的大部分(特别是应用程序界面部分的编程)是用这三个DLL(Dynatic Linked Library)动态链接库子程序形式提供的API函数。
首先:你必须有编程的经验。这里的经验不是指传统的DOS下的字符模式下的编程。大家都知道,Window是图形操作系统、同时也多任务抢占式(理解它很重要),它是在图形模式下工作。当然你编程得服从于它。但是正 是因为这个,Window的编程模式就和DOS不一样。所有你得有DOS下编程的经验,但是还得转变为WINDOW下的编程方式。因为两个系统的编程一个是过程化的。即程序从上到下,顺序执行。而另一个是,事件驱动的。要明白这个,才会体验到Window的博大精深。
事件驱动:我们知道DOS下程序是顺序执行的。至少它是按着你指定的路径或条件执行的。尽管可能会在某些条件下跳转,但是基本上是在你(程序的掌握之中),但是在事件驱动中,你只需考虑到可能出现的情况,并对这些情况做相应的处理。当Window执行你的程序时,它会检测是否发生了你考虑的那些事情是否发生,如果发生了某件事情(比如你用鼠标单击),它会给你的程序发送相应的消息(所以叫做消息驱动,这里对就鼠标的消息是WM_MOUSELDOWN等)。windows操作系统是靠消息的驱动的,所有的事件都被封装为各种各样的消息,系统和其他程序通过接受消息,分析消息附带的参数,再分别进行相关的处理,然后完成相关的任务。不管用什么语言,或者什么开发工具,只要是在windows下可以运行的程序,在他的本质上都有一个接受消息、处理消息的循环。这就是win32程序乃至整个windows操作系统本身的运做本质。
学习WIN32需要看那些资料,这里推荐《windows程序设计》、《windows api参考大全》、《windows核心编程》、MSDN。
二、怎样使用API写Windows程序
1、先来看个简单实例:
#include "windows.h"
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
MessageBox (NULL, TEXT ("你好,欢迎来到VC之路"), TEXT ("欢迎"), 0) ;
return 0 ;
}
第一个参数:应用程序的当前实例句柄。
第二个参数:应用程序的前一个实例句柄,别管它,对于Win32位而言,它一般是NULL.
第三个参数:指向任何传给程序的命令行参数。PSTR代表"指向字符串的指针"。
第四个参数:它告诉应用程序如何初始化窗口,如最大化,最小化等状态。
WinMain()所起的作用:初始化,展示,销毁应用程序等。
2、消息机制
#include "stdafx.h" //注意,这个向导产生的头文件不能去掉
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wc ;
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.lpfnWndProc = WndProc ;
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
wc.hInstance = hInstance ;
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wc.lpszMenuName = NULL ;
wc.lpszClassName = szAppName ;
if (!RegisterClass (&wc))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ("欢迎你的到来!"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, TEXT ("你好,欢迎你来到VC之路!"), -1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
3、Windows编程的特点
C语言编程至少有一个主程序,其名字是main()。Windows程序则至少两个主程序,一个是WinMain(),
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
);
另一个是窗口过程函数WndProc,它的函数原型为:
long FAR PASCAL WndProc(HWND hWnd,WORD message,WORD wParam,LONG lParam);
Windows应用程序的编程就围绕这两个部份进行的。其中WinMain函数为应用程序的入口点,它的名字一定要是WinMain。
在Windows中,应用程序通过要求Windows完成指定操作,而承担这项通信任务的API函数就是Windows的相应窗口函数WndProc。在dos里,程序能直接控制事件的发生顺序,结果等。而在Windows里,应用程序不直接调用任何窗口函数,而是等待Windows调用窗口函数,请求完成任务或返回信息。为保证Windows调用这个窗口函数,这个函数必须先向Windows登记,然后在Windows实施相应操作时回调,所以窗口函数又称为回调函数。WndProc是一个主回调函数,Windows至少有一个回调函数。
回调函数WndProc在哪里定义的呢,请看这个语句:wc.lpfnWndProc = WndProc .
我把这个程序支解为四块:
(一)建立注册窗口类.
(二)创建窗口.
(三)显示和更新窗口.
(四)创建消息循环.
(五)终止应用程序.
(六)窗口过程.
(七)处理消息.
(一)注册窗口类:
(1)建立窗口类
WinMain()是程序的入口,它相当于一个中介人的角色,把应用程序(指小窗口)介绍给windows.首要的一步是登记应用程序的窗口类.
窗口种类是定义窗口属性的模板,这些属性包括窗口式样,鼠标形状,菜单等等,窗口种类也指定处理该类中所有窗口消息的窗口函数.只有先建立窗口种类,才能根据窗口种类来创建Windows应用程序的一个或多个窗口.创建窗口时,还可以指定窗口独有的附加特性.窗口种类简称窗口类,窗口类不能重名.在建立窗口类后,必须向Windows登记.
建立窗口类就是用WNDCLASS结构定义一个结构变量,在这个程序中就是指WNDCLASS wc ;然后用自己设计的窗口属性的信息填充结构变量wc的域.
要WinMain登记窗口类,首先要填写一个WNDCLASS结构,其定义如下所示:
typedef struct _WNDCLASSA
{
UINT style ; //窗口类风格
WNDPROC lpfnWndProc ; //指向窗口过程函数的指针
int cbClsExtra ; //窗口类附加数据
int cbWndExtra ; //窗口附加数据
HINSTANCE hInstance ; //拥有窗口类的实例句柄
HICON hIcon ; //最小窗口图标
HCURSOR hCursor ; //窗口内使用的光标
HBRUSH hbrBackground ; //用来着色窗口背景的刷子
LPCSTR lpszMenuName ; //指向菜单资源名的指针
LPCSTR lpszClassName ; // 指向窗口类名的指针
}
在VC6.0里面,把光标定位在WNDCLASS上,按F1,即可启动MSDN,在MSDN里你可看到这个结构原形.在下节讲解这些参数在本程序中的具体用法.
(2)注册窗口类
(1)第一个参数:成员style控制窗口的某些重要特性,在WINDOWS.H中定义了一些前缀为CS的常量,在程序中可组合使用这些常量.也可把sytle设为0.本程序中为wc.style = CS_HREDRAW | CS_VREDRAW,它表示当窗口的纵横坐标发生变化时要重画整个窗口。你看:无论你怎样拉动窗口的大小,那行字都会停留在窗口的正中部,而假如把这个参数设为0的话,当改动窗口的大小时,那行字则不一定处于中部了。
(2)第二个参数:lpfnWndProc包括一个指向该窗口类的消息处理函数的指针,此函数称为窗口过程函数。它将接收Windows发送给窗口的消息,并执行相应的任务。其原型为:
long FAR PASCAL WndProc(HWND ,unsigned,WORD,LONG);并且必须在模快定义中回调它。WndProc是一个回调函数(见第五节),如果暂时无法理解这个模糊的概念意味着什么,可先放过,等到讲消息循环时再详谈。
(3)第三,四个参数:cbWndExtra域指定用本窗口类建立的所有窗口结构分配的额外字节数。当有两个以上的窗口属于同一窗口类时,如果想将不同的数据和每个窗口分别相对应。则使用该域很有用。这般来讲,你只要把它们设为0就行了,不必过多考虑。
(4)第五个参数:hInstance域标识应用程序的实例hInstance,当然,实例名是可以改变的。wc.hInstance = hInstance ;这一成员可使Windows连接到正确的程序。
(5)第六个参数:成员hIcon被设置成应用程序所使用图标的句柄,图标是将应用程序最小化时出现在任务栏里的的图标,用以表示程序仍驻留在内存中。Windows提供了一些默认图标,我们也可定义自己的图标,VC里面专有一个制作图标的工具。
(6)第七个参数: hCursor域定义该窗口产生的光标形状。LoadCursor可返回固有光标句柄或者应用程序定义的光标句柄。IDC_ARROW表示箭头光标.
(7)第八个参数:wc.hbrBackground域决定Windows用于着色窗口背景的刷子颜色,函数GetStockObject返回窗口的颜色,本程序中返回的是白色,你也可以把它改变为红色等其他颜色.试试看
(8)第九个参数:lpszMenuName用来指定菜单名,本程序中没有定义菜单,所以为NULL。
(9)第十个参数:lpszClassName指定了本窗口的类名。
当对WNDCLASS结构域一一赋值后,就可注册窗口类了,在创建窗口之前,是必须要注册窗口类的,注册窗口类用的API函数是RegisterClass,注册失败的话,就会出现一个对话框如程序所示,函数RegisterClass返回0值,也只能返回0值,因为注册不成功