分类:
2006-06-14 12:45:13
当我们使用着漂亮的界面,方便快捷的应用程序的时候。我们才会发现,以前曾编写的程序是多么的粗糙(TC编写的程序)。简单的界面,16色的显示系统,大大的落后于计算机的发展。简单的说就是杀鸡用牛刀。如何该改变这种情况呢?Microsoft公司在推出windows操作系统的时候给出了简单易行的解决方案。这就是WINDOWS平台API应用程序接口。当然API也是发展的,它从WIN 16 API发展到了现在普遍使用的WIN 32 API。只有充分理解API函数功能和用法,才能深入到WINDOWS系统的内部,才能充分挖掘出操作系统给我们提供的强大功能。现在就让我们放弃那DOS应用程序,进入WINDOWS编程的海洋之中吧。
要想了解WINDOWS API那么我们必须先了解WINDOWS下的程序是如何进行驱动的。同学们可以很清楚的发现到,当你在使用WINDOWS记事本的时候,当键盘输入字符的时候字就会出现在屏幕上。当你移动鼠标的时候,光标就会在屏幕上移动。双击鼠标、单击鼠标就会有相应的事件发生。这些都是由于WINDOWS具有的事件驱动的属性造成的。比如说当你按下键盘的字符键的时候,消息队列就会向程序发送WM_CHAR的消息,如果你所写的程序中含有处理这个消息的函数,程序就会执行它。
为了更好的了解WINDOWS编程,这里我必须介绍几个基本的概念:
1,句柄:它是WINDOWS编程的基础。一个句柄是指WINDOWS在内存中使用的一个唯一的整数质,是一个4个字节长的数值,用于标识应用程序中不同对象和相同对象的不同实例。
这里我列出几种WINDOWS常用的句柄:
HWND: 标示窗口句柄
HINSTANCE:标示当前实例句柄
HCOURSOR:标示光标句柄
HFONT: 标示字体句柄
HPEN:标示画笔句柄
HBRUSH:标示画刷句柄
HDC:标示设备环境句柄
HBITMP:标示位图句柄
HICON:标示图标句柄
HMENU:标示菜单句柄
HFILE:标示文件句柄
由于WINDOWS应用程序利用WINDOWS消息来与其它的WINDOWS应用程序及WINDOWS系统进行消息交换。所以消息是一个十分重要的对象它的结构如下。
typedef struct{
HWND hwnd; //检索消息的窗口句柄
UNIT message; //代表一个消息的消息质
WPARAM wParam; //消息附加信息的字参数
LPARAM lParam; //消息附加信息的长字参数
DWORD time; //消息入队时间
POINT pt; //消息发送时鼠标的位置 point.x;point.y;
} tagMSG;
2,消息:VC++中消息都用前缀标示消息所属的分类,下面我来介绍一下这些前缀
BM表示按钮控制消息
CB表示组合框控制消息
DM表示默认下压式按钮控制消息
EM表示编辑控制消息
LB表示列表框控制消息
SBM表示滚动条控制消息
WM表示窗口消息
现在我来对系统常用的一些消息进行说明:
1,WM_LBUTTONDOWN: 单击鼠标左键时产生
2,WM_LBUTTONUP: 放开鼠标左键时产生
3,WM_RBUTTONUP: 放开鼠标右键时产生
4,WM_LBUTTONBLCLK: 双击鼠标左键时产生
5,WM_RBUTTONBLCLK: 双击鼠标右键时产生
6,WM_KEYDOWN: 按下了一个非系统键时产生的消息
7,WM_CHAR: 同上
8,WM_CREATE: 由CreateWindow函数发出的消息
9,WM_DESTROY: 消除窗口时发出的消息
10,WM_QUIT: 退出程序时发送的消息
11,WM_PAINT: 做任何移动操作时发出的消息
介绍了以上的这些基础入门知识,我们就可以简单的了解一下WINDOWS API 程序的组成基本结构。它是由入口函数WinMain和窗口函数基本框架,并包含各种数据类型、数据结构与函数等应用组建组成的。其中入口函数WinMain和窗口函数是WINDOWS应用程序的主体。
一个基本的WinMain函数应该具有以下的功能:
1,注册窗口类,建立窗口及执行其他必要的初始化工作
2,进入消息循环,根据从应用程序消息队列接受的消息,调用相应的处理过程。
3,当消息循环检索到WM_QUIT消息时中止程序运行
WinMain函数有三个基本组成部分:函数说明、初始化和消息循环。
(1)函数说明
int WINAPI WinMain
(
HINSTANCE hThisInst, //应用程序当前实例句柄
HINSTANCE hPrevInst, //应用程序其它实例句柄
LPSTR lpszCmdLine, //指向程序命令行参数的指针
int nCmdShow //应用程序开始执行时窗口显示方式的整数值标示
)
(2)初始化
初始化包括窗口类的定义、注册、创建窗口实例和显示窗口四部分。(在以后的程序中我将详细的介绍它们具体的实现方法)
(3)消息循环
WINDOWS应用程序的运行是以消息为核心的。WINDOWS将产生的消息放入应用程序的消息队列中,而应用程序的WinMain函数从消息循环提取队列中的消息,并将其传递给窗口函数的相应过程处理。
它的基本写法如下:
MSG Meg;//定义消息
//(...)省略了一些内容
while (GetMessage(&Meg,NULL,0,0)
{
TranslanteMessage(&Meg);
DispatchMessage(&Meg);
}
本人水平有限请大家见谅。
在上一篇中我着重介绍了WINDOWS API32程序的基本结构框架,您一定想完成自己的第一个WINDOWS程序吧?别忙我先向您介绍一下API的窗口函数,只有了解它您才能进行编程。
什么是窗口函数呢?它又定义了什么呢?窗口函数定义了应用程序对接受到的不同消息的响应,其中包含了应用程序对各种可能接受到的消息的处理过程,是消息处理分支控制语句的集合。一般来说,窗口函数由一个或多个switch语句组成。每一个case语句对应一种消息,当应用程序接受到一个消息时,在窗口函数内的相应的case语句就会被激活并执行相应的响应程序模块。
简单的说窗口函数就是应用程序处理接受到的消息的函数,其中包含了应用程序对各种可能接受到的有用的消息的处理过程。
窗口函数的一般格式是这样的:
LRESULT CALLBACK WndProc
( HWND hwnd, //窗口句柄
UNIT message, //代表所处理消息的消息值
WPARAM wParam, //消息的附加参数(1)
LPARAM lParam //消息的附加参数(2)
)
{
... //省略
switch(message) //message为标识消息的消息值
{
case...
...
break;
...
case WM_DESTROY:
PostQuitMessage(0);
default:
return DefWindowProc(hwnd,message,wParam,lParam);
}
return(0);
}
窗口函数主体内容是消息处理语句,它由多个case语句组成。您只需要将窗口可能接收到的消息在case语句中编写相应的处理程序段就可以了。
在case语句的消息处理程序段中一般都有对消息WM_DESTROY的处理。这个消息是关闭窗口时发出的。一般情况下,应用程序调用函数PostQuitMessage响应这条消息。PostQuitMessage函数的定义如下:
void PostQuitMessage(int nExitCode); //nExitCode为应用程序退出代码
在处理case语句中不包含的信息时我们用这个默认处理:
return DefWindowProc(hwnd,message,wParam,lParam);
来保证所有发送到窗口的消息都得到了应有的处理。
除了了解窗口函数的基本结构,我们还要掌握一些基本WINDOWS程序的数据结构
(1)MSG,前文已介绍过了
(2)WNDCLASS
结构WNDCLASS包含一个窗口类的全部信息。应用程序通过定义一个窗口类来确定窗口的属性。它的定义如下:
typedef struct tagWNDCLASS
{
UNIT style; //窗口的样式,一般为0
WNDPROC lpfWndProc; //指向窗口函数的指针
int cbClsExtra; //分配在窗口类结构后的字节数
int cbWndExtra; //分配在窗口实例后的字节数
HINSTANCE hInstance; //定义窗口类的应用程序的实例句柄
HICON hIcon; //窗口类的图标
HCURSOR hCursor; //窗口类的光标
HBRUSH hbrBackground; //窗口类的背景刷
LPCSTR lpszMenuName; //窗口类的菜单资源名
LPCSTR lpszClassName; //窗口类名
} WNDCLASS;
现在我就可以教您写出自己的第一个WINDOWS程序(点击此处下载)
#include
//窗口函数说明
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
//初始化窗口类
//WinMain函数说明
int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd ;
MSG Msg ;
WNDCLASS wndclass ;
char lpszClassName[] = "窗口"; //窗口类名
char lpszTitle[]= "My_Windows"; //窗口标题名
//窗口类的定义
wndclass.style = 0; //窗口类型为缺省类型
wndclass.lpfnWndProc = WndProc ; //窗口处理函数为WndProc
wndclass.cbClsExtra = 0 ; //窗口类无扩展
wndclass.cbWndExtra = 0 ; //窗口实例无扩展
wndclass.hInstance = hInstance ; //当前实例句柄
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION) ;
//窗口的最小化图标为缺省图标
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW) ;
//窗口采用箭头光标
wndclass.hbrBackground = GetStockObject( WHITE_BRUSH) ;
//窗口背景为白色
wndclass.lpszMenuName = NULL ; //窗口中无菜单
wndclass.lpszClassName = lpszClassName ; //窗口类名为"窗口示例"
//窗口类注册
if( !RegisterClass( &wndclass)) //如果注册失败则发出警告声音
{
MessageBeep(0) ;
return FALSE ;
}
//创建窗口
hwnd=CreateWindow(lpszClassName, //窗口类名
lpszTitle, //窗口实例的标题名
WS_OVERLAPPEDWINDOW, //窗口的风格
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口左上角坐标为缺省值
CW_USEDEFAULT,
CW_USEDEFAULT,, //窗口的高和宽为缺省值
NULL, //此窗口无父窗口
NULL, //此窗口无主菜单
hInstance, //创建此窗口的应用程序的当前句柄
NULL) ; //不使用该值
//显示窗口
ShowWindow( hwnd, nCmdShow) ;
//绘制用户区
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)
{
switch(message)
{
case WM_DESTROY:
PostQuitMessage(0); //调用PostQuitMessage发出WM_QUIT消息
default: //默认时采用系统消息默认处理函数
return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}
您的程序成功了吗?在下一章我将向您介绍WINDOWS绘图。
由于上一章的文章中我没有向大家介绍清楚初试化的具体实现,造成很多的读者无法很好的理解,这是我的失误。本人现在补上,请大家原谅。
一个Windows API程序的初始化主要分为为四个部分。1、窗口类的定义2、窗口类的注册3、创建窗口实例4、显示窗口
①窗口类定义
在Windows应用程序中,窗口类定义了窗口的形式与功能。它的定义过程通过给窗口类数据结构WNDCLASS赋值来完成,这个数据结构包含窗口类的各个属性。窗口类的定义常用到以下几个函数,在这里一一介绍。
1、LoadIcon函数
LoadIcon函数的作用是在应用程序中加载一个窗口图标。它的原型为:
HICON LoadIcon
(
HINSTANCE hInstance, //图标资源所在的模块句柄;
//如果使用NULL,就会使用系统预定义的图标
LPCTSTR lpIconName //图标资源名或系统预定义的图标标识名
)
2、LoadCursor函数
LoadCursor函数作用是在应用程序中加载一个窗口光标。它的原型为:
HCURSOR LoadCursor
(
HINSTANCE hInstance,//光标资源所在的模块句柄;
//如果使用NULL,它就会使用系统预定义的光标
LPCTSTR lpCursorName//图标资源名或系统预定义的光标标识名
)
3、GetStockObject函数
应用程序通过调用GetStockObject函数来获取系统提供的背景刷,它的原型为:
HBRUSH GetStockObject(int nBrush);
//nBrush 为系统提供的背景刷标示名
②注册窗口类
Windows系统本身提供部分预定义的窗口类,我们也可以自己定义窗口类,窗口类必须先注册后使用。窗口类注册使用的函数是RegisterClass()实现。它的原型为:
RegisterClass(&wndclass);
//wndclass为窗口的类结构(前面第二篇文章已经介绍过了)
③创建窗口
窗口注册之后就要把它实例化,简单的说就是创建一个窗口的实例。它是由函数CreateWindow()实现,函数的原型为:
HWND CreateWindow
(
LPCTSTR lpszClassName,//窗口实例的类的名字
LPCTSTR lpszTitle, //窗口标题名
DWORD dwStyle, //新创建的窗口的样式(后面将会详细介绍)
int x, //窗口左上角的横坐标
int y, //窗口左上角的纵坐标
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hwndParent, //该窗口的父窗口的句柄
HMENU hMenu, //窗口主菜单句柄
HINSTANCE hInstance, //创建窗口的应用程序当前句柄
LPVOID lpParam //指向一个传递给窗口的参数值的指针
)
那么窗口的样式有哪些呢?
标识 说明
WS_BORDER 创建一般带边框的窗口
WS_CAPTION 创建一个带标题栏的窗口
WS_HSCROLL 创建一个带水平滚动条的窗口
WS_MAXIMIZEBOX 创建一个带最大化按钮的窗口
WS_MINIMIZEBOX 创建一个带最小化按钮的窗口
WS_OVERLAPPED 创建一个带边框和标题栏的窗口
WS_OVERLAPPEDWINDOW 创建一个带边框、标题栏、系统菜单及最大化、最小化按钮的窗口
WS_POPUP 创建一弹出式窗口
WS_POPUPWINDOW 创建一带边框和系统菜单的弹出式窗口
WS_SYSMENU 创建一带系统菜单的窗口
WS_VSCROLL 创建一带垂直滚动条的窗口
当然为了实现具有多种风格的窗口,WINAPI提供了“|”来表示并(∪)的意思。例如我们要实现一个即具有垂直滚动条又具有水平滚动条的弹出式窗口时可以输入:WS_BSCOLL|WS_VSCROLL|WM_POPUP
④显示窗口
以上的操作均由函数实现,显示窗口当然也不例外。窗口类的显示由ShowWindow和UpdateWindow函数实现。应用程序调用ShowWindow函数在屏幕上显示窗口,其形式为:
BOOL ShowWindow(hwnd,nCmdShow)
//其中hwnd为窗口句柄,nCmdShow为窗口显示形式标识
nCmdShow共有六个可选值
标识 说明
SW_HIDE 隐藏窗口
SW_SHOWNORMAL 显示并激活窗口
SW_SHOWMINIMIZE 显示并最小化窗口
SW_SHOWMAXIMIZE 显示并最大化窗口
SW_SHOWNOACTIVE 显示但不激活窗口
SW_RESTORE 恢复窗口原来的位置及尺寸
在窗口显示之后,应用程序应使用UpdateWindow函数更新并绘制用户区,并发出WM_PAINT消息。它的形式为:
BOOL UpdataWindow(hwnd);
//hwnd为窗口句柄
(未完待续)