windows 未打开窗口的 OpenGL 上下文 - 使用由 GetDesktopWindow 制作的 HWND 时,wglMakeCurrent 因 HDC 和 HGLRC 失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/714707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:15:22  来源:igfitidea点击:

OpenGL context without opening a window - wglMakeCurrent fails with HDC and HGLRC when using HWND made with GetDesktopWindow

c++windowsopengl

提问by Keyframe

This is somewhat a duplicate of this question.

这有点重复这个问题

I am trying to make a windowless console application to check up on OpenGL version supported. In order to do this I need to set up a render context - but without creating a window. I am trying to use desktop handle, which I won't write to.

我正在尝试制作一个无窗口控制台应用程序来检查支持的 OpenGL 版本。为了做到这一点,我需要设置一个渲染上下文——但不创建窗口。我正在尝试使用桌面句柄,我不会写信给它。

I forgot to set pixel format in previous example - that is probable reason why creation of render context failed - however even with pixel format set, I cannot activate it. wglMakeCurrent(hDC, hRC) just returns 0.

我忘记在前面的例子中设置像素格式——这可能是创建渲染上下文失败的原因——但是即使设置了像素格式,我也无法激活它。wglMakeCurrent(hDC, hRC) 只返回 0。

Here is the complete source code dump:

这是完整的源代码转储:

    #include <iostream>
    #include <GL/GLee.h>

    #include <windows.h>

HDC hDC = NULL;
HGLRC hRC = NULL;
HWND hWnd = NULL;
HINSTANCE hInstance;

int res = 0;
int pf = 0;
PIXELFORMATDESCRIPTOR pfd = {
    sizeof(PIXELFORMATDESCRIPTOR),
    1,                     /* version */
    PFD_DRAW_TO_WINDOW |
    PFD_SUPPORT_OPENGL |
    PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    24,                    /* 24-bit color depth */
    0, 0, 0, 0, 0, 0,      /* color bits */
    0,                     /* alpha buffer */
    0,                     /* shift bit */
    0,                     /* accumulation buffer */
    0, 0, 0, 0,            /* accum bits */
    32,                    /* z-buffer */
    0,                     /* stencil buffer */
    0,                     /* auxiliary buffer */
    PFD_MAIN_PLANE,        /* main layer */
    0,                     /* reserved */
    0, 0, 0                /* layer masks */
};


std::string trash;

int main(int argc, char**argv) {

hInstance = GetModuleHandle(NULL);  // Grab An Instance For Our Window

hWnd = GetDesktopWindow();          // Instead of CreateWindowEx

if (!(hDC = GetDC(hWnd))) {
    std::cout << "Device context failed" << std::endl;

    std::cout << std::endl << "Press ENTER to exit" << std::endl;
    std::getline(std::cin, trash);
    return 1;
}

// pixel format
pf = ChoosePixelFormat(hDC, &pfd);
res = SetPixelFormat(hDC, pf, &pfd);

if (!(hRC = wglCreateContext(hDC))) {
    std::cout << "Render context failed" << std::endl;

    std::cout << std::endl << "Press ENTER to exit" << std::endl;
    std::getline(std::cin, trash);
    return 1;
}

if(!wglMakeCurrent(hDC,hRC)) { // fail: wglMakeCurrent returns 0
    std::cout << "Activating render context failed" << std::endl;

    std::cout << std::endl << "Press ENTER to exit" << std::endl;
    std::getline(std::cin, trash);
    return 1;
}

std::cout << "OpenGL 1.2 support ... ";
if (GLEE_VERSION_1_2) {
    std::cout << "OK" << std::endl;
} else {
    std::cout << "FAIL" << std::endl;
}

std::cout << "OpenGL 1.3 support ... ";
if (GLEE_VERSION_1_3) {
    std::cout << "OK" << std::endl;
} else {
    std::cout << "FAIL" << std::endl;
}

std::cout << "OpenGL 1.4 support ... ";
if (GLEE_VERSION_1_4) {
    std::cout << "OK" << std::endl;
} else {
    std::cout << "FAIL" << std::endl;
}

std::cout << "OpenGL 1.5 support ... ";
if (GLEE_VERSION_1_5) {
    std::cout << "OK" << std::endl;
} else {
    std::cout << "FAIL" << std::endl;
}

std::cout << "OpenGL 2.0 support ... ";
if (GLEE_VERSION_2_0) {
    std::cout << "OK" << std::endl;
} else {
    std::cout << "FAIL" << std::endl;
}

std::cout << "OpenGL 2.1 support ... ";
if (GLEE_VERSION_2_1) {
    std::cout << "OK" << std::endl;
} else {
    std::cout << "FAIL" << std::endl;
}

std::cout << "OpenGL 3.0 support ... ";
if (GLEE_VERSION_3_0) {
    std::cout << "OK" << std::endl;
} else {
    std::cout << "FAIL" << std::endl;
}

std::cout << std::endl << "Press ENTER to exit" << std::endl;
std::getline(std::cin, trash);

// cleanup
wglMakeCurrent(NULL, NULL);     /* make our context not current */
wglDeleteContext(hRC);      /* delete the rendering context */
ReleaseDC(hWnd, hDC);               /* release handle to DC */

return 0;

}

}



edit:I know that wglMakeCurrent() fails if either of the handles passed to it is invalid or if the rendering context that is to become current is presently current for another thread, but I am not really sure which of these is true in this case.

编辑:我知道 wglMakeCurrent() 如果传递给它的任何一个句柄无效,或者如果要变为当前的渲染上下文当前对于另一个线程来说是当前的,则 wglMakeCurrent() 会失败,但我不确定在这种情况下哪些是正确的.

回答by datenwolf

One must not create a OpenGL context on the desktop window. To create a OpenGL context, one must set the windows's pixelformat, which is strictly forbidden to be done on the desktop window.

不得在桌面窗口上创建 OpenGL 上下文。要创建一个 OpenGL 上下文,必须设置窗口的像素格式,这是严格禁止在桌面窗口上进行的。

If you want to do offscreen rendering, use a PBuffer instead of a window, or create a window you don't make visible and use a Frame Buffer Object (FBO) as render target.

如果要进行离屏渲染,请使用 PBuffer 而不是窗口,或者创建一个不可见的窗口并使用帧缓冲区对象 (FBO) 作为渲染目标。

回答by Keyframe

Does it work if you use CreateWindow() rather than GetDesktopWindow()?

如果您使用 CreateWindow() 而不是 GetDesktopWindow() 是否有效?

I would say GetDesktopWindow() is extremely unlikely to work. I would expect that to be unlike a normal window and the value you receive to be a special handle value.

我会说 GetDesktopWindow() 极不可能工作。我希望这与普通窗口不同,并且您收到的值是一个特殊的句柄值。

If push comes to shove, just open a window without WS_VISIBLE. No one will be the wiser.

如果迫不得已,只需打开一个没有 WS_VISIBLE 的窗口。没有人会更聪明。

P.s. I note you're making this a console application. I will be quite surprised if console applications work with anything graphical, be it OpenGL or just the Windows 2D drawing API.

Ps 我注意到你正在把它作为一个控制台应用程序。如果控制台应用程序可以处理任何图形,无论是 OpenGL 还是 Windows 2D 绘图 API,我都会感到非常惊讶。

P.s.s I'm pretty sure Windows applications can write (one way or another) to the stdout of the command line they're run from. You could simply write a normal windows app, but just emit your output to stdout.

Pss 我很确定 Windows 应用程序可以(以一种或另一种方式)写入它们运行的​​命令行的标准输出。您可以简单地编写一个普通的 Windows 应用程序,但只需将您的输出发送到 stdout。