科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Delpih 中的Windows API编程初步

Delpih 中的Windows API编程初步

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

使用RAD类型工具的人越来越多了,虽然我对于RAD类的工具向来不多作评议,但我还是常常使用的。

作者:潇潇 来源:天极网 2007年10月31日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
三、消息的处理

  那么消息是怎样被处理的呢?回调函数又有什么作用呢?有了前面的知识,我们只要能对不同的消息进行正确的解释,就可以做到对消息的正确处理了。但前面我们提到了对于不同的消息传递的信息使不相同的,所以这是API编程中最麻烦的一部分了。

  我们这里先给出一个常见而又必须的消息框架。

function WindowProc ( hwnd : HWnd ; Msg : UINT; Wparam : WPARAM ; Lparam : LPARAM ) : LRESULT ; stdcall ; export ;
var
 dc : hdc ;
 rc : Trect ;
 ps : TpaintStruct ;
begin
 case Msg of
  WM_PAINT :
  Begin
   dc : = BeginPaint ( hwnd , ps ) ;
   …… ……
   EndPaint (hwnd, &ps) ;
   Exit ;
  end;
  WM_COMMAND :
  …… ……
  WM_DESTROY :
  Begin
  PostQuitMessage ( 0 ) ;
  Exit ;
 end ;
end;
Result : = DefWindowProc ( hWnd , Msg , wParam , lParam ) ;
end ;

  在这个框架中,WindowProc就是我们前面提到的回调函数。它是windows程序设计中的重点。无论是从输入输出等硬件设备传来的消息,还是从软件传来的消息,都要保存到系统的消息队列中,这个消息队列有两种,一种是系统消息队列,主要是用来保存从输入输出等硬件设备传来的消息,另一种是每个程序窗口的窗口消息队列,主要保存每个窗口的发送来的消息。之后对消息的获取和分发工作,当然是由前面讲到的GetMessage 、 TranslateMessage和DispatchMessage三个函数来完成。至于消息的处理工作,则是由WindowProc函数来完成了。也就是说它是由系统在程序有消息到达时才调用的,所以我们称之为回调函数。

  WindowProc是在注册窗口类时,注册的窗口消息处理函数,当然名字可以自己命名。其中的参数有hwnd : HWnd ; Msg : UINT; Wparam : WPARAM ; Lparam : LPARAM ,这也就是我们前面谈到的消息和窗体。

  这里我们主要使用了三种消息:WM_PAINT , WM_COMMAND和WM_DESTROY ,但是我们可以随着程序而是用各种各样的消息。为了处理不同的消息,在程序中使用了分支结构,所以随着程序的规模越来越大,这个分支结构也会越来越庞大。

  在这些消息中有两个点是最为重要的,其一是WM_DESTROY消息,它表示一个销毁窗口退出应用程序的消息。也是每个程序所必备的。对于这个消息的处理方式就是通过调用PostQuitMessage ( 0 )函数传递一个WM_QUIT消息,准备让由GetMessage 、 TranslateMessage和DispatchMessage三个函数组成的消息循环中的GetMessage取得。当消息循环中的收到WM_QUIT消息时,GetMessage会传回0,从而结束消息循环。进而释放各种资源,结束整个程序。另一个重要的地方是DefWindowProc函数。我们的程序无论多大都不可能将所有的消息都处理,所以我们必须有一个机制让不重要的不需要我们处理的消息,交给windows操作系统为我们处理,这个过程就是由DefWindowProc函数来实现的。 因此当我们按下窗口右上角的差号或者按下左上角系统菜单中的Close命令时,系统会送出WM_CLOSE消息。通常程序的窗口函数不拦截此消息,于是交由DefWindowProc函数来处理。DefWindowProc函数在受到WM_CLOSE消息后,调用DestroyWindow把窗口清除。DestroyWindow又会送出WM_DESTROY消息。程序又如前面讲到的一样来结束程序释放资源。

  四、建立窗口类

  知道了消息的传递和处理之后,我们来看看有关窗口的知识。

  Windows带给我们的不仅是技术上的创新,更重要的是统一而又便捷的窗口。那么它是怎样创建的呢?这就要从窗口类tagWNDCLASSA说起了。

  让我们先打开delphi目录下的source\rtl\Win\Windows.pas文件,18875行,可以看到这样一个结构:

tagWNDCLASSA = packed record
style : UINT ;
lpfnWndProc : TFNWndProc ;
cbClsExtra : Integer ;
cbWndExtra : Integer ;
hInstance : HINST ;
hIcon : HICON ;
hCursor : HCURSOR ;
hbrBackground : HBRUSH ;
lpszMenuName : PansiChar ;
lpszClassName : PansiChar ;
end ;

  其中存储了一个窗口的所有相关信息。style : UINT 表示窗口的风格;lpfnWndProc : TFNWndProc 表示窗口的消息处理函数;hInstance : HINST 表示窗口的一个应用实例;Icon : HICON 用来记录窗口的图标;hCursor : HCURSOR 记录窗口的光标;hbrBackground : HBRUSH 用来记录窗口的背景色;lpszMenuName : PansiChar 表示窗口中的菜单资源的名称; lpszClassName : PansiChar 记录窗口类的名称。

  下面是一个例子:

WindowClass . style : = CS_VREDRAW + CS_HREDRAW + CS_DBLCLKS ;
WindowClass . lpfnWndProc : = @DefWindowProc ;
WindowClass . hCursor : = LoadCursor ( 0 , IDC_ARROW ) ;
WindowClass . hbrBackground : = 0 ;
WindowClass . hInstance : = Hinstance ;
StrPCopy ( WinClassName , ClassName ) ;

  五、注册窗口类

  当我们按照程序的要求创建了这个窗口类之后,我们就可以在系统中注册它了。这就要用到function RegisterClass(const lpWndClass: TWndClass): ATOM; stdcall;这样一个函数了。他只有一个参数,就是我们先前说注册的窗口类。

  六、创建窗口

  有了前面几步,现在我们可以创建我们所注册的窗口,看看她的真面目了。

function CreateWindow ( lpClassName : Pchar ; lpWindowName : PChar ;
dwStyle : DWORD ; X , Y , nWidth , nHeight : Integer ; hWndParent : HWND ;
hMenu : HMENU ; hInstance : HINST ; lpParam : Pointer ) : HWND ;

  这个函数可以帮助我们创建我们先前注册的窗口。其中的参数lpClassName : Pchar表示我们前面注册的窗口类的名称。lpWindowName : PChar 表示窗口的标题; dwStyle : DWORD 表示窗口的风格; X , Y , nWidth , nHeight : Integer ; 表示窗口的位置和宽度高度;

  七、显示窗口

  窗口创建了,但我们只有在调用function ShowWindow ( hWnd : HWND ; nCmdShow : Integer ) : BOOL ; stdcall ;函数之后才会显示出来。这个函数很简单,hWnd : HWND 表示窗口的句柄, nCmdShow : Integer则是窗口的显示方式。function UpdateWindow ( hWnd : HWND ) : BOOL ; stdcal l ;函数则会送出一个WM_PAINT消息,使窗体得到更新。

  也许你会觉得很烦人,但这是所有windows程序的基础,即便是我们用delphi编程时,程序也都是这样运行的,只是delphi的创造者将一切都隐藏到了一个美丽外表之下。

  下面我们用大家最常见的一个例子对前面的知识加以总结。在这个例子中,我们将在窗体中显示“ hello , world ! ” 。下面是程序及其运行效果:

program Project1;
{ $ APPTYPE CONSOLE }
uses
Windows ,
Messages ;
{ uses
 SysUtils ; }
var
 wClass : TWndClass; // 主窗口类
 hInst , //应用程序句柄
 Handle : HWnd ; // 主窗口
 aMsg : TMsg ; //消息
 RCT : TRect ; //区域
 ps : TPaintStruct ; //显示
 dc : hdc ; //设备上下文
 //函数:WindowProc
 //作用:处理主窗口的消息
 function WindowProc ( hWnd , Msg , wParam , lParam : Longint ) : Longint ; stdcall ;
 begin
  WindowProc : = 0 ;
 case Msg of
  WM_PAINT :
 begin
  dc : =BeginPaint ( hWnd , ps ) ;
  GetClientRect ( hWnd , RCT ) ;
  DrawText ( dc , ' hello , world ! ' , -1 , RCT , Dt_SINGLELINE or DT_CENTER or DT_VCENTER ) ;
  EndPaint ( hWnd , ps ) ;
  Exit ;
 end ;
  WM_DESTROY : //结束应用程序
  Begin
  PostQuitMessage ( 0 ) ;
  Exit ;
  end ;
 end ;
 Result : = DefWindowProc ( hWnd , Msg , wParam , lParam ) ; //消息默认处理
end ;
//主窗口
begin
// hInst : = GetModuleHandle ( nil ) ; // 获得应用程序句柄
with wClass do //初始化窗口类
begin
 hInstance : = system.MainInstance ;
 Style : = CS_HREDRAW or CS_VREDRAW ;
 HIcon : = LoadIcon ( 0 , IDI_APPLICATION ) ;
 LpfnWndProc : = @WindowProc ;
 HbrBackground : = GetStockObject ( WHITE_BRUSH ) ;
 lpszClassName : = ' Sample Class ' ;
 hCursor : = LoadCursor ( 0 , IDC_ARROW ) ;
end ;
RegisterClass ( wClass ) ; // 注册窗口类
//创建主窗口
Handle : = CreateWindow (
' Sample Class ' , // 窗口类名
' Windows API在Delphi中的应用 ' , //窗口标题
WS_OVERLAPPEDWINDOW or WS_VISIBLE , // 窗口风格
10 , //左边界坐标
10 , //上边界坐标
400 , // 宽度
300 , // 高度
0 , // 父窗口句柄
0 , //菜单句柄
system . MainInstance , // 应用程序实例
nil //创建窗口的附加参数
) ;

if Handle <> 0 then
begin
 ShowWindow ( Handle , SW_SHOW ) ;
 UpdateWindow ( Handle ) ;
end ;

while ( GetMessage ( aMsg , Handle , 0 , 0 ) ) do //消息循环
begin
 TranslateMessage ( aMsg ) ; //翻译消息 DispatchMessage ( aMsg ) ; //发送消息
end ;
end .

  效果如下图:

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章