win32程序在GCC中编译,但不是G ++ HDC错误

win32 program compiles in GCC but not G++ HDC error

本文关键字:错误 HDC 程序 GCC 编译 win32      更新时间:2023-10-16

我有一个简单的win32程序,用于基本的opengl绘图。它将使用 gcc 编译,但如果我使用 g++ 它会给我错误:

minimal.c: In function 'HWND__* CreateOpenGLWindow(char*, int, int, int, int, BYTE, DWORD)':
minimal.c:130:24: error: cannot convert 'HDC {aka HDC__*}' to 'HWND {aka HWND__*}' for argument '1' to 'int ReleaseDC(HWND, HDC)'
     ReleaseDC(hDC, hWnd);
                        ^
minimal.c: In function 'int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)':
minimal.c:160:24: error: cannot convert 'HDC {aka HDC__*}' to 'HWND {aka HWND__*}' for argument '1' to 'int ReleaseDC(HWND, HDC)'
     ReleaseDC(hDC, hWnd);

我不知道为什么它会使用 gcc 编译但在我使用 g++ 时失败?

这是代码:

#include <windows.h>            /* must include this before GL/gl.h */
#include <GL/gl.h>          /* OpenGL header file */
#include <GL/glu.h>         /* OpenGL utilities header file */
#include <stdio.h>

void
display()
{
    /* rotate a triangle around */
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_TRIANGLES);
    glColor3f(1.0f, 0.0f, 0.0f);
    glVertex2i(0,  1);
    glColor3f(0.0f, 1.0f, 0.0f);
    glVertex2i(-1, -1);
    glColor3f(0.0f, 0.0f, 1.0f);
    glVertex2i(1, -1);
    glEnd();
    glFlush();
}
LONG WINAPI
WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ 
    static PAINTSTRUCT ps;
    switch(uMsg) {
    case WM_PAINT:
    display();
    BeginPaint(hWnd, &ps);
    EndPaint(hWnd, &ps);
    return 0;
    case WM_SIZE:
    glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
    PostMessage(hWnd, WM_PAINT, 0, 0);
    return 0;
    case WM_CHAR:
    switch (wParam) {
    case 27:            /* ESC key */
        PostQuitMessage(0);
        break;
    }
    return 0;
    case WM_CLOSE:
    PostQuitMessage(0);
    return 0;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam); 
} 

HWND
CreateOpenGLWindow(char* title, int x, int y, int width, int height, 
           BYTE type, DWORD flags)
{
    int         pf;
    HDC         hDC;
    HWND        hWnd;
    WNDCLASS    wc;
    PIXELFORMATDESCRIPTOR pfd;
    static HINSTANCE hInstance = 0;
    /* only register the window class once - use hInstance as a flag. */
    if (!hInstance) {
    hInstance = GetModuleHandle(NULL);
    wc.style         = CS_OWNDC;
    wc.lpfnWndProc   = (WNDPROC)WindowProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = NULL;
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = "OpenGL";
    if (!RegisterClass(&wc)) {
        MessageBox(NULL, "RegisterClass() failed:  "
               "Cannot register window class.", "Error", MB_OK);
        return NULL;
    }
    }
    hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW |
            WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
            x, y, width, height, NULL, NULL, hInstance, NULL);
    if (hWnd == NULL) {
    MessageBox(NULL, "CreateWindow() failed:  Cannot create a window.",
           "Error", MB_OK);
    return NULL;
    }
    hDC = GetDC(hWnd);
    /* there is no guarantee that the contents of the stack that become
       the pfd are zeroed, therefore _make sure_ to clear these bits. */
    memset(&pfd, 0, sizeof(pfd));
    pfd.nSize        = sizeof(pfd);
    pfd.nVersion     = 1;
    pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | flags;
    pfd.iPixelType   = type;
    pfd.cColorBits   = 32;
    pf = ChoosePixelFormat(hDC, &pfd);
    if (pf == 0) {
    MessageBox(NULL, "ChoosePixelFormat() failed:  "
           "Cannot find a suitable pixel format.", "Error", MB_OK); 
    return 0;
    } 
    if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
    MessageBox(NULL, "SetPixelFormat() failed:  "
           "Cannot set format specified.", "Error", MB_OK);
    return 0;
    } 
    DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
    ReleaseDC(hDC, hWnd);
    return hWnd;
}    

int APIENTRY
WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,
    LPSTR lpszCmdLine, int nCmdShow)
{
    HDC hDC;                /* device context */
    HGLRC hRC;              /* opengl context */
    HWND  hWnd;             /* window */
    MSG   msg;              /* message */
    hWnd = CreateOpenGLWindow("minimal", 0, 0, 256, 256, PFD_TYPE_RGBA, 0);
    if (hWnd == NULL)
    exit(1);
    hDC = GetDC(hWnd);
    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);
    ShowWindow(hWnd, nCmdShow);
    while(GetMessage(&msg, hWnd, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    wglMakeCurrent(NULL, NULL);
    ReleaseDC(hDC, hWnd);
    wglDeleteContext(hRC);
    DestroyWindow(hWnd);
    return msg.wParam;
}

有人可以解释为什么 g++ 的编译器会产生 HWND HDC 错误,而 gcc 编译器接受代码吗?

ReleaseDC(hDC, hWnd);

应该是

ReleaseDC(hWnd, hDC);
不同类型的

HANDLE(HWNDHDC等(是使用DECLARE_HANDLE()宏声明的。定义STRICT时,它具有以下定义:

#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name

g++ 似乎隐式地定义了这一点,因为允许交换不同句柄类型的 DECLARE_HANDLE() 版本要求不定义STRICT,在这种情况下,DECLARE_HANDLE()有这个定义:

#define DECLARE_HANDLE(name) typedef HANDLE name

您以错误的顺序调用ReleaseDC()参数。第一个参数是HWND;第二个参数是 HDC 。仔细阅读文档。 STRICT旨在防止此类编码错误。

顺便说一下,这也意味着您的hDC是永久分配的。

如果需要在C++代码中的句柄类型之间进行转换(不太可能需要合法的理由(,则需要类似以下内容:

HWND hWnd = reinterpret_cast<HWND>(hDC);