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. 关于资源文件的说明

菜单与图标

范例:menu_one

[images/menu_one.gif]

  这是一个展示如何向你的窗口添加基本的菜单的小段落一般你使用一个準好的菜单资源它们在.rc文件中编译后链接到你的.exe文件中.这部分对于不同的编译器很多差異商业化的编译器拥有资源编辑器你可用它来创建菜单不过在这里我将向你展示.rc的內容这样你就可以手工修攺我通常用一个.h文件同时被我的.rc文件和.c文件包含这个件包含控件和菜单项目的标识等內容

  比如你可以从我们的那个simple_window的例子开始再按照我们所说的把下面的代码加入进去

  首先是.h文件.一般称为"resource.h"

#define IDR_MYMENU 101
#define IDI_MYICON 201

#define ID_FILE_EXIT 9001
#define ID_STUFF_GO 9002

  不是很多代码但我们的菜单将非常简单这里的名字和值由你选择现在我们来写.rc文件

#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "E&xit", ID_FILE_EXIT
    END

    POPUP "&Stuff"
    BEGIN
        MENUITEM "&Go", ID_STUFF_GO
        MENUITEM "G&o somewhere else", 0, GRAYED
    END
END

IDI_MYICON ICON "menu_one.ico"

  你可能需要把这个.rc文件添到你的项目或makefile中去依你使用的工具而定).

  你也要在你的源文件.c中#include "resource.h"这样你要用的菜单命令标识和菜单资源标识才会被定义

  将菜单和图标加到你的窗口的最简单的方法是当你注冊你的窗口类的时候指明它们这样

    wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MYMENU);
    wc.hIcon  = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
    wc.hIconSm  = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0);

  攺变一下看有什么效果. 你的窗口将有一个File和一个Stuff菜单项目和它们下面的项目假设你的.rc文件被正确编译并链接至你的程序中去.(又要参考编译器的说明了.)

  窗口的左上角和任务栏现在将显示我们定义的自定义小图标如果你按下Alt+Tab应用程序列表中将显示图标的大版本

  我用了LoadIcon()来装入大图标因为这样简单但它只会装入默认的分辨率为32*32的图标所以为了装入小图标我们要用LoadImage().注意图标文件和资源可以含有个图像这个例子中我提供了我要装入的两种大小的图像

范例:menu_two

  另外一种使用菜单资源的方式是在运行的时候创建一个on the fly).这需要多一点的技巧但增添了灵活度而且在某些时候是必需的

  你也可以不是以资源存储的图标你可以把你的图标存为一个单独的文件并在运行的时候装入这样可以给你使用戶自己来选择图标的选项使用我们将在后面的章节中讲的对话框或別的什么类似的东西来选择

  再从沒有添加.h的.rc文件的simple_window例子开始现在我们要处理WM_CREATE消息并向窗口添加一个菜单

#define ID_FILE_EXIT 9001
#define ID_STUFF_GO 9002

  这次把这两个标识放在你的.c文件的首部就在你的#include语句下面.接下来我们向我们的WM_CREATE消息处理部分添加如下的代码

    case WM_CREATE:
    {
        HMENU hMenu, hSubMenu;
        HICON hIcon, hIconSm;

        hMenu = CreateMenu();

        hSubMenu = CreatePopupMenu();
        AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
        AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");

        hSubMenu = CreatePopupMenu();
        AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&Go");
        AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Stuff");

        SetMenu(hwnd, hMenu);


        hIcon = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
        if(hIcon)
            SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
        else
            MessageBox(hwnd, "Could not load large icon!", "Error", MB_OK | MB_ICONERROR);

        hIconSm = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
        if(hIconSm)
            SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
        else
            MessageBox(hwnd, "Could not load small icon!", "Error", MB_OK | MB_ICONERROR);
    }
    break;

  这样做几乎创建了和我们添加资源文件的一样的菜单加到一个窗口的菜单会随著程序的终止而自动删除所以我们不需要在后面来担心怎样删除.我们真的要那样做的话可以用GetMenu()和DestroyMenu()

  图标的代码相当简单我们调用LoadImage()两次装入了16*16和32*32两种大小的图标.我们这里不能用LoadIcon()因为它只能装入资源而不能装入文件.我们把实例句柄参数写成了NULL因为我们不是从我们的模块装入资源而且我们不用资源的标识而使用了我们要装入的图标文件名.最后我们传入了LR_LOADFROMFILE这个标志来指示我们需要这个函数将我们传入的字符串当作文件名而不是资源名字

  如果所有的调用都成功了我们就我在WM_SETICON的消息处理中把图标的句柄赋给我们的窗口如果失败了则弹出一个对话框告诉我们出错了

注意如果我们要装入的图标文件不在程序现在的当前目錄则LoadImage()调用失败如果你用VC++从IDE来运行程序的话当前目錄就是你工程文件所在的目錄.如果你从Debug或Release目錄下用文件管理器或命令行运行的话你就需要把你的图标文件拷进去样以使你的程序找到它如果怎样还是出错就在你的调用中指明图标的全路径, "c:\\path\\to\\icon.ico".

  好的现在我们有菜单了我们让它做点事情.这很简单我们就需要响应WM_COMMAND消息就行.我们也需要我们得到了哪个消息并做出相应的动作现在我们的WndProc()应该看起来像这样

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch(Message)
    {
        case WM_CREATE:
        {
            HMENU hMenu, hSubMenu;

            hMenu = CreateMenu();

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&Go");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Stuff");

            SetMenu(hwnd, hMenu);


            hIcon = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
            if(hIcon)
                SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
            else
                MessageBox(hwnd, "Could not load large icon!", "Error", MB_OK | MB_ICONERROR);

            hIconSm = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
            if(hIconSm)
                SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
            else
                MessageBox(hwnd, "Could not load small icon!", "Error", MB_OK | MB_ICONERROR);
        }
        break;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case ID_FILE_EXIT:

                break;
                case ID_STUFF_GO:

                break;
            }
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    return 0;
}

  你可以看到我们把WM_COMMAND消息响应了并且它还有自己的一个switch()在其中.这个switch()由wParm的低字来決定因为可能WM_COMMAND消息包含了发送消息的菜单或控件的标识

  我们显然想要Exit菜单来关闭程序所以在WM_COMMANDID_FILE_EXIT消息的处理程序中你可以使用下面的代码来做到这一点

PostMessage(hwnd, WM_CLOSE, 0, 0);

  你的WM_COMMAND处理代码现在看起来应该像样:

    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
            case ID_FILE_EXIT:
                PostMessage(hwnd, WM_CLOSE, 0, 0);
            break;
            case ID_STUFF_GO:

            break;
        }
    break;

  至于ID_STUFF_GO要干什么就留给你来定义了.

程序文件的图标

  你可能注意到了menu_one.exe看起来是我们给的那个当作资源的那个图标而menu_two.exe则不是的因为我们是装入的外部的文件.Windows资源管理器只是显示程序资源中的第一个图标(由ID排序)所以我们只有一个图标的时候就显示那个了.如果我们要显示某个特定的图标就把它加到资源中去并给定义个很小的标识...比如1.你根本就需要使用这个图标你完全可以给你的窗口装入完全不同的图标

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