Timers and Animation

theForger's Win32 API教程第二版(简体中文)

主页

基础
  1. 开始学习
  2. 一个简单的窗口
  3. 处理消息
  4. 理解消息循环
  5. 使用资源
  6. 菜单和图标
  7. 对话框
  8. 非模态对话框
  9. 标准控件
  10. 对话框常见问题
创建一个简单应用
  1. 在运行时创建控件
  2. 文件与常用对话框
  3. 工具栏与状态栏
  4. 多文档界面
图形设备接口
  1. 位图,设备上下文
  2. 透明位图
  3. 定时器与动画
  4. 文本,字体与顏色
工具与文档
  1. 参考
  2. 免费的Visual C++(最新更新)
附表
  1. 常见错误的解決方法
  2. API vs. MFC
  3. 关于资源文件的说明

应用 第一部分:运行时创建控件

[images/app_one.gif] 范例:app_one

  我想对于一个在运行时候创建控件的范例来讲,虽然有用,但除非真的做点什么有用的事,否则还是沒什么用,所以这里我以一个文本编辑器开始并把它其做成能支持打开,编辑并保存文本文件的有用程序.

  第一步,这页所说的就是简单地创建窗口和作为整个程序的核心的一个编辑框控件.

  从那个简单窗口的程序框架开始,我们加上用#define定义我们的控件标识和在我们的窗口过程中加上下面的两个消息处理的代码:

#define IDC_MAIN_EDIT	101
    case WM_CREATE:
    {
        HFONT hfDefault;
        HWND hEdit;

        hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", 
            WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 
            0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
        if(hEdit == NULL)
            MessageBox(hwnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);

        hfDefault = GetStockObject(DEFAULT_GUI_FONT);
        SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
    }
    break;
    case WM_SIZE:
    {
        HWND hEdit;
        RECT rcClient;

        GetClientRect(hwnd, &rcClient);

        hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
        SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
    }
    break;

创建控件

  正如创建所有其它的窗口一样,创建控件使用CreateWindowEx()这个API.我们将我们想要的已注冊的类传进去,这里是编辑框控件类, 这样我们就得到一个标準的编辑框控件窗口. 当用对话框来创建我们的控件时,我们一般要写下要创建的控件的清单,以便在你调用DialogBox()或CreateDialog()的时候系统可以在对话框的资源中读入控件的列表并调用CreateWindowEx()来按照在资源中定义的位置和式样来创建每个.

    hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", 
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 
        0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
    if(hEdit == NULL)
        MessageBox(hwnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);

  你可以看到这个CreateWindowEx()的调用指定了很多的式样,而且在实际的编程有更多也很常见,尤其是有大堆选项的常用控件. 开始的四个WS_式样应该相当清楚,我们以我们窗口的一个子窗口来创建这个控件,我们使其可见,并且有纵向和水平的滾动条.

  三个为编辑框特有的式样(ES_MULTLINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL)指定了这个编辑框应该含有多行文本,并于你在控件的最底部和最右边打字的时候分別自动滾动.

  常规的窗口式样(WS_*)列在MSDN中.而扩展的窗口式样(WS_EX_*)在MSDN中对CreateWindowEx()的解释中有说明,那个地方你也可以找到对每个控件特有式样说明的链接.(我们例子中的ES_*就是为编辑框所特有).

  我们以控件指定了作为其父窗口的我们的窗口句柄,并为其实指定了一个为IDC_MAIN_EDIT的标识,以便在后面要在对话框上创建控件时引用该控件.位置和大小参数在这里不是很重要因为我马上要响应WM_SIZE消息来动态调整此控件以使它总位于我们的窗口中间并适合其大小.

动态创建的控件的大小调整

  一般来说如果你的窗口可以调大小的话,你总是希望写点代码来动态调整你在之中创建的控件的大小以使它们总是分佈合理.

    GetClientRect(hwnd, &rcClient);

    hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
    SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);

  因为我们现在只有一个控件,工作相对比较简单.我们用GetClientRect()来获取窗口的客戶区的大小,也就是说不包括边际,菜单和标题栏的那块大(当前为止)地方.这会用值填充我们的RECT结构体,left 和top总是为0,所以你一般可以忽略他们.right和 bottom值会给你客戶区的寛和高.

  下一步我们用GetDlgItem()来获取我们控件的句柄,这个API对于对话框和常规的窗口都可以使用,并调用SetWindowPos()去移动和拉伸以填充整个客戶区.你当然可以通过更改给SetWindowPos()的值来做些別的事情,比如只填充窗口的一半,让另外一半留下来放別的控件.

在运行时创建別的控件

  我就不给出在运行时创建別的控件(列表框,按钮等等)的例子了,因为基本上是一样的,要是重复多了也烦:)如果你去查查MSDN,或是在你的Win32参考里翻翻你就会找到创建任何其它的标準控件的所需的消息.

  我们将在后面的章节中还会多次有对常见控件的操作以使你获得更多的实践.

Copyright © 1998-2008, Brook Miles (forgey). All rights reserved.