2014-05-07 64 views
0

我有以下代码:的OpenGL覆盖Windows的按钮

void DrawGLScene(unsigned char *drawing_bytes, HDC hdc, int xWidth, int yWidth) { 
    if ((!xWidth) || (!yWidth)) return; 

    BOOL returnVal = wglMakeCurrent(hdc, hrc); 

    glBindTexture(GL_TEXTURE_2D, texture); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, xWidth, yWidth, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, drawing_bytes); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 

    glViewport(0,0,xWidth,yWidth);      // Reset The Current Viewport 

    glMatrixMode(GL_PROJECTION);      // Select The Projection Matrix 
    glLoadIdentity();         // Reset The Projection Matrix 

    // Calculate The Aspect Ratio Of The Window 
    gluPerspective(25.0f,1.0f,0.1f,100.0f); 

    glMatrixMode(GL_MODELVIEW);       // Select The Modelview Matrix 
    glLoadIdentity();         // Reset The Modelview Matrix 

    glEnable(GL_TEXTURE_2D);       // Enable Texture Mapping 
    glShadeModel(GL_SMOOTH);       // Enable Smooth Shading 
    glDisable(GL_DEPTH_TEST);       // Enables Depth Testing 
    glDepthFunc(GL_LEQUAL);        // The Type Of Depth Testing To Do 
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations 

    glLoadIdentity();         // Reset The View 
    glTranslatef(0.0f,0.0f,-5.0f); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glColor4f(1.0, 1.0, 1.0, 1.0); 

    glBegin(GL_QUADS); 
     // Front Face 
     glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.5f); 
     glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 0.5f); 
     glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 0.5f); 
     glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.5f); 
    glEnd(); 

    glSwapBuffers(hdc); 
} 

此代码覆盖前面创建我的按钮通过

hInstallButton = CreateWindow(TEXT("button"), "", 
        WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX, 
        137, 70, 13, 13,   
        hWnd, (HMENU) 1, GetModuleHandle(NULL), NULL); 

的问题是glSwapBuffers(),其中隐藏的按钮为好。 这是由PIXELFORMATDESCRIPTOR

static PIXELFORMATDESCRIPTOR pfd=    // pfd Tells Windows How We Want Things To Be 
    { 
     sizeof(PIXELFORMATDESCRIPTOR),    // Size Of This Pixel Format Descriptor 
     1,           // Version Number 
     PFD_DRAW_TO_WINDOW |      // Format Must Support Window 
     PFD_SUPPORT_OPENGL |      // Format Must Support OpenGL 
     0,       // Must Support Double Buffering 
     PFD_TYPE_RGBA,        // Request An RGBA Format 
     24,          // Select Our Color Depth 
     0, 0, 0, 0, 0, 0,       // Color Bits Ignored 
     0,           // No Alpha Buffer 
     0,           // Shift Bit Ignored 
     0,           // No Accumulation Buffer 
     0, 0, 0, 0,         // Accumulation Bits Ignored 
     16,           // 16Bit Z-Buffer (Depth Buffer) 
     0,           // No Stencil Buffer 
     0,           // No Auxiliary Buffer 
     PFD_MAIN_PLANE,        // Main Drawing Layer 
     0,           // Reserved 
     0, 0, 0          // Layer Masks Ignored 
    }; 

我怎么能强迫一个缓冲区,或东西可写的按钮两个缓冲器产生的?我在这里遇到了很大的损失,不知道如何正确地做到这点(除了可能用每个WM_PAINT调用重新创建按钮)?

编辑: 尝试与子窗口(见代码),但它创建第二个窗口,而不是嵌入到第一个窗口。

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 
    HWND hWnd; 

    hInst = hInstance; // Instanzenhandle in der globalen Variablen speichern 
    DWORD  dwExStyle;    // Window Extended Style 
    DWORD  dwStyle;    // Window Style 

    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 
     CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 

    if (!hWnd) { 
     return FALSE; 
    } 
    dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | CS_OWNDC;   // Window Extended Style 
    dwStyle=WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;       // Windows Style 
    WNDCLASS wndClass; 
    wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 
    wndClass.lpfnWndProc = WndProc; 
    wndClass.cbClsExtra = 0; 
    wndClass.cbWndExtra = 0; 
    wndClass.hInstance = hInstance; 
    wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wndClass.hbrBackground = CreateSolidBrush(BLACK_BRUSH); 
    wndClass.lpszMenuName = NULL; 
    wndClass.lpszClassName = "Test Window"; 
    RegisterClass(&wndClass); 

    hWndOpenGL = CreateWindowEx( dwExStyle,       // Extended Style For The Window 
     "Test Window",       // Class Name 
     "Testy test",        // Window Title 
     dwStyle,       // Required Window Style 
     0, 0,       // Window Position 
     800,  
     600,  
     hWnd,        // Parent Window 
     NULL,        // No Menu 
     hInstance,       // Instance 
     NULL); 

    //CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 
    //CW_USEDEFAULT, 0, CW_USEDEFAULT-500, 0, hWnd, NULL, hInstance, NULL); 

    static PIXELFORMATDESCRIPTOR pfd=    // pfd Tells Windows How We Want Things To Be 
    { 
     sizeof(PIXELFORMATDESCRIPTOR),    // Size Of This Pixel Format Descriptor 
     1,           // Version Number 
     PFD_DRAW_TO_WINDOW |      // Format Must Support Window 
     PFD_SUPPORT_OPENGL |      // Format Must Support OpenGL 
     0,           // Must Support Double Buffering 
     PFD_TYPE_RGBA,        // Request An RGBA Format 
     24,          // Select Our Color Depth 
     0, 0, 0, 0, 0, 0,       // Color Bits Ignored 
     0,           // No Alpha Buffer 
     0,           // Shift Bit Ignored 
     0,           // No Accumulation Buffer 
     0, 0, 0, 0,         // Accumulation Bits Ignored 
     16,           // 16Bit Z-Buffer (Depth Buffer) 
     0,           // No Stencil Buffer 
     0,           // No Auxiliary Buffer 
     PFD_MAIN_PLANE,        // Main Drawing Layer 
     0,           // Reserved 
     0, 0, 0          // Layer Masks Ignored 
    }; 

    hdcOpenGL=GetDC(hWndOpenGL); 

    GLuint  PixelFormat;   // Holds The Results After Searching For A Match 
    PixelFormat=ChoosePixelFormat(hdcOpenGL,&pfd); 

    SetPixelFormat(hdcOpenGL,PixelFormat,&pfd); 

    hrc=wglCreateContext(hdcOpenGL); 

    ShowWindow(hWnd, nCmdShow); 
    UpdateWindow(hWnd); 
    ShowWindow(hWndOpenGL, nCmdShow); 
    UpdateWindow(hWndOpenGL); 

    return TRUE; 
} 

回答

2

我猜你创建的按钮作为OpenGL窗口的孩子。如果你这样做了,那么你实际上做了一些事情,这在WGL和Win32 API文档中明确提到要破坏事情。

该修复很简单:OpenGL窗口应该是按钮的兄弟并具有其自己的DC:使用CS_OWNDC窗口类标志集和WS_CLIPSIBLINGS | WS_CLIPCHILDREN窗口样式被设置,为OpenGL操作创建自己的子窗口。 OpenGL子窗口和按钮都是用所需的容器窗口作为父窗口创建的。

这样,即使使用双缓冲像素格式,按钮也不会被OpenGL操作破坏。

+0

你可以分享CreateWindowEx()函数吗?我已经测试过它,但无法使其正常工作。我编辑了我的问题以显示我一直在使用的代码。它现在显示了两个窗口,但我希望它只在一个窗口中。 – SinisterMJ

+0

@SinisterMJ:对于OpenGL子窗口使用'dwExStyle = 0',类应该指定没有图标和背景画笔(否则你的OpenGL图形将闪烁);由于OpenGL子窗口不是顶层窗口,因此不需要标题;为了清晰起见,只需在CreateWindowEx中使用'wndClass.lpszClassName';确保类名与父窗口的类不同。你的容器窗口必须有一个WM_SIZE事件处理程序,相应地调整OpenGL子窗口的大小。 dwStyle需要设置'WS_CHILD'风格。 – datenwolf

+0

好的,我已经这样做了,但它仍然是第二个窗口。我接近只是住着两扇开着的窗户,但理想的确是一扇大窗户,有两个区域(一个按钮区域,一个OpenGL区域) – SinisterMJ