无边框窗口和桌面尺寸相同时闪烁

时间:2014-04-17 23:36:20

标签: windows winapi opengl borderless

我正在尝试使用OpenGL视口创建borderless window that fills the screen。问题是,当我将窗口和视口设置为与桌面大小相同时,窗口会在丢失和获得焦点,退出和创建时闪烁黑色。这可能与Windows将窗口设置为某种类型的真正“全屏”模式有关。在使用这种无边框全屏窗口的其他应用程序(DirectX?)中似乎不会发生这种情况。

我相信SFML has/had a variant of this problem

有一种解决方法:不要将窗口设置为桌面的确切大小。例如,使窗口的宽度比桌面的宽度大一个像素。

下面是SSCCE,没有错误检查,显示我正在谈论的内容。这将创建一个无边框的全屏窗口,其桌面大小的OpenGL视口显示丑陋的绿色(使用 Alt F4 退出)。您可以将行#define FIX_BUG 0更改为#define FIX_BUG 1,只需在窗口的宽度上添加一个额外的像素即可查看我想要的行为。

#define WIN32_LEAN_AND_MEAN
#include "windows.h"

#pragma comment(lib, "OpenGL32.lib")

#define FIX_BUG 0

void MyRegisterClass(HINSTANCE hInstance);
HWND MyCreateWindow(HINSTANCE hInstance);
void MySetupOpenGLContext(HWND hWnd);
void MySetPixelFormat(HDC hDC);
RECT MyGetDesktopRect();
void MyLoadOpenGLFunctions();

#define APIENTRYP APIENTRY *
#define GLAPI extern
#define GL_COLOR 0x1800

typedef int GLint;
typedef int GLsizei;
typedef unsigned int GLenum;
typedef float GLfloat;

typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
PFNGLVIEWPORTPROC glViewport;

typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
PFNGLCLEARBUFFERFVPROC glClearBufferfv;

static const char *windowClass = "CLASS";
static const char *windowTitle = "TITLE";

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
    MyRegisterClass(hInstance);
    const HWND hWnd = MyCreateWindow(hInstance);
    MySetupOpenGLContext(hWnd);
    ShowWindow(hWnd, nCmdShow);
    HDC hDC = GetDC(hWnd);

    MSG msg;
    while (IsWindow(hWnd)) {
        while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)) DispatchMessage(&msg);

        const GLfloat color[] = {0.5f, 0.5f, 0.0f, 1.0f};
        glClearBufferfv(GL_COLOR, 0, color);

        SwapBuffers(hDC);
    }

    return 0;
}

void MyRegisterClass(HINSTANCE hInstance) {
    WNDCLASSEX wcex = {0};

    wcex.cbSize = sizeof wcex;
    wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wcex.lpfnWndProc = &DefWindowProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH) (COLOR_WINDOWFRAME + 1);
    wcex.lpszClassName = windowClass;

    RegisterClassEx(&wcex);
}

HWND MyCreateWindow(HINSTANCE hInstance) {
    RECT dRect = MyGetDesktopRect();
    return CreateWindow(windowClass, windowTitle, WS_POPUP,
                        0, 0, dRect.right + FIX_BUG, dRect.bottom,
                        NULL, NULL, hInstance, NULL);
}

void MySetupOpenGLContext(HWND hWnd) {
    HDC hDC = GetDC(hWnd);
    MySetPixelFormat(hDC);
    HGLRC hGLRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hGLRC);
    MyLoadOpenGLFunctions();
    RECT dRect = MyGetDesktopRect();
    glViewport(0, 0, dRect.right, dRect.bottom);
}

void MySetPixelFormat(HDC hDC) {
    PIXELFORMATDESCRIPTOR pfd = {0};

    pfd.nSize = sizeof pfd;
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int format = ChoosePixelFormat(hDC, &pfd);
    SetPixelFormat(hDC, format, &pfd);
}

RECT MyGetDesktopRect() {
    RECT desktopRect;
    const HWND hDesktop = GetDesktopWindow();
    GetWindowRect(hDesktop, &desktopRect);
    return desktopRect;
}

void MyLoadOpenGLFunctions() {
    glViewport = (PFNGLVIEWPORTPROC) GetProcAddress(GetModuleHandleA("OpenGL32.dll"), "glViewport");
    glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) wglGetProcAddress("glClearBufferfv");
}

Github Gist | Raw Text

为什么会这样?有没有办法通过将窗口设置为桌面的确切大小来获得我想要的行为?

我的平台:Visual Studio 2013/64位Windows 8 / AMD Radeon HD6850。

0 个答案:

没有答案