SDK(API)入门
今天我也来冒个泡~ 嘿.. 好了废话不多少 我们现在就开始进入SDK的学习.1.必须了解的内容
SDK是Software Development Kit 的缩写,中文意思就是“软件开发工具包”,学习SDK编程就不得不提到API函数了。
在SDK编程中就是直接调用API函数进程编程。到这里肯定会有朋友问那什么是API呢?API其实就是应用程序编程接口,
英文全称是Application Programming Interface,我们可以把它想象成一个程序库,提供各式各样的与windows系统服务
有关的函数,这样有利用理解.由于API函数众多,详细的去了解每一个API函数是没必要的,我们只需要知道那些功能由
哪些API函数提供就行了。所以我建议大家在学习的过程中去安装一部MSDN。
[table=72%,#ffffff]
[tr]
[td=1,1,97%]
[table]
[tr]
[td]2.VC++的基本使用
在这里我使用的是VISUAL C++ 6.0,如果在座的朋友没有使用过VC++的话,相信看过本节后也能快速
的掌握VC++6.0的基本使用方法。
windows支持两种类型的程序:一种是基于图形用户界面(Graphic User Interface,简称GUI)的窗口应用程序,
这是大家常见的windows应用程序;另一种是基于控制台用户的界面(Console User Interface,简称CUI)的应用程序,
即DOS界面的应用程序。控制台的应用程序也属于windows程序,所以它也可以去使用API函数,下面我们就开始在控制台
编程环境下了解下API的使用吧.
运行VC++6.0,选择菜单“文件”,然后点击”新建“,在“工程”里选择"Win32 Console Application"(这就是创建控
制台程序了,如果需要创建SDK程序就选择Win32 Application,在后面的章节 我会讲到),输入了工程名后,就点击确定,
接着出现了一个对话框,我们选择”一个简单程序“。基本步骤完成了,我们开始写代码吧。
使用API函数需要添加相应的头文件,一般的API函数使用"windows.h"这个头文件。添加好头文件后,我们就可以使用
API了。在大多数C语言的书中,大家可能会记得“Hello World”这个非常经典的程序,现在我给大家也来个API版的“Hello World”
吧,嘿嘿..。我们在main函数中写入MessageBox(NULL,"Hello World!","hello",MB_OK);,然后点击那个"红色的感叹号",
或者是快捷键"Ctrl+F5"便可以运行,看到了吧,一个对话框。我就来给大家讲解下MessageBox这个API函数吧。MessageBox
是众多API函数中的一个,它声明在"windows.h"中,用于一个指定风格的对话框。我们来看看MessageBox函数的声明原型吧
int MessageBox(
HWND hWnd, // handle to owner window
LPCTSTR lpText, // text in message box
LPCTSTR lpCaption, // message box title
UINT uType // message box style
);
第一个参数hWnd:标识将被创建的消息框的拥有窗口。如果此参数为NULL,则消息框没有拥有窗口。
第二个参数lpText:指向一个以NULL结尾的、含有将被显示的消息的字符串的指针。
第三个参数lpCaption:指向一个以NULL结尾的、用于对话框标题的字符串的指针。
第四个参数uType:指定一个决定对话框的内容和行为的位标志集。此参数可以为下列标志组中标志的组合。
要了解API的详细使用方法,请看MSDN。
现在对VC++6.0和API有一些认识了吧,好了我们进入下一步学习。
3.SDK的初步学习
本节将学习GUI程序的编写。
上回我们写的程序是控制台的,这回我们就来了解GUI程序的编写吧。要学会GUI的程序编写,首先我们得知道什么是Windows界面
程序。
在图形化的基于视窗的应用程序里,窗口就是屏幕上的一块区域。在这块区域中。应用程序取得用户的输入,显示用户的输出。因此
GUI程序的首要任务就是创建一个窗口。
每个GUI程序至少要创建一个窗口,称主窗口,它作为用户与应用程序间的主界面来提供服务。大多数应用程序也直接或间接的创建
其他窗口,来完成与主窗口相关的工作。
应用程序的主窗口包括 标题栏,菜单栏,最小化按钮,最大化按钮,关闭按钮,窗口客户区。如下图所示。
现在我们就开始写GUI窗口程序吧,按照上回的步骤我们选择"Win32 Application",然后选择"一个空的工程",单击完成.然后我们新建一个
C++的文本文件,如下图所示.
我先把代码写进去吧,待会逐步分析。
#include <windows.h>
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char szClassName[] = "MainWClass";
WNDCLASSEX wndclass;
// 用描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); // 结构的大小
wndclass.style = CS_HREDRAW|CS_VREDRAW; // 指定如果大小改变就重画
wndclass.lpfnWndProc = MainWndProc; // 窗口函数指针
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 = szClassName ; // 窗口类的名称
wndclass.hIconSm = NULL; // 没有类的小图标
// 注册这个窗口类
RegisterClassEx(&wndclass);
// 创建主窗口
HWND hwnd = CreateWindowEx(
0, // dwExStyle,扩展样式
szClassName, // lpClassName,类名
"My first Window!", // lpWindowName,标题
WS_OVERLAPPEDWINDOW, // dwStyle,窗口风格
CW_USEDEFAULT, // X,初始 X 坐标
CW_USEDEFAULT, // Y,初始 Y 坐标
CW_USEDEFAULT, // nWidth,宽度
CW_USEDEFAULT, // nHeight,高度
NULL, // hWndParent,父窗口句柄
NULL, // hMenu,菜单句柄
hInstance, // hlnstance,程序实例句柄
NULL) ; // lpParam,用户数据
if(hwnd == NULL)
{
MessageBox(NULL, "创建窗口出错!", "error", MB_OK);
return -1;
}
// 显示窗口,刷新窗口客户区
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// 从消息堆中取出消息
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
// 转化键盘消息
TranslateMessage(&msg);
// 将消息发送到相应的窗口函数
DispatchMessage(&msg);
}
// 当GetMessage返回0时程序结束
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
char szText[] = "最简单的窗口程序";
switch (message)
{
case WM_PAINT: // 窗口客户区需要重画
{
HDC hdc;
PAINTSTRUCT ps;
// 使无效的客户区变的有效,并取得设备环境句柄
hdc = BeginPaint (hwnd, &ps) ;
// 显示文字
TextOut(hdc, 10, 10, szText, strlen(szText));
EndPaint(hwnd, &ps);
return 0;
}
case WM_DESTROY: // 正在销毁窗口
// 向消息队列投递一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
PostQuitMessage(0) ;
return 0 ;
}
// 将我们不处理的消息交给系统做默认处理
return DefWindowProc(hwnd, message, wParam, lParam);
}
在讲解之前,我来给大家讲下什么是句柄.
句柄是一个(通常为32位的)整数,它代表一个对象。Windows中的句柄类似传统C或者MS-DOS程序设计中使用的文件句柄。
程序几乎总是通过呼叫Windows函数取得句柄。程序在其它Windows函数中使用这个句柄,以使用它代表的对象。
代号的实际值对程序来说是无关紧要的。但是,向您的程序提供代号的Windows模块知道如何利用它来使用相对应的对象。
标识符 含义
HINSTANCE 执行实体(程序自身)句柄
HWND 窗口句柄
HDC 设备内容句柄
句柄的介绍就先到这里吧.
大家可能会发现程序的入口怎么不是main函数而是WINMain函数。这里我给大家说下,GUI应用程序的入口函数
WinMain. APIENTRY是_stdcall的宏定义,说明WinMain函数是采用Windows标准调用方式。我们来看下WINMAIN函数
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
系统传递给WinMain函数的几个参数如下:
hInstance 指定了当前模块句柄。
hPrevInstance 是WIN16留下的废物,现在已经不用了
hPrevInstance 是命令行参数。
nCmdShow 指定了窗口初始化的显示方式
接下来我来讲解下窗口创建的过程,
(1)设计一个窗口类;
(2)注册窗口类;
(3)创建窗口;
(4)更新及显示窗口。
下面我来对上面的代码一一对应的讲解这些过程。
(1)设计一个窗口类;
这个过程的代码就是这一段
WNDCLASSEX wndclass;
// 用描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); // 结构的大小
wndclass.style = CS_HREDRAW|CS_VREDRAW; // 指定如果大小改变就重画
wndclass.lpfnWndProc = MainWndProc; // 窗口函数指针
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 = szClassName ; // 窗口类的名称
wndclass.hIconSm = NULL; // 没有类的小图标
一个完整的窗口具有许多特征,包括光标,图标,背景色等.
所以我们在创建一个窗口前,要对它进行设计。我们在设计一个窗口时,
WINDOWS已经为我们提供好了一些窗口的基本属性,我们只需要将它填好就可以了。
这些属性都在WNDCLASSEX这类当中 我们来看看它的结构吧
typedef struct _WNDCLASSEX {
UINT cbSize; //指定WNDCLASSEX的大小
UINT style; //从这个窗口类派生的窗口具有的风格
WNDPROC lpfnWndProc;// 即 windows procedure 窗口消息处理函数指针
int cbClsExtra; // 指定紧跟在窗口类结构的附加字节数
int cbWndExtra; // 指定紧跟在窗口实例的附加字节数
HINSTANCE hInstance; // 本模块的实例句柄
HICON hIcon; // 标题栏上的图标句柄
HCURSOR hCursor; // 光标句柄
HBRUSH hbrBackground; // 背景色刷的句柄
LPCTSTR lpszMenuName; // 菜单句柄
LPCTSTR lpszClassName; // 该窗口类的名称
HICON hIconSm; // 小图标句柄
} WNDCLASSEX, *PWNDCLASSEX;
【1】指定窗口的风格。
wndclass.style = CS_HREDRAW|CS_VREDRAW; // 指定如果大小改变就重画
CS_HREDRAW|CS_VREDRAW风格指定了如果窗口客户区的大小改变了,则重画整个窗口
【2】指定窗口消息处理函数地址
wndclass.lpfnWndProc = MainWndProc;
WNDCLASSEX结构的成员lpfnWndProc指定了基于此类的窗口的窗口函数,当窗口收到消息时,都交给次函数处理
这个函数就是我们事先定义好了的
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
好了剩下的我就不一一解释了 上面都有注释 大家可以对照着看。
(2)注册窗口类;
窗口类定义完了,我们就开是注册了,
// 注册这个窗口类
RegisterClassEx(&wndclass);
注册类用到API RegisterClassEx
(3)创建窗口;
HWND hwnd = CreateWindowEx(
0, // dwExStyle,扩展样式
szClassName, // lpClassName,类名
"My first Window!", // lpWindowName,标题
WS_OVERLAPPEDWINDOW, // dwStyle,窗口风格
CW_USEDEFAULT, // X,初始 X 坐标
CW_USEDEFAULT, // Y,初始 Y 坐标
CW_USEDEFAULT, // nWidth,宽度
CW_USEDEFAULT, // nHeight,高度
NULL, // hWndParent,父窗口句柄
NULL, // hMenu,菜单句柄
hInstance, // hlnstance,程序实例句柄
NULL) ; // lpParam,用户数据
创建窗口用到 CreateWindowEx 函数 它返回一个HWND句柄 也就窗口句柄 函数的参数我就讲了 这里有注释
更详细的请看MSDN.
(4)更新及显示窗口。
在桌面显示窗口
ShowWindow(hwnd, nCmdShow);
更新窗口
UpdateWindow(hwnd);
这样一个窗口就完成了 剩下的就是消息循环和消息处理了。
无限消息循环:
// 从消息堆中取出消息
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
// 转化键盘消息
TranslateMessage(&msg);
// 将消息发送到相应的窗口函数
DispatchMessage(&msg);
}
首先我们定义一个MSG结构 用于填充消息的
这是MSG的属性
typedef struct tagMSG {
HWND hwnd; //消息要发送的窗口句柄
UINT message;//消息标识符,以WM_开头
WPARAM wParam;//消息参数之一
LPARAM lParam; //消息参数之一
DWORD time; //消息放入队列的时间
POINT pt; //POINT结构表示放入消息队列时鼠标的位置
} MSG, *PMSG;
然后用while(GetMessage(&msg, NULL, 0, 0))无限循环来获取消息
GetMessage如果获取的不是WM_QUIT消息,侧返回非0值,继续进行消息循环,如果是WM_QUIT消息,
则返回0值,从而结束消息循环,程序就退出了。
TranslateMessage(&msg);//这个函数把键盘输入的消息翻译成可以传递的消息
DispatchMessage(&msg);//DispatchMessage把消息分发给消息处理函数处理.
到程序最后一部分了 消息处理:
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
char szText[] = "最简单的窗口程序";
switch (message)
{
case WM_PAINT: // 窗口客户区需要重画
{
HDC hdc;
PAINTSTRUCT ps;
// 使无效的客户区变的有效,并取得设备环境句柄
hdc = BeginPaint (hwnd, &ps) ;
// 显示文字
TextOut(hdc, 10, 10, szText, strlen(szText));
EndPaint(hwnd, &ps);
return 0;
}
case WM_DESTROY: // 正在销毁窗口
// 向消息队列投递一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
PostQuitMessage(0) ;
return 0 ;
}
// 将我们不处理的消息交给系统做默认处理
return DefWindowProc(hwnd, message, wParam, lParam);
}
这个函数将接收消息
这里一般用 switch case结构来处理函数接收到了什么消息,如何处理消息. 剩下的所有不处理
的消息都交给DefWindowProc(hwnd, message, wParam, lParam);函数让WINDOWS默认处理。
我们来看看 WM_PAINT消息
这个消息在Windows程序设计中是很重要的。当窗口显示区域的一部分显示内容或者全部变为「无效」,
以致于必须「更新画面」时,将由这个消息通知程序。
TextOut(hdc, 10, 10, szText, strlen(szText));//这个函数用于显示文字
WM_DESTROY消息
当窗口关闭时,消息处理函数会接收到WM_DESTROY消息
然后使用PostQuitMessage(0) ;函数让WINMIAN函数结束.
就到这里吧 写的不够详细 如果想继续学习的话 可以看《WINDOWS程序设计》
现在在学汇编 有时间弄个WIN32汇编的教程 嘿嘿.. 我一直想学习api应用,总听人说api多么多么强大,可是我又不知道如何去学习,非常感谢楼主分享如此详细的帖子,就从这里开始 话说API是个蛮难理解的存在。。。 O(∩_∩)O哈哈~ 又学习了
一直是学 java 的,可以 比较比较 非常不错。 我最近再看着一个! 框架程序的窗口也是这样写出来的吗!
页:
[1]
