Chinaunix首页 | 论坛 | 博客
  • 博客访问: 104579992
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: C/C++

2008-04-15 18:46:34

    来源:    作者:ant3000

你要把所有要发生的消息都写进程序代码的话,我想你可能已经累疯了。我想我会的。感谢上帝,Windows提供了默认消息处理,如果你没有任何特殊的消息需要处理了,你总是要用DefWindowPorc()函数的,下面给一个最简单的例子,没有任何特定的消息要处理的例子:

LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    return(DefWindowProc(hwnd, msg, wparam, lparam));
}

简单吧!但通常你都需要处理一些自己的消息,你要写自己的程序代码,然后返回0,来告诉程序你干完了。下面是一个例子,当窗口建立时,你调用了一个初始化的函数Initialize_Game(),然后返回0,最后告诉程序自己处理那些默认的消息吧:

LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    if (msg == WM_CREATE)
    {
        Initialize_Game();
        return(0);
    }

    return(DefWindowProc(hwnd, msg, wparam, lparam));
}

你很可能需要一个“switch”结构来手动完成你想要控制的消息,然后把剩下的交给DefWindowProc()去做。大功告成前,我不得不提醒您一件事,就是怎样使你的消息控制得到响应呢?

六、读取消息队列

这里先给你一个switch结构的例子吧:

LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    switch(msg)
    {
    case WM_CREAT:
        [初始化游戏]
        return 0;
    case WM_PAINT:
        [画一架飞机]
        return 0;
    case ……………………
        ……………………
    }

    return(DefWindowProc(hwnd, msg, wparam, lparam));
}

在进入程序的主循环前,你需要看看你的消息控制(就是你在switch结构里编的那些),尤其是还没有用到的消息控制是否被机器存了起来,以备一旦用到,马上响应。做到正确的响应,你需要做几件事。首先你需要PeekMessage()函数。下面是它的原形:

BOOL PeekMessage(
    LPMSG lpMsg,          // pointer to structure for message
    HWND hWnd,            // handle to window
    UINT wMsgFilterMin,   // first message
    UINT wMsgFilterMax,   // last message
    UINT wRemoveMsg       // removal flags
);

这是一个布尔类型,也就是一个int型,不过只有两个值,TRUE和FALSE,如果有一条消息在队列中等待,函数返回TRUE,否则,返回FALSE。它的参数也很简单:

※ LPMSG lpMsg:这是一个MSG类型的指针变量。如果有消息在等待,消息信息将被填入该变量。

※ HWND hWnd:你所要检查的消息队列的窗口的句柄。

※ UINT wMsgFilterMin,wMsgFilterMax:索引第一个和最后一个消息,一般你都从第一个消息开始检索,所以把它们都设置为0好了。

※ UINT wRemoveMsg:一般来说,它有两个指,PM_REMOVE或者PM_NOREMOVE。使用前者会在消息被读取后从队列中移除,后者是继续保留。通常,我们选择前者PM_REMOVE。

真正处理消息时,你需要做两件事,很简单,第一件是TranslateMessage(),第二件是DispatchMessage()。它们的原形很相似:

BOOL TranslateMessage(CONST MSG *lpmsg);
LONG DispatchMessage(CONST MSG *lpmsg);

头一个是把消息翻译过来,第二个是从MSG结构中调用相应的信息。你只需要知道这么多。伴随着程序主循环的反复执行,如果有消息出现,你就调用这两个函数,函数MsgHandler()会安排好一切的。下面是个例子:

if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

没问题,你现在完全可以写一个窗口程序了。不坏吧?在结束本章前,我还有几点要提醒你。还记得我们在消息时,说要在后面进一步讨论它吗?那么怎样主动向Windows发送消息呢?

七、发送消息

有两种办法可以做到:PostMessage()函数或SendMessage()函数。

它们的原形很相似:

BOOL PostMessage(
            HWND hWnd,     // handle of destination window
            UINT Msg,      // message to post
            WPARAM wParam, // first message parameter
            LPARAM lParam  // second message parameter
);

LRESULT SendMessage(
            HWND hWnd,     // handle of destination window
            UINT Msg,      // message to post
            WPARAM wParam, // first message parameter
            LPARAM lParam  // second message parameter
);

它们的参数相同,并且和前面讲过的函数MsgHandler()的参数功能相同,就不重复了。现在我们只谈谈它们之间的区别。

PostMessage()被经常用来向队列中加入消息,成功,返回TRUE,否则,返回FALSE。它只是简单的把消息加入到队列中,然后返回。多数情况下,调用它将返回TRUE。

SendMessage()则有些不同,它并不是把消息加入到队列里,而是直接翻译消息和调用消息处理,直到消息处理完成后才返回。所以,SendMessage()比PostMessage()有更高的应急性。你想立刻干的事情,就应该调用它。消息是DOS和Windows编程之间重要的区别标志。

八、程序的流程

在DOS中,我们不必担心消息这种东西,不必担心多个程序同时运行,但在Windows里,你必须考虑这些。在Windows平台上编程,有一些不同于DOS下编程的地方。让我们看看下面这段虚拟的代码:

// main game loop
do
{
    // handle messages here

    // ...

    // update screen if necessary
    if (new_screen)
    {
        FadeOut();
        LoadNewMap();
        FadeIn();
    }

    // perform game logic
    WaitForInput();
    UpdateCharacters();
    RenderMap();

} while (game_active);

假设FadeOut()函数这样工作:当函数被调用,在一秒内屏幕图象暗淡下来,当屏幕完全黑了,函数返回。LoadNewMap()调用一个新的图象;FadeIn()使屏幕逐渐亮起来,好显示新图象。当有键子按下,调用WaitForInput()函数,再继续调用下去。这在DOS游戏编程里是合情合理的,但在Windows下不行。为什么呢?让我们看看新画面诞生的过程。画面逐渐变黑,调用图片,逐渐恢复。这大概要2秒钟,用户可以等待,也可能要移动一下窗口,但程序只专心的干调用图片的工作,不会对窗口的移动作出反应。这是很糟糕的,你做了机器不知道的事情,这可能导致系统崩溃,我们必须要让机器对用户的任何操作作出正确的反应。不多说了,总之你要换一换脑筋,如果你从来就没在DOS下编过程序,那正好,你赶上潮流了!

九、总结

本章我们讲了Windows编程的基础,虽然只是一个空白的窗口,但包含了最基本的东西。接下来的连载我们将学习创建资源和利用资源,你就可以用有自己风格的光标、图标、声音、菜单等等,还要生成一个EXE文件呢!

阅读(331) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~