所有的Windows SDK编程都有一个类似的框架,本文就说说这个框架,Windows程序设计的框架分为“三部曲”:

一、注册窗口类

注册窗口类的API函数是RegisterClass或者RegisterClassEx,这两个函数参数区别不大,具体看MSDN,这里以RegisterClass为例。函数原型如下:

参数WNDCLASS定义如下:

 
1
2
3
4
5
6
7
8
9
10
11
12
typedef struct {
    UINT style;
    WNDPROC lpfnWndProc;
    int cbClsExtra;
    int cbWndExtra;
    HINSTANCE hInstance;
    HICON hIcon;
    HCURSOR hCursor;
    HBRUSH hbrBackground;
    LPCTSTR lpszMenuName;
    LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;

结构成员说明如下:

style:指示类窗口类的风格,比如指定水平、垂直重画;是否显示关闭窗口等。

lpfnWndProc:窗口过程函数指针,这个是最重要的参数,该参数指定消息执行的处理函数入口。

cbClsExtra:类扩展数据大小,一般不用。

cbWndExtra:窗口扩展数据大小,一般不用。

hInstance:应用程序实例,这个参数会从WinMain函数传过来。

hIcon:应用程序的图标句柄。

hCursor:应用程序的光标句柄。

hbrBackground:窗口的背景画刷。Windows预定义了一些纯色画刷,如COLOR_GRAYTEXT、COLOR_BACKGROUND、COLOR_ACTIVECAPTION等等。

lpszMenuName:菜单名,该名以资源的方式存在。

lpszClassName:窗口类的名字,这个必须指定且不能重复,否则会失败,除非你需要重复的,否则尽量避免。

二、创建主窗口并显示

 
1
2
3
4
5
6
7
8
9
10
11
12
HWND CreateWindow(LPCTSTR lpClassName,
    LPCTSTR lpWindowName,
    DWORD dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    HWND hWndParent,
    HMENU hMenu,
    HINSTANCE hInstance,
    LPVOID lpParam
);

参数如下:

lpClassName:类名,就是WNDCLASS结构中的 lpszClassName。

lpWindowName:本窗口的名字,一个字符串。

dwStyle:窗口风格,比如是否有边框、标题框、子窗口、水平垂直滚动条、弹出、重叠性等,具体看MSDN,很多特殊效果都是用这个风格指定的,比如类似迅雷的悬浮窗等。

x,y, nWidth, nHeight:指定窗口相对于父窗口的位置和宽高。

hWndParent:指定父窗口句柄,如果该窗口没有父窗口,则为NULL,比如应用程序主窗口。

hMenu:菜单句柄。

hInstance:应用程序实例句柄,跟WNDCLASS中的hInstance一样。

lpParam:指向一个CREATESTRUCT结构的参数。

显示并刷新窗口的API函数如下,参数都有对应的窗口句柄:

ShowWindow(hWnd, iCmdShow);

UpdateWindow(hWnd);

三、进入消息循环

这个过程基本是一个固定的格式:

 
1
2
3
4
5
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

该过程从系统消息队列里面获取一个消息,然后翻译虚拟按键成字符消息,并派送到窗口消息队列中,等待消息处理函数处理。如果获取到的消息为WM_QUIT,则返回0,于是就退出循环。

通过上面的三部曲,我们就创建了windows程序设计的框架,几乎任何的windows程序都可以在这个框架基础上衍生出来。下面我们给出完整的框架代码:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <windows.h>
 
static TCHAR szAppName[] = TEXT("Windows programming framework");
static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
   HWND     hWnd;
   MSG      msg;
   WNDCLASS wndclass;
 
   wndclass.style         = CS_HREDRAW | CS_VREDRAW;
   wndclass.lpfnWndProc   = WndProc;
   wndclass.cbClsExtra    = 0;
   wndclass.cbWndExtra    = 0;
   wndclass.hInstance     = hInstance;
#ifdef MY_ICON_USED
   wndclass.hIcon         = (HICON)LoadImage(NULL, TEXT("home.ico"), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
#else
   wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
#endif
   wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
   wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
   wndclass.lpszMenuName  = NULL;
   wndclass.lpszClassName = szAppName;
   if (!RegisterClass(&wndclass))
   {
      MessageBox (NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
      return 0;
   }
 
   hWnd = CreateWindow(szAppName,                  // window class name
                     TEXT("Win32 Framework Demo"), // window caption
                     WS_OVERLAPPEDWINDOW,        // window style
                     CW_USEDEFAULT,              // initial x position
                     CW_USEDEFAULT,              // initial y position
                     400,              // initial x size
                     300,              // 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;
}
 
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   HDC         hDC;
   PAINTSTRUCT ps;
 
   switch (message)
   {
   case WM_CREATE:
      // create sub window
      return 0;
 
   case WM_PAINT:
      hDC = BeginPaint(hWnd, &ps);
      // paint image
      EndPaint(hWnd, &ps);
      return 0;
 
   case WM_DESTROY:
      PostQuitMessage(0);
      return 0 ;
 
   default:
      break;
   }
 
   return DefWindowProc (hWnd, message, wParam, lParam);
}

在消息处理函数中,根据消息类型执行不同的处理,比如WM_CREATE可以处理一些创建的工作;WM_PAINT可以处理画图,显示文本;WM_DESTROY处理在窗口被销毁时的事件;当然还有很多其他的消息事件,根据情况我们做出相应的处理。

该框架程序运行起来就是一个空空的窗口,没有任何其他内容。虽然整个框架简单,但是对于windows程序设计来说非常重要。如果你想学习windows编程,就需要把每一个部分都真正理解,这样就算基本入门windows编程了,剩下的就是如何根据需求丰富这个框架使之成为一个“有用”的程序。

下一篇我们将讲解如何在windows SDK创建各种常用的控件,请继续关注。

转载请注明原文出处:http://www.coderonline.net/?p=565

api(一) 创建窗口 (转)的更多相关文章

  1. QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

    QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...

  2. 【C语言探索之旅】 第三部分第二课:SDL开发游戏之创建窗口和画布

    内容简介 1.第三部分第二课: SDL开发游戏之创建窗口和画布 2.第三部分第三课预告: SDL开发游戏之显示图像 第三部分第二课:SDL开发游戏之创建窗口和画布 在上一课中,我们对SDL这个开源库做 ...

  3. Win32 SDK 编程开始, 创建窗口, 消息的处理, 消息循环

    Windows SDK 编程的一般步骤为: 1. 注册窗口类, 使用到的结构 WNDCLASSEX, 函数 RegisterClassEx. 2. 创建窗口, 函数 CreateWindowEx. 3 ...

  4. Windows运行机理——创建窗口

    Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以进行了搬运和个人加工 Windows 窗口在创建之前,其属性必须设定好,所谓属性包括类的名字 ...

  5. vc++如何创建窗口

    创建一个mfc工程,AppWizard可以用来增加和选择一些特性 可以发现一共有五个类,每一个类都有一个基类,都是mfc基础类库中的类 例如将一个类拷贝一下,将CFrameWnd到msdn中查找一下, ...

  6. QT创建窗口程序、消息循环和WinMain函数(为主线程建立了一个QEventLoop,并执行exec函数)

    使用QT也有一段时间了,有的时候需要跟踪代码到QT的源码中去查找问题.在这里我将记录一下我跟踪QT源码学习到的一些知识. 我的开发环境是VC6.0+QT4.3.3.QT已经不为VC6.0提供addin ...

  7. ASP.NET Web API 过滤器创建、执行过程(二)

    ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...

  8. ASP.NET Web API 过滤器创建、执行过程(一)

    ASP.NET Web API 过滤器创建.执行过程(一) 前言 在上一篇中我们讲到控制器的执行过程系列,这个系列要搁置一段时间了,因为在控制器执行的过程中包含的信息都是要单独的用一个系列来描述的,就 ...

  9. ASP.NET Web API 控制器创建过程(二)

    ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...

随机推荐

  1. 面向对象继承实例(a如何继承b)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  2. RCTF Re300 Writeup

    发现一篇写得更好的:http://insight-labs.org/?p=2009  程序要求输入一个flag.拿ida加载后,发现是Upx壳,脱壳后加载入ida进行分析.定位到输入flag的地方,如 ...

  3. ThreadLocal 在web环境下使用的边界问题

    ThreadLocal 相关分析,请查看http://wangxinchun.iteye.com/blog/1884228 另外一个必须要提的点是: ThreadLocal在线程池环境下的使用. 比如 ...

  4. 从客户端中检测到有潜在危险的Request.Form值的解决办法

    http://www.pageadmin.net/article/20141016/935.html 如果你网站iis服务器asp.net采用了4.0的版本,则默认会阻止客户端的html内容提交,提交 ...

  5. 简述UITextField的属性和用法

    0.     enablesReturnKeyAutomatically 默认为No,如果设置为Yes,文本框中没有输入任何字符的话,右下角的返回按钮是disabled的. 1.borderStyle ...

  6. java 类访问权限

    Java有四种访问权限, 其中三种有访问权限修饰符,分别为private,public和protected,还有一种不带任何修饰符. private: Java语言中对访问权限限制的最窄的修饰符,一般 ...

  7. 关于ASP .Net Core 引用dll 一

    一:ASP.Net Core 引用dll文件,不可以直接引用,必须在NuGet中引用才行. 二:如果想引用自己的dll文件,则需要注册NeGet账号,获取到API Key 才行,还需要下载NuGet安 ...

  8. java创建对象的几种常用方法

    java几种常见的创建对象的方法: 1.使用new关键字创建对象 2.利用java的反射机制,通过java.lang.Class或者java.lang.reflect.Constructor创建对象 ...

  9. Binder的非正常消亡时的重置方法

    一.原理 当Binder非正常消亡的时候,会导致远程调用失败,这样客户端功能就会受到影响. 解决:给Binder设置一个死亡代理,当Binder死亡时,我们就会收到通知,这个时候可以重新发起连接. 二 ...

  10. Canvas、Paint、的简单使用及辅助类(Path、Shader、简介)

    1.Canvas类 作用:1.绘制各种图形.图片.字等.2.提供各种方法进行坐标变换(rotate.scale.skew.translate) 获取Canvas:一般是子类继承View并重写onDra ...