winapi属于底层开发吗_WinAPI简单入门

本文介绍了WinAPI的基本概念和一个简单的HelloWin程序,展示了WinAPI的运行机制,包括WinMain函数、窗口类注册、窗口创建、消息循环及窗口过程的处理。通过对WM_PAINT和WM_DESTROY消息的处理,揭示了Windows程序如何响应用户操作并完成自身绘制。
摘要由CSDN通过智能技术生成

WinAPI简单入门

2018-11-29

不要觉得奇怪,虽然我们拥有众多“所见即所得”的编程方式来开发众多界面精美的应

用程序,这些可视化的编程环境提供了大量的类库和控件,但是在开发者享受方便的同时,

他们的手脚已经不知不觉的受到了限制,有很多深入到Windows内部的操作它们无法完成,

为什么?因为所用的类库不支持。

事实上这些类库与控件都是架构在Window API的基础上面的,API即 Application

Programming Interface -- 应用编程接口 的缩写,它不仅为应用程序所调用,同时也是

Windows的一部分,Windows自身的运行也调用这些API函数。要了解如何使用API就必须了

解一些Windows的运行机制。

简单地说,Windows是由事件驱动的抢占式多任务操作系统。事件驱动是相对于过程驱

动而言的,它改变了原来文件的顺序执行方式;Windows既然是多任务系统,就必须能同时

处理多个事件,系统为应用程序生成一个消息队列,消息在上面被张贴和发送,应用程序只

要从其消息队列中取出消息,然后一一执行就可以了。

现在,我将使用最最基本的范例程序 HelloWin 来说明WIN32 API的运行机制

首先,一个程序一定要有进入点,Win32 App的进入点函数的名称是WinMain,它的原型如下

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine,int nCmdShow)

hInstance是所谓的“实例句柄”,它是一个数值,当程序在Windows下运行的时候,它被用

来唯一的标示这个程序,虽然用户可能同时运行多个同一个程序,即运行多个“实例”,我

们可以看到,每一个实例都有不同的hInstance值。

hPrevInstance,简单地说就是没用…它是存在于16位Windows程序中的,在编写

Windows 9x/NT/2000 程序的时候,总应该是NULL。

szCmdLine是一个指针,指向一个以0为终结的字串,里面包含传给该程序的命令行参数,

如果想要让程序处理命令行,那么这个参数就有用了。

iCmdShow参数是一个数值,指示窗口将如何被显示,这个数值由在Windows下运行该程序的

程序所决定,通常是SW_SHOWNORMAL。

接下来是注册一个窗口类,窗口总是从窗口类的基础上创建的,窗口类用以标示处理窗口消

息的窗口过程,注册窗口类时使用 RegisterClassEx() 函数,它只需要一个参数,一个指向

类型为 WNDCLASSEX 的结构指针。

具体注册初始是这样的:

WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);     //结构的大小

wcex.style = CS_HREDRAW | CS_VREDRAW; //类风格

wcex.lpfnWndProc = (WNDPROC)WndProc;  //窗口类的窗口过程

wcex.cbClsExtra = 0;            //在类结构中预留的空间

wcex.cbWndExtra = 0;           //在Windows内部保存的窗口结构中预留的空间

wcex.hInstance = hInstance;        //程序的实例句柄

wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_EXAMPLE);  //程序图标

wcex.hCursor = LoadCursor(NULL, IDC_ARROW);         //结构的大小

wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);    //指定窗口的背景颜色

wcex.lpszMenuName = (LPCSTR)IDC_EXAMPLE;         //菜单

wcex.lpszClassName = szWindowClass;             //类名,和程序名相同

wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);    //也是程序图标

return RegisterClassEx(&wcex);

接下来,定义一个HWND,然后使用 CreateWindow() 函数,原型如下:

HWND CreateWindow(

LPCTSTR lpClassName,    // 窗口类名

LPCTSTR lpWindowName,  // 窗口标题

DWORD dwStyle,       // 窗口风格

int x,             // 初始x

int y,             // 初始y

int nWidth,          // 窗口宽

int nHeight,         // 窗口高

HWND hWndParent,     // 父窗口句柄

HMENU hMenu,       // 菜单句柄

HINSTANCE hInstance,   // 实例句柄

LPVOID lpParam       // 创建参数

);

在 CreateWindow() 调用返回之后,Windows内部已经创建了这窗口。但是窗口并为显示,

还需要两个调用,一个是 ShowWindow(hwnd, iCmdShow):第一个参数是刚刚创建的窗口

句柄,第二个参数是传递给WinMain的nCmdShow;另一个是 UpdateWindow(hwnd) ,导致

客户区域被绘制。

接下来,程序通过执行一块被称为“消息循环”的代码从消息队列中取出消息

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

{

if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

消息循环以 GetMessage 开始,它从消息队列中取出一条消息,只要从消息队列中取出消

息的 Message 域不为 WM_QUIT,GetMessage 就返回一个非零值,否则将导致程序退出

消息循环,然后程序中止,返回 msg 结构的 wParam 参数。在循环中,TranslateMessage

将 msg 结构的内容进行修改,而 DispatchMessage 找出准备调用的窗口过程。

上面进行的仅仅是准备性工作:注册窗口类、创建窗口、显示窗口、进入消息循环取出消息

而实际的动作都发生在窗口过程中。

LRESULT CALLBACK WndProc(HWND hWnd, //刚刚创建的窗口句柄

UINT message,           //得到的消息

WPARAM wParam,

LPARAM lParam           //消息的进一步详细的参数

)

在程序中窗口过程通常是命名为 WndProc 的函数,其实窗口过程可以任意的命名,一个

Windows程序可以包含多个窗口过程,一个窗口过程总是与调用了 RegisterClassEx 注册的

窗口类相关联,CreateWindow 函数根据窗口类来创建窗口,但是一个窗口类可以被用来创

建多个窗口。

消息收到之后,接下来应该根据消息的不同来进行处理

switch(message)

{

case …:

HelloWin程序只需要处理两条消息,即 WM_PAINT 和 WM_DESTROY。

WM_PAINT 消息在Windows程序中的地位极其重要,当窗口客户区的一部分或者全部变为

“无效”,必须进行刷新的时候,将由这条消息通知程序。

为什么客户区域会变得无效呢?在创建窗口的时候,整个客户区都是无效的,因为还没有画

任何的东西。第一条 WM_PAINT 消息指示窗口过程在窗口上面画一些东西;还有在用户改

变了窗口的大小之后,客户区域重新变得无效,除此之外最小化窗口之后再还原、窗口的一

部分被覆盖,都会引发这条消息。

WM_DESTROY消息则是当用户按下“关闭”按钮的时候被触发,标准的处理方法是调用

PostQuitMessage 将一条 WM_QUIT 消息插入消息队列,这将使得 GetMessage 函数调用

返回0,从而退出消息循环,结束整个程序。

其实,从上面可以看出,Windows程序的这种运行机制并不是很难理解,真正困难的是不知

道调用什么函数去完成想要的操作,以及怎样调用那些函数,从而灵活的进行底层API程序

开发,这是一个循序渐进的积累过程,没有捷径可走的。请各位一定要记住。

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。

http://www.pinlue.com/style/images/nopic.gif

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值