1

假设我从codeguru 下载了 COpenGLControl 类,假设创建 OpenGL 窗口时运行的第一个事件处理程序是 OnCreate,我试图赶上这个类的错误。这是用于在我的对话框的 .h 和 .cpp 文件中创建窗口的代码:

MyOpenGLTestDlg.h

COpenGLControl m_oglWindow;  

MyOpenGLTestDlg.cpp

CRect rect;

// Get size and position of the picture control
GetDlgItem(ID_OPENGL)->GetWindowRect(rect);

// Convert screen coordinates to client coordinates
ScreenToClient(rect);  

直到知道我认为该函数OnCreate已被调用。事实上,我认为这行代码COpenGLControl m_oglWindow;会导致调用这个函数!但我不确定,所以如果你能指导我一点,那将不胜感激?
无论如何,我并没有对课程做很多改变:

OpenGLControl.h

#pragma once
#include "afxwin.h"
#include "WinBase.h"

#include <gl/gl.h>
#include <gl/glu.h>

class COpenGLControl : public CWnd
{
public:
    /******************/
    /* Public Members */
    /******************/
    UINT_PTR m_unpTimer;
    // View information variables
    float    m_fLastX;
    float    m_fLastY;
    float    m_fPosX;
    float    m_fPosY;
    float    m_fZoom;
    float    m_fRotX;
    float    m_fRotY;
    bool     m_bIsMaximized;

private:
    /*******************/
    /* Private Members */
    /*******************/
    // Window information
    CWnd  *hWnd;     //window handle
    HDC   hdc;       //device context handle    
    HGLRC hrc;       //handle to GL Rendering Context
    int   m_nPixelFormat;
    CRect m_rect;
    CRect m_oldWindow;
    CRect m_originalRect;

public:
    COpenGLControl(void);
    virtual ~COpenGLControl(void);

    void oglCreate(CRect rect, CWnd *parent);
    void oglInitialize(void);
    void oglDrawScene(void);

    // Added message classes:
    afx_msg void OnPaint();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnDraw(CDC *pDC);
    afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnTimer(UINT nIDEvent);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);

    DECLARE_MESSAGE_MAP()
};  

OpenGL控制.cpp

int COpenGLControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CWnd::OnCreate(lpCreateStruct) == -1) return -1;

    oglInitialize();

    return 0;
}  
void COpenGLControl::oglInitialize(void)
{
    // Initial Setup:
    //
    static PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32, // bit depth
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        24, // z-buffer depth
        8,0,PFD_MAIN_PLANE, 0, 0, 0, 0,
    };

    // Get device context only once.
    hdc = GetDC()->m_hDC;
    // Pixel format.
    m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
    SetPixelFormat(hdc, m_nPixelFormat, &pfd);
    // Create the OpenGL Rendering Context.
    hrc = wglCreateContext(hdc);
    GLenum error13 = glGetError();
    wglMakeCurrent(hdc, hrc);

   // Basic Setup:
   //
   // Set color to use when clearing the background.
   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
   glClearDepth(1.0f);
   // Turn on backface culling
   glFrontFace(GL_CCW);
   glCullFace(GL_BACK);
   // Turn on depth testing
   glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);
   // Send draw request
   OnDraw(NULL);
}  

如您所见,我已经编写了代码GLenum error13 = glGetError();hrc = wglCreateContext(hdc);捕获它抛出的任何可能的错误,是的,error13 的值是1282这意味着INVALID_OPERATION我认为handle for OpenGL rendering context没有正确创建!
此外,如果您检查 and 的值hdchrc您会遇到以下情况:

hdc -> 未使用 = ??? (错误:无法评估表达式)
hrc -> 未使用 = 0

你能帮我找出为什么会这样吗?有什么问题?

4

2 回答 2

2

在 Win32 中的调用线程拥有“当前上下文”之前,不要调用 OpenGL API 函数。操作将是未定义的。

要更正此问题,只需将呼叫移至wglMakeCurrent (...)一行,使其位于对 的呼叫之前glGetError (...)

请注意,您必须为每个线程执行此操作,并且在 Win32 中,在任何给定时间只允许一个线程访问 OpenGL 上下文。如果您想在 Win32 中进行多线程渲染,您将不得不获取/释放上下文并在线程之间进行同步,或者使用一堆“共享列表”(wglShareLists (...))的上下文。

就像 derhass 提到的,如果您想要有关 WGL API 生成的错误的信息,请使用GetLastError (...). WGL 是窗口系统的一部分,它建立在 Win32 API 之上,因此它将通过传统的 Win32 通道将其错误传达给您。


顺便说一句,尽量不要以十进制形式打印 GL 错误值。它们总是在 gl.h 中作为十六进制常量枚举,所以如果你这样做会更容易找到合适的枚举数:

printf ("OpenGL Error: 0x%X\n", err);

OpenGL 中的所有枚举常量也是如此。如果您没有将它们映射到人类可读字符串的函数,则应使用十六进制值来查找它们。

于 2013-08-16T21:24:23.213 回答
2

glGetError()如果您在没有当前 GL 上下文的情况下调用 GL 函数(如其自身),则结果非常不确定。

wglCreateContext()是 Win33 API(而不是 GL API)的一部分,将通过返回一个NULL指针来表示错误。如果您需要这种情况下的详细信息,您可以调用 Windows API 函数GetLastError(),就像大多数其他 Windows API 函数一样。

于 2013-08-16T19:09:09.493 回答