65.9K
CodeProject 正在变化。 阅读更多。
Home

通用 Win32 项目中所有课程的集中

2014年2月4日

CPOL

7分钟阅读

viewsIcon

33125

downloadIcon

525

OpenGL 教程和课程的支持

引言

大约三个月前,我发表了关于集成到 Visual C++ MFC 项目中的课程的文章。令我有些惊讶的是,我发现很多人对 MFC 这个词感到恐慌(有人甚至称之为厌恶)。尽管如此,OpenGL 课程的想法很好,并且本网站提供的代码适用于任何版本的软件。因此,我也为 Win32 Visual C++ Visual Studio 2010-2012 专业版做了同样的工作。

我相信将所有课程集中在一个通用项目中,对于所有初学者开始学习 OpenGL 应该非常有帮助。这些课程的代码一个接一个地紧密排列,展示了从上一阶段到下一阶段的程序进展。此外,将所有课程集成到一个通用项目中,使得可以使用和组合不同课程的程序,并可以基于原始课程开发新应用程序。

在将代码适配到现代版本的 Visual C++ 时,我发现从一个版本的 MS Visual Studio 修改到另一个版本的项目中出现了一些冲突。最后,为了演示目的,我开发了项目 OpenGLWin32_2010。这里的 2010 意味着该项目是为 Microsoft Visual Studio Professional 2010 开发的。尽管如此,所有项目都可以轻松地升级到 2012 版本,但该版本需要 Windows 7,而 2010 版本适用于 Windows XP SP3 及更高版本。

上述项目的开发得到了 NeHe 俄罗斯网站编辑 Sergey Anisimov 的大力帮助,我非常感谢他的善意协助。

上述代码对于想要从头开始学习 Visual C++ 的人来说将是一个巨大的帮助。毋庸置疑,学习任何编译器最好的方法是从一些可运行的项目开始。本课程的演示参考 Visual Studio 2010 专业版。但是,在 2012 版本中不会出现太多差异。

OpenGLWin32_2010 目录的内容如下

  • OpenGLWin32 - 包含所有课程项目的空项目
  • Lesson01..X5 - 每个单独课程的项目
  • GLSummary - 包含所有课程的项目
  • Data - 所有课程的源数据
  • NeHeProgs - 课程的主要和辅助代码
  • GlobUse - 所有课程通用的程序
  • DemoLessons - 所有课程的所有可执行文件
  • HelpText - 所有课程的帮助和信息文件

要查看和编辑代码,请启动 OpenGLWin32.sln 文件。即使您没有使用 Visual C++ 的经验,也可以通过启动此项目(或任何其他包含的项目)来开始学习。

项目中所使用的程序列表可通过菜单“视图”->“解决方案资源管理器”找到。只需选择任何 *.h*.cpp 文件,即可查看和编辑。乍一看,可能觉得包含的文件太多,但进一步考虑后会发现一切并非过于复杂。

要构建所有项目,只需启动构建(菜单“构建”->“构建解决方案”)。如果一切正确,输出窗口中的报告结果必须是:49 个成功,3 个失败,0 个跳过。

失败的项目是 OpenGLWin32 本身(它没有入口点)以及 Lesson43/Lesson47。遗憾的是,我对 OpenGL 的处理经验不足,其中两个课程未能成功适配到 Visual C++ 的现代版本。我希望原始代码的作者们能轻松改进我的代码,使其完全符合他们的初衷。

要启动任何项目,只需将其指定为启动项目(右键单击鼠标 - 菜单“指定为启动项目”)并选择菜单“调试”->“不带调试启动”。如果一切正常,将开始演示相应的课程。如果您将 GLSummary 项目指定为启动项目,则将启动其中一个课程(其名称存储在 LessonsGL/GLSummary 目录下的 LastNum.txt 文件中)。对于任何其他课程演示,请选择菜单“文件”->“课程...”,然后将出现“选择课程”对话框。

您可以从列表中选择任何其他课程进行演示。如果您从单个课程开始工作,程序会调用所选课程,然后自行终止。如果您从 GLSummary 开始,程序只会调用包含的所选课程。Lesson43/Lesson47 也可启动,但您不能从它们调用其他课程:它们是原始的 .exe 文件。

用于创建独立应用程序

  • 创建一个新目录(例如,GLTest);
  • 将所有 *.exe 程序(位于 ../lesson*/Release../GLSummary/Release 目录中)复制到这个新目录;
  • DataHelpText 目录复制到这个新目录中,然后应用程序就可以使用了,它们必须与 DemoLessons 目录中的程序完全一样运行。

CreateGLWindowResizeGLSceneWndProcGlobWinMain 程序是所有课程通用的,位于 GlobUse/GLRoutine.cpp 文件中。

CreateGLWindow 程序与 NeHe 教程中的原始程序几乎相同。

ResizeGLScene 过程中发生了一些修改

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)      // Resize And Initialize The GL Window
{
        if (height==0)                                      // Prevent A Divide By Zero By
        {
               height=1;                                       // Making Height Equal One
        }
        glViewport(0,0,width,height);                       // Reset The Current Viewport
 
        glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
        glLoadIdentity();                                   // Reset The Projection Matrix
 
if(m_bOrtho)
         glOrtho(0.0f,width,height,0.0f,-1.0f,1.0f);        // Create Ortho View (0,0 At Top Left)
else
        // Calculate The Aspect Ratio Of The Window
        gluPerspective(fViewAngle,(GLfloat)width/(GLfloat)height,fNearPlane,fFarPlane);
        glMatrixMode(GL_MODELVIEW);                         // Select The Modelview Matrix
        glLoadIdentity();                                   // Reset The Modelview Matrix
 
HWND hWin = GetDlgItem(hWnd, IDC_MAIN_TOOL);
if(hWin != NULL)
{                                                       //ToolBar Adjusted to Main window
        RECT rect;
    GetWindowRect(hWin, &rect);  
        BOOL bVisible = IsWindowVisible(hWin);
        MoveWindow(hWin, rect.left, rect.top, rect.bottom - rect.top, width, TRUE);                                         
}                                             
 
HWND  hSt = GetDlgItem(hWnd, IDC_MAIN_STATUS);
if(hSt != NULL)
{                                                       //StatusBar Adjusted to Main window
        RECT rect;
    GetWindowRect(hSt, &rect);  
        BOOL bVisible = IsWindowVisible(hSt);
        MoveWindow(hSt, rect.left, height + rect.top - rect.bottom, rect.bottom - rect.top, width, TRUE);                                                
}                                             

m_boxWidth =  width;    //remember thr current width and height in global variables. 
m_boxHeight = height;
}

gluPerspective 过程中,出现了全局变量 fViewAngle, fNearPlane, fFarPlane。在大多数课程中,将使用默认值。

fViewAngle = 45; fNearPlane = <st1:metricconverter
ProductID="0.1f" w:st="on">0.1f</st1:metricconverter>; fFarPlane = 100;

将使用。然而,在第30、31、34、36、44、45、46课中,这些值需要改变。

此外,全局变量 m_bOrtho 根据需要(第 21 和 24 课)安排 glOrtho 的性能。

TollBarStatusBarResizeGLScene 期间调整到主窗口。

由于额外的对话框和条形处理,WndProcGlobWinMain 过程也发生了一些变化。您可以在 GlobUse/GLRoutine.cpp 中查看这些变化 - 没什么特别的,只是常规操作。

与原始课程不同,同时按下 Ctrl+Enter 键可实现全屏显示。

F1 键与原始课程不同,用于调用帮助的标准目的(菜单“帮助”->“帮助对话框...”)

“帮助对话框”窗口是非模态的,因此程序处理既可以从该窗口进行,也可以通过其他方式进行。所有帮助信息都以纯文本文件的形式存储在 HelpText 目录中。

关于原始代码的作者们,关于对话框(菜单“帮助”->“关于...”)包含原始 NeHe 的 ReadMe 文本。

About Dialog 也可通过“关于...”按钮从其他“课程”和“帮助对话框”中访问。

与原始课程的另一个不同之处在于,所有纹理过程都集成在 GlobUse 目录下的 GlobGLTexture.cpp 文件中。我没有使用 auxDIBImageLoad 进行纹理加载,而是使用 CImage 类安排了如下过程:

HBITMAP GetImgBitmap(CImage * nImg)
{
 
        if(nImg == NULL)
           return NULL;
 
        CImage * pImg = new CImage;
        pImg->Create(nImg->GetWidth(),nImg->GetHeight(), 24);
        nImg->BitBlt(pImg->GetDC(),CPoint(0,0));
 
        HDC hdc = CreateCompatibleDC(pImg->GetDC());
        HBITMAP hbm = CreateCompatibleBitmap(pImg->GetDC(), pImg->GetWidth(), pImg->GetHeight());
 
        HBITMAP bmOld = (HBITMAP) SelectObject(hdc,hbm);
        pImg->BitBlt(hdc, CPoint(0,0));
 
        pImg->ReleaseDC();
        delete pImg;
 
        return hbm;
}
//////////////////////////////////////////////////////////////////////////
HBITMAP LoadMyBitmap(char * fName)
{
          if(!isFileExist(fName))
          {
                 char strk[_MAX_PATH];
                 _getcwd(str, _MAX_PATH);
                 sprintf_s(strk, "LoadMyBitmap\nNo File exist:\n%s\nin Directory:\n%s", fName, str);
                 MessageBox(NULL, strk, "No File:", MB_OK | MB_ICONINFORMATION); 
                 return NULL;
          }
  CImage * pImg = new CImage; 
   pImg->Load(fName);
 
   HBITMAP bm = GetImgBitmap(pImg);
               delete pImg;
    pImg = NULL;
  return bm;
}
//////////////////////////////////////////////////////////////////////////////

您可以复制 GlobGLTexture.cpp 文件,并将其用于任何使用 OpenGL 开发的各种图像文件项目,只要 Windows 支持这些文件。

课程代码本身集中在 NeHeProgs 目录中,并根据课程编号以 "01_"、"02_"、..."X5_" 开头。这些是 NeHe 的 GameDev 网站(Grant James)中提供的代码,我尽力在适配到现代版本的 Visual Studio 时不更改代码。

唯一的巨大区别是我敢于从所有项目中排除 Glaux.lib 库。尽管如此,我希望原始代码的作者们不会抱怨。他们当然不可能期望 MS VS 开发人员从第 10 版开始就排除 Glaux.lib 库。而且,即使仍然可以在 MS VS 第 10 版中包含 Glaux.lib,但在第 11 版中,它将不再工作。

所有程序集中在一个公共目录 GlobUse 中,使得可以在单独的课程中使用和组合通用程序,并可以基于原始课程开发新应用程序。应用程序开发的示例在项目 lessonX4/UFOgame 和 lessonX5/BoxMan 中呈现。Lesson X4.UFO Games 结合了课程 07、11、30、32、34。Lesson X5.BoxMan 演示了在外部文本文件中创建图形及其移动的可能性,用户无需了解程序员细节,只需空间想象力就足够了。

而 LessonX5 展示了一个由于同时使用 <windows.h><afxwin.h> 而引发的问题。冲突在“属性窗口配置属性”->“链接器”->“常规”->“强制输出”中被弃用。错误已消除,但警告仍然存在,并且生成的 EXE 文件非常大。在 MFC 平台上,没有出现任何问题。

我认为借助现有的工作项目来学习 OpenGL 的想法,完全符合人们对 OpenGL 的教程需求。我希望所提供的项目能为 OpenGL 的教程和课程提供良好的支持。

© . All rights reserved.