首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有奇怪选项卡问题的无边界OpenGL窗口

带有奇怪选项卡问题的无边界OpenGL窗口
EN

Stack Overflow用户
提问于 2014-03-14 21:42:23
回答 2查看 961关注 0票数 1

我想用Windows创建一个无边界的全屏OpenGL窗口。在许多游戏中都可以看到这一点,这样您就可以在游戏和其他应用程序之间快速切换。

我的问题是,当我创建我的窗口(它起作用了)并退出时,它就会退出,因为我看到我的光标更改为文本编辑器的文本光标,但是我的OpenGL应用程序的屏幕仍然是完全红色的,因此我什么也看不见。

但是,当我在主循环中(或者在主循环之前,但在创建窗口之后)设置一个断点(Visual )时,在交换缓冲区之前,让它在那之后继续,这个问题就解决了。下面是我的主回路。我正在使用我自己的窗口类。

代码语言:javascript
复制
while(window.Running())
{
    window.PollEvents();

    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT);

    window.SwapBuffers();
    Sleep(10);
}

我的问题是:当我在交换缓冲区之前暂停我的应用程序,这会使窗口的行为有所不同(对我来说是正确的)?

window.SwapBuffers()的内部如下:

代码语言:javascript
复制
void GLWindowImpWin32::swapBuffers()
{
    SwapBuffers(handleDeviceContext);
}

handleDeviceContext是我的HDC

此外,按下Windows按钮不会在应用程序前面显示任务栏。

这里是我的最小化源代码,它的行为与我的原始代码相同,如果您在交换缓冲区之前放置一个断点,它也能工作。如果正在编译,请不要忘记链接到opengl32.lib

代码语言:javascript
复制
#include <Windows.h>
#include <gl/GL.h>

WNDCLASSEX windowClass;
HWND handleWindow;
HDC handleDeviceContext;
HGLRC handleGLRenderingContext;
bool running = false;

// set this to your screen size
const int windowWidth = 1680;
const int windowHeight = 1050;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_CREATE:
        {
            handleDeviceContext = GetDC(hWnd);

            PIXELFORMATDESCRIPTOR pfd =
            {
                sizeof(PIXELFORMATDESCRIPTOR),
                1,                              
                PFD_SUPPORT_OPENGL |            
                PFD_DRAW_TO_WINDOW |            
                PFD_DOUBLEBUFFER,       
                PFD_TYPE_RGBA,                  
                32,                             
                0, 0, 0, 0, 0, 0,               
                0,
                0,
                0,
                0, 0, 0, 0,
                16,                             
                8,                              
                0,
                PFD_MAIN_PLANE,
                0,
                0, 0, 0
            };

            int pixelFormat = ChoosePixelFormat(handleDeviceContext, &pfd);
            SetPixelFormat(handleDeviceContext, pixelFormat, &pfd);

            handleGLRenderingContext = wglCreateContext(handleDeviceContext);

            wglMakeCurrent(handleDeviceContext, handleGLRenderingContext);

            running = true;

            break;
        }
    case WM_DESTROY:
    case WM_CLOSE:
        {
            wglMakeCurrent(handleDeviceContext, NULL);
            wglDeleteContext(handleGLRenderingContext);

            running = false;

            break;
        }
    default:
        break;
    }

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

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR cmdLine, int cmdShow)
{
    memset(&windowClass, 0, sizeof(WNDCLASSEX));
    windowClass.cbSize          = sizeof(WNDCLASSEX);
    windowClass.style           = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
    windowClass.cbClsExtra      = 0;
    windowClass.cbWndExtra      = 0;
    windowClass.hInstance       = hInstance;
    windowClass.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
    windowClass.hIconSm         = LoadIcon(NULL, IDI_WINLOGO);
    windowClass.hCursor         = LoadCursor(NULL, IDC_ARROW);
    windowClass.hbrBackground   = NULL;
    windowClass.lpszMenuName    = NULL;
    windowClass.lpszClassName   = "GLWindowClass";
    windowClass.lpfnWndProc     = WndProc;

    if(!RegisterClassEx(&windowClass))
    {
        return false;
    }

    DWORD windowStyleEx = WS_EX_APPWINDOW;
    DWORD windowStyle = WS_POPUP;

    handleWindow = CreateWindow(
        "GLWindowClass",
        "title",
        windowStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,    
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        windowWidth,
        windowHeight,
        NULL,
        NULL,
        hInstance,
        NULL);

    if(!handleWindow)
    {
        return false;
    }

    handleDeviceContext = GetDC(handleWindow);

    ShowWindow(handleWindow, SW_SHOW);

    while(running)
    {
        MSG msg;

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

        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        SwapBuffers(handleDeviceContext);
        Sleep(10);
    }

    PostQuitMessage(0);

    return 0;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-14 23:18:17

缓冲区交换是不够的。您需要告诉windows您已经切换了窗口。为了让“其他应用程序”显示其屏幕,Windows需要知道您的应用程序不再在顶部,其他应用程序应该放在最前面,并允许重新绘制。

编辑/重写:既然您已经为一个示例提供了源代码,并且我已经编译和测试了这些代码,我将进行以下观察。

  1. 我不能重复这个问题。在Windows 8双监视器上,主监视器完全被红色面板所取代,但Alt+Tab和Windows的行为正常。第二个监视器不受影响。我不知道是Windows 8、双显示器还是其他什么东西造成了这种差异。
  2. 所提供的代码假定有一个1680x1050监视器。我的是1920x1080。屏幕高度和宽度必须完全匹配程序才能按预期工作。我编辑了代码来匹配。
  3. 正在使用的DC来自窗口句柄。这意味着所有的OpenGL绘图都将在窗口内。然而,它将不尊重NC边界--它将覆盖整个窗口。
  4. 没有WM_PAINT处理程序,因此Windows可能假定从未绘制过该窗口,并且整个工作区都无效。DefWindowProc将绘制并验证NC区域(如果有的话)。

除了我认为这是问题所在之外,我认为我不能再帮上忙了。您可能想尝试使用不同版本的Windows或双监视器系统。您可能需要尝试添加一个油漆处理程序(它只需要调用BeingPaint/EndPaint)。

票数 0
EN

Stack Overflow用户

发布于 2014-03-14 21:48:51

我不确定这是否有帮助,但尝试将glClear(GL_COLOR_BUFFER_BIT);更改为glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

我觉得这可能很有趣。虽然我对你的案子不太了解

深度缓冲器 深度缓冲器存储每个像素的深度值。正如第五章“隐藏表面清除生存工具包”中所描述的,深度通常是以距离眼睛的距离来衡量的,因此具有较大深度缓冲值的像素被较小值的像素覆盖。然而,这只是一个有用的约定,深度缓冲区的行为可以按照“深度测试”中的描述进行修改。深度缓冲器有时称为z缓冲器(z来自x和y值测量屏幕上的水平和垂直位移,z值测量垂直于屏幕的距离)。

来源:

http://www.glprogramming.com/red/chapter10.html

此外,我认为您应该展示在window.SwapBuffers()中发生的事情;

如果这不管用,很抱歉,但你至少应该试试。

编辑:

我真的认为问题在于睡眠()函数。我试过了,它停止了绘画(虽然还在工作)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22416253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档