第01课 OpenGL窗口(4)

下面的代码处理所有的窗口消息。当我们注册好窗口类之后,程序跳转到这部分代码处理窗口消息。

LRESULT CALLBACK WndProc(    HWND    hWnd,                    // 窗口的句柄
                UINT    uMsg,                    // 窗口的消息

                WPARAM    wParam,                    // 附加的消息内容

                LPARAM    lParam)                    // 附加的消息内容
{

下面的代码比对uMsg的值,然后转入case处理,uMsg 中保存了我们要处理的消息名字。

  switch (uMsg)                                // 检查Windows消息
    {

如果uMsg等于WM_ACTIVE,查看窗口是否仍然处于激活状态。如果窗口已被最小化,将变量active设为FALSE。如果窗口已被激活,变量active的值为TRUE。

        case WM_ACTIVATE:                        // 监视窗口激活消息
        {
            if (!HIWORD(wParam))                    // 检查最小化状态
            {
                active=TRUE;                    // 程序处于激活状态
            }
            else
            {
                active=FALSE;                    // 程序不再激活
            }
            return 0;                        // 返回消息循环
        }

如果消息是WM_SYSCOMMAND(系统命令),再次比对wParam。如果wParam 是 SC_SCREENSAVE 或 SC_MONITORPOWER的话,不是有屏幕保护要运行,就是显示器想进入节电模式。返回0可以阻止这两件事发生。

        case WM_SYSCOMMAND:                        // 系统中断命令
        {
            switch (wParam)                        // 检查系统调用
            {
                case SC_SCREENSAVE:                // 屏保要运行?

                case SC_MONITORPOWER:                // 显示器要进入节电模式?

                return 0;                    // 阻止发生
            }
            break;                            // 退出
        }

如果 uMsg是WM_CLOSE,窗口将被关闭。我们发出退出消息,主循环将被中断。变量done被设为TRUE,WinMain()的主循环中止,程序关闭。

        case WM_CLOSE:                            // 收到Close消息?
        {
            PostQuitMessage(0);                    // 发出退出消息

            return 0;                        // 返回
        }

如果键盘有键按下,通过读取wParam的信息可以找出键值。我将键盘数组keys[ ]相应的数组组成员的值设为TRUE。这样以后就可以查找key[ ]来得知什么键被按下。允许同时按下多个键。

        case WM_KEYDOWN:                        // 有键按下么?
        {
            keys[wParam] = TRUE;                    // 如果是,设为TRUE

            return 0;                        // 返回
        }

同样,如果键盘有键释放,通过读取wParam的信息可以找出键值。然后将键盘数组keys[ ]相应的数组组成员的值设为FALSE。这样查找key[ ]来得知什么键被按下,什么键被释放了。键盘上的每个键都可以用0-255之间的一个数来代表。举例来说,当我们按下40所代表的键时,keys[40]的值将被设为TRUE。放开的话,它就被设为FALSE。这也是key数组的原理。

        case WM_KEYUP:                            // 有键放开么?
        {
            keys[wParam] = FALSE;                    // 如果是,设为FALSE

            return 0;                        // 返回
        }

当调整窗口时,uMsg 最后等于消息WM_SIZE。读取lParam的LOWORD 和HIWORD可以得到窗口新的宽度和高度。将他们传递给ReSizeGLScene(),OpenGL场景将调整为新的宽度和高度。

        case WM_SIZE:                            // 调整OpenGL窗口大小
        {
            ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));        // LoWord=Width,HiWord=Height

            return 0;                        // 返回
        }
    }

其余无关的消息被传递给DefWindowProc,让Windows自行处理。

    // 向 DefWindowProc传递所有未处理的消息。

    return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

下面是我们的Windows程序的入口。将会调用窗口创建例程,处理窗口消息,并监视人机交互。

int WINAPI WinMain(    HINSTANCE    hInstance,                // 当前窗口实例
            HINSTANCE    hPrevInstance,                // 前一个窗口实例

            LPSTR        lpCmdLine,                // 命令行参数

            int        nCmdShow)                // 窗口显示状态
{

我们设置两个变量。msg 用来检查是否有消息等待处理。done的初始值设为FALSE。这意味着我们的程序仍未完成运行。只要程序done保持FALSE,程序继续运行。一旦done的值改变为TRUE,程序退出。

    MSG    msg;                                // Windowsx消息结构

    BOOL    done=FALSE;                            // 用来退出循环的Bool 变量

这段代码完全可选。程序弹出一个消息窗口,询问用户是否希望在全屏模式下运行。如果用户单击NO按钮,fullscreen变量从缺省的TRUE改变为FALSE,程序也改在窗口模式下运行。

    // 提示用户选择运行模式

    if (MessageBox(NULL,"你想在全屏模式下运行么?", "设置全屏模式",MB_YESNO|MB_ICONQUESTION)==IDNO)
    {
        fullscreen=FALSE;                        // FALSE为窗口模式
    }

接着创建OpenGL窗口。CreateGLWindow函数的参数依次为标题、宽度、高度、色彩深度,以及全屏标志。就这么简单!我很欣赏这段代码的简洁。如果未能创建成功,函数返回FALSE。程序立即退出。

    // 创建OpenGL窗口

    if (!CreateGLWindow("NeHe‘s OpenGL程序框架",640,480,16,fullscreen))
    {
        return 0;                            // 失败退出
    }

下面是循环的开始。只要done保持FALSE,循环一直进行。

    while(!done)                                // 保持循环直到 done=TRUE
    {

我们要做的第一件事是检查是否有消息在等待。使用PeekMessage()可以在不锁住我们的程序的前提下对消息进行检查。许多程序使用GetMessage(),也可以很好的工作。但使用GetMessage(),程序在收到paint消息或其他别的什么窗口消息之前不会做任何事。

        if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))            // 有消息在等待吗?
        {

下面的代码查看是否出现退出消息。如果当前的消息是由PostQuitMessage(0)引起的WM_QUIT,done变量被设为TRUE,程序将退出。

            if (msg.message==WM_QUIT)                // 收到退出消息?
            {
                done=TRUE;                    // 是,则done=TRUE
            }
            else                            // 不是,处理窗口消息
            {

如果不是退出消息,我们翻译消息,然后发送消息,使得WndProc() 或 Windows能够处理他们。

                TranslateMessage(&msg);                // 翻译消息

                DispatchMessage(&msg);                // 发送消息
            }
        }
        else                                // 如果没有消息
        {

如果没有消息,绘制我们的OpenGL场景。代码的第一行查看窗口是否激活。如果按下ESC键,done变量被设为TRUE,程序将会退出。

            // 绘制场景。监视ESC键和来自DrawGLScene()的退出消息

            if (active)                        // 程序激活的么?
            {
                if (keys[VK_ESCAPE])                // ESC 按下了么?
                {
                    done=TRUE;                // ESC 发出退出信号
                }
                else                        // 不是退出的时候,刷新屏幕
                {

如果程序是激活的且ESC没有按下,我们绘制场景并交换缓存(使用双缓存可以实现无闪烁的动画)。我们实际上在另一个看不见的"屏幕"上绘图。当我们交换缓存后,我们当前的屏幕被隐藏,现在看到的是刚才看不到的屏幕。这也是我们看不到场景绘制过程的原因。场景只是即时显示。

                    DrawGLScene();                // 绘制场景

                    SwapBuffers(hDC);            // 交换缓存 (双缓存)
                }
            }

下面的一点代码是最近新加的(05-01-00)。允许用户按下F1键在全屏模式和窗口模式间切换。

            if (keys[VK_F1])                    // F1键按下了么?
            {
                keys[VK_F1]=FALSE;                // 若是,使对应的Key数组中的值为 FALSE

                KillGLWindow();                    // 销毁当前的窗口

                fullscreen=!fullscreen;                // 切换 全屏 / 窗口 模式

                // 重建 OpenGL 窗口

                if (!CreateGLWindow("NeHe‘s OpenGL 程序框架",640,480,16,fullscreen))
                {
                    return 0;                // 如果窗口未能创建,程序退出
                }
            }
        }
    }

如果done变量不再是FALSE,程序退出。正常销毁OpenGL窗口,将所有的内存释放,退出程序。

    // 关闭程序

    KillGLWindow();                                // 销毁窗口

    return (msg.wParam);                            // 退出程序
}

在这一课中,我已试着尽量详细解释一切。每一步都与设置有关,并创建了一个全屏OpenGL程序。当您按下ESC键程序就会退出,并监视窗口是否激活。我花了整整2周时间来写代码,一周时间来改正BUG并讨论编程指南,2天( 整整22小时来写HTML文件)。如果您有什么意见或建议请给我EMAIL。如果您认为有什么不对或可以改进,请告诉我。我想做最好的OpenGL教程并对您的反馈感兴趣。

时间: 2024-10-12 08:13:19

第01课 OpenGL窗口(4)的相关文章

第01课 OpenGL窗口(3)

接下来的代码段创建我们的OpenGL窗口.我花了很多时间来做决定是否创建固定的全屏模式这样不需要许多额外的代码,还是创建一个容易定制的友好的窗口但需要更多的代码.当然最后我选择了后者.我经常在EMail中收到诸如此类的问题:怎样创建窗口而不使用全屏幕?怎样改变窗口的标题栏?怎样改变窗口的分辨率或pixel format(象素格式)?以下的代码完成了所有这一切!尽管最好要学学材质,这会让您写自己的OpenGL程序变得容易的多! 正如您所见,此过程返回布尔变量(TRUE 或 FALSE).他还带有5

第01课 OpenGL窗口(1)

教程的这一节在2000年一月彻底重写了一遍.将会教您如何设置一个 OpenGL窗口.它可以只是一个窗口或是全屏幕的.可以任意 大小.任意色彩深度.此处的代码很稳定且很强大,您可以在您所有的OpenGL项目中使用.我所有的教程都将基于此节的代码!所有的错误都有被报告.所以应该没有内存泄漏,代码也很容易阅读和修改.感谢Fredric Echols对代码所做的修改! 现在就让我们直接从代码开始吧.第一件事是打开VC然后创建一个新工程.如果您不知道如何创建的话,您也许不该学习OpenGL,而应该先学学V

第02课 OpenGL 多边形

你的第一个多边形: 在第一个教程的基础上,我们添加了一个三角形和一个四边形.也许你认为这很简单,但你已经迈出了一大步,要知道任何在OpenGL中绘制的模型都会被分解为这两种简单的图形.读完了这一课,你会学到如何在空间放置模型,并且会知道深度缓存的概念. 第一课中,我教您如何创建一个OpenGL窗口.这一课中,我将教您如何创建三角形和四边形.我们讲使用来创建GL_TRIANGLES一个三角形,GL_QUADS来创建一个四边形. 在第一课代码的基础上,我们只需在DrawGLScene()过程中增加代

第04课 OpenGL 旋转

旋转: 在这一课里,我将教会你如何旋转三角形和四边形.左图中的三角形沿Y轴旋转,四边形沿着X轴旋转. 上一课中我教给您三角形和四边形的着色.这一课我将教您如何将这些彩色对象绕着坐标轴旋转.其实只需在上节课的代码上增加几行就可以了.下面我将整个例程重写一遍.方便您知道增加了什么,修改了什么.我们增加两个变量来控制这两个对象的旋转.这两个变量加在程序的开始处其他变量的后面( bool fullscreen=TRUE;下面的两行).它们是浮点类型的变量,使得我们能够非常精确地旋转对象.浮点数包含小数位

第03课 OpenGL 添加颜色

添加颜色: 作为第二课的扩展,我将叫你如何使用颜色.你将理解两种着色模式,在下图中,三角形用的是光滑着色,四边形用的是平面着色 上一课中我教给您三角形和四边形的绘制方法.这一课我将教您给三角形和四边形添加2种不同类型的着色方法.使用Flat coloring(单调着色)给四边形涂上固定的一种颜色.使用Smooth coloring(平滑着色)将三角形的三个顶点的不同颜色混合在一起,创建漂亮的色彩混合. 继续在上节课的DrawGLScene例程上修改.下面将整个例程重写了一遍.如果您计划修改上节课

第09课 OpenGL 移动图像

3D空间中移动图像: 你想知道如何在3D空间中移动物体,你想知道如何在屏幕上绘制一个图像,而让图像的背景色变为透明,你希望有一个简单的动画.这一课将教会你所有的一切.前面的课程涵盖了基础的OpenGL,每一课都是在前一课的基础上创建的.这一课是前面几课知识的综合,当你学习这课时,请确保你已经掌握了前面几课的知识. 欢迎进入第九课.到现在为止,您应该很好的理解OpenGL了.『CKER:如果没有的话,一定是我翻译的罪过......』.您已经学会了设置一个OpenGL窗口的每个细节.学会在旋转的物体

智慧解析第01课:九鼎

智慧解析第01课:九鼎,布布扣,bubuko.com

Qt4.3.4下面创建一个OpenGL 窗口

直接上代码: NeHeWidget.h #include <QtOpenGL/qgl.h> class NeHeWidget:public QGLWidget { Q_OBJECT public: NeHeWidget( QWidget* parent=0 ); ~NeHeWidget(); protected: void initializeGL(); void paintGL(); void resizeGL(int width,int height); }; NeHeWidget.cpp

[转]用多线程方法实现在MFC/WIN32中调用OpenGL函数并创建OpenGL窗口

原文链接: 1.用多线程方法实现在MFC/WIN32中调用OpenGL函数并创建OpenGL窗口 2.Windows MFC 两个OpenGL窗口显示与线程RC问题 原文地址:https://www.cnblogs.com/rainbow70626/p/8973440.html