在子窗口中运行OpenGL时隐藏表面删除的问题

时间:2011-05-14 15:17:31

标签: winapi opengl 3d

我正在尝试使用openGL绘制二次曲面。当使用单个窗口时,我的程序可以正常工作。现在我需要一个控制面板,所以我创建了两个窗口,一个是框架窗口,另一个是OpenGL运行的子窗口。但是当openGL在子窗口中运行时隐藏表面移除有问题,而如果我使用单个窗口则不存在这个问题。我没有改变绘图功能,只是得到直流子窗口并设置rc.Here是代码。感谢您的帮助。

#include <windows.h> //Windows header
#include <gl\glut.h>                                    //glut
#include <gl\glaux.h>                                   //glaux
#define hID 6310                                        //ID of child window

LRESULT CALLBACK WndProc   (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK OpenProc (HWND, UINT, WPARAM, LPARAM) ;

TCHAR       szChildClass[] = TEXT ("OpenGL");     //child window class name
TCHAR       szAppName[] = TEXT ("Frame");         //frame window class name
HWND        hwndopen;                             //child window
handle
HWND        hwnd;                                 //frame window handle
MSG         msg ;                                 //message structure
HDC         hdc = NULL;                           //device context used in child window
HGLRC       hrc = NULL;                           //rendering context
HINSTANCE   hInstance;                            //application instance
GLuint      PixelFormat;                                //pixformat
BOOL        active=TRUE;                           
BOOL        keys[256];
float       rquad[3]={0,0,0};                     //angle of rotate    
// pfd Tells Windows How We Want Things To Be
static  PIXELFORMATDESCRIPTOR pfd={
sizeof(PIXELFORMATDESCRIPTOR),
1,PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,  
16,
0, 0, 0, 0, 0, 0,
0,0,0,0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0 
};

/* Here I draw a color cube and I draw black line in every  edge
of the cube,the I draw 3 color lines to show x,y,z coordinate
axis*/
int DrawGLScene(void)                                   
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glLoadIdentity();                                   
glTranslatef(0.0f,0.0f,-10.0f);                     
glRotatef(rquad[0],1.0f,0.0f,0.0f);                 
glRotatef(rquad[1],0.0f,1.0f,0.0f); 
glRotatef(rquad[2],0.0f,0.0f,1.0f);                 
glBegin(GL_QUADS);                                  
glColor3f(0.0f,1.0f,0.0f);                  
glVertex3f( 1.0f, 1.0f,-1.0f);                  
glVertex3f(-1.0f, 1.0f,-1.0f);                  
glVertex3f(-1.0f, 1.0f, 1.0f);                  
glVertex3f( 1.0f, 1.0f, 1.0f);              
glColor3f(1.0f,0.5f,0.0f);                      
glVertex3f( 1.0f,-1.0f, 1.0f);                  
glVertex3f(-1.0f,-1.0f, 1.0f);                  
glVertex3f(-1.0f,-1.0f,-1.0f);                  
glVertex3f( 1.0f,-1.0f,-1.0f);                  
glColor3f(1.0f,0.0f,0.0f);                      
glVertex3f( 1.0f, 1.0f, 1.0f);                  
glVertex3f(-1.0f, 1.0f, 1.0f);                  
glVertex3f(-1.0f,-1.0f, 1.0f);                  
glVertex3f( 1.0f,-1.0f, 1.0f);                  
glColor3f(1.0f,1.0f,0.0f);                      
glVertex3f( 1.0f,-1.0f,-1.0f);                  
glVertex3f(-1.0f,-1.0f,-1.0f);                  
glVertex3f(-1.0f, 1.0f,-1.0f);                  
glVertex3f( 1.0f, 1.0f,-1.0f);                  
glColor3f(0.0f,0.0f,1.0f);                      
glVertex3f(-1.0f, 1.0f, 1.0f);              
glVertex3f(-1.0f, 1.0f,-1.0f);                  
glVertex3f(-1.0f,-1.0f,-1.0f);                  
glVertex3f(-1.0f,-1.0f, 1.0f);                  
glColor3f(1.0f,0.0f,1.0f);                      
glVertex3f( 1.0f, 1.0f,-1.0f);                  
glVertex3f( 1.0f, 1.0f, 1.0f);                  
glVertex3f( 1.0f,-1.0f, 1.0f);                  
glVertex3f( 1.0f,-1.0f,-1.0f);                  
glEnd();                                            


glBegin(GL_LINES);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);                  
glVertex3f(-1.0f, 1.0f,-1.0f);                  
glVertex3f(-1.0f, 1.0f,-1.0f);                  
glVertex3f(-1.0f, 1.0f, 1.0f);                  
glVertex3f(-1.0f, 1.0f, 1.0f);                  
glVertex3f( 1.0f, 1.0f, 1.0f);              
glVertex3f( 1.0f, 1.0f,-1.0f);                  
glVertex3f( 1.0f, 1.0f, 1.0f);              
glVertex3f( 1.0f,-1.0f, 1.0f);              
glVertex3f(-1.0f,-1.0f, 1.0f);              
glVertex3f(-1.0f,-1.0f, 1.0f);                  
glVertex3f(-1.0f,-1.0f,-1.0f);                  
glVertex3f(-1.0f,-1.0f,-1.0f);                  
glVertex3f( 1.0f,-1.0f,-1.0f);                  
glVertex3f( 1.0f,-1.0f,-1.0f);                  
glVertex3f( 1.0f,-1.0f, 1.0f);                  
glVertex3f( 1.0f, 1.0f, 1.0f);                  
glVertex3f( 1.0f, -1.0f, 1.0f);             
glVertex3f( -1.0f, 1.0f, 1.0f);             
glVertex3f( -1.0f, -1.0f, 1.0f);                
glVertex3f( -1.0f, 1.0f, -1.0f);                
glVertex3f( -1.0f, -1.0f, -1.0f);               
glVertex3f( 1.0f, 1.0f, -1.0f);             
glVertex3f( 1.0f, -1.0f, -1.0f);                
glEnd();    
glBegin(GL_LINES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);  
glVertex3f( 10.0f, 0.0f, 0.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 10.0f, 0.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 0.0f, 10.0f);
glEnd();    
return TRUE;                                        
}


BOOL InitGL(void)                                       //init opengl
{
glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
glClearColor(1.0f,0.0f,1.0f,0.5f);
   glClearDepth(1.0f);                              glEnable(GL_DEPTH_TEST);                            glDepthFunc(GL_LEQUAL);                         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
   return TRUE;
}

// resize the opengl scene in child window
void ReSizeGLScene(int width, int height)
{
 if (height==0)   //avoid zero to be the divisor 
                            {
    height=1;
}
glViewport(0,0,(int)width,(int)height);         
glMatrixMode(GL_PROJECTION);                        
glLoadIdentity();                                   
gluPerspective(45.0f,(float)width/(float)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);                         
glLoadIdentity();                               
}



int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                PSTR szCmdLine, int iCmdShow)
{


WNDCLASS     wndclass ;
BOOL         flag=TRUE;
hInstance    = GetModuleHandle(NULL);
InitGL();

wndclass.style         = 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 = (HBRUSH) (COLOR_BTNFACE + 1);
wndclass.lpszMenuName  = NULL ;
wndclass.lpszClassName = szAppName ;

if (!RegisterClass(&wndclass))                                  
{
MessageBox(NULL,"窗口类注册失败","演示程序 ",MB_OK|MB_ICONINFORMATION);
    return 0;
}
wndclass.lpfnWndProc   = OpenProc ;
wndclass.cbWndExtra    = sizeof (long) ;
wndclass.hIcon         = NULL ;
wndclass.hbrBackground = NULL;
wndclass.lpszClassName = szChildClass ;

if (!RegisterClass(&wndclass))                                  
{
    MessageBox(NULL,"子窗口类注册失败","演示程序",MB_OK|MB_ICONINFORMATION);
    return 0;
}

if(!(hwnd = CreateWindow (szAppName, TEXT ("Frisa"),
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT,
    CW_USEDEFAULT, CW_USEDEFAULT,
    NULL, NULL, hInstance, NULL)))
{
    MessageBox(NULL,"窗口创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
    return FALSE;                           
}

ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;

while (flag)
{
    if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
        if (msg.message==WM_QUIT)           
        {
            if (!UnregisterClass(szChildClass,hInstance))           
            {
                MessageBox(NULL,"子窗口类注销失败","演示程序",MB_OK | MB_ICONINFORMATION);
                hInstance=NULL;                                 
            }

            if (!UnregisterClass(szAppName,hInstance))          
            {
                MessageBox(NULL,"窗口类注销失败","演示程序",MB_OK | MB_ICONINFORMATION);
                hInstance=NULL;                             
            }
            flag=FALSE;
        }
        else                                    
        {
            TranslateMessage(&msg);             
            DispatchMessage(&msg);              
        }
    }
    else
    {
        if (active && !DrawGLScene())   // Active?  Was There A Quit Received?
        {
            flag=FALSE;                         // ESC or DrawGLScene Signalled A Quit
        }
        else                                    // Not Time To Quit, Update Screen
        {

            SwapBuffers(hdc);                   // Swap Buffers (Double Buffering)
        }
        if(keys[VK_RIGHT]){rquad[0]+=0.12;}
        if(keys[VK_LEFT]){rquad[0]=0;rquad[1]=0;rquad[2]=0;}
        if(keys[VK_UP]){rquad[1]+=0.12;}
        if(keys[VK_DOWN]){rquad[2]+=0.12;}
    }
}

return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

int   cxBlock, cyBlock;

switch (message)
{
case WM_CREATE :
    if(!(hwndopen= CreateWindow (szChildClass, NULL,
        WS_CHILDWINDOW | WS_VISIBLE,
        0, 0, 0, 0,
        hwnd,(HMENU)(hID),
        (HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE),
        NULL)))
    {
        MessageBox(NULL,"子窗口创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;                               
    }
    if (!(hdc=GetDC(hwndopen)))                         
    {               
        MessageBox(NULL,"设备描述表创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if (!(PixelFormat=ChoosePixelFormat(hdc,&pfd)))
    {               
        MessageBox(NULL,"未找到匹配的像素格式","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if(!SetPixelFormat(hdc,PixelFormat,&pfd))   
    {               
        MessageBox(NULL,"设置像素格式失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if (!(hrc=wglCreateContext(hdc)))           
    {               
        MessageBox(NULL,"获取渲染描述表失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if(!wglMakeCurrent(hdc,hrc))                
    {               
        MessageBox(NULL,"渲染描述表激活失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }
    return 0 ;

case WM_ACTIVATE:                           // Watch For Window Activate Message
    // LoWord Can Be WA_INACTIVE, WA_ACTIVE, WA_CLICKACTIVE,
    // The High-Order Word Specifies The Minimized State Of The Window Being Activated Or Deactivated.
    // A NonZero Value Indicates The Window Is Minimized.
    if ((LOWORD(wParam) != WA_INACTIVE) && !((BOOL)HIWORD(wParam)))
        active=TRUE;                        // Program Is Active
    else
        active=FALSE;                       // Program Is No Longer Active
    return 0;                               // Return To The Message Loop

case WM_SIZE :
    cxBlock = LOWORD (lParam);
    cyBlock = HIWORD (lParam);
    MoveWindow (hwndopen,
        5,5,
        (int)(cxBlock*0.80),(int)(cyBlock*0.98), TRUE) ;
    ReSizeGLScene((int)(cxBlock*0.80),(int)(cyBlock*0.97));
    return 0 ;

case WM_LBUTTONDOWN :
    MessageBeep (0) ;
    return 0 ;

case WM_KEYDOWN:                
    keys[wParam] = TRUE;                
    return 0;                       

case WM_KEYUP:                              
    keys[wParam] = FALSE;
    return 0;

case WM_CLOSE:
    DestroyWindow(hwnd);
    return 0;

case WM_DESTROY :
    if (hrc)                                            
    {
        if (!wglMakeCurrent(hdc,NULL))
        {
            MessageBox(NULL,"DC和RC关联解除失败","演示程序",MB_OK | MB_ICONINFORMATION);
        }

        if (!wglDeleteContext(hrc)) 
        {
            MessageBox(NULL,"RC释放失败","演示程序",MB_OK | MB_ICONINFORMATION);
        }

        hrc=NULL;
    }

    if (!DestroyWindow(hwnd))   
    {
        MessageBox(NULL,"窗口句柄释放失败","演示程序",MB_OK | MB_ICONINFORMATION);
        hwnd=NULL;  
    }

    PostQuitMessage (0) ;
    return 0 ;

}
return DefWindowProc (hwnd, message, wParam, lParam) ;
  }

LRESULT CALLBACK OpenProc (HWND hwnd, UINT message, 
                       WPARAM wParam, LPARAM lParam)
{
return DefWindowProc (hwnd, message, wParam, lParam) ;
}

ADDITION

我的目标是使用OpenGL在子窗口中绘制clolor立方体。子窗口的大小约为框架窗口大小的0.8倍。我将在框架窗口的其余区域添加一个控制面板。我的程序可以绘制一个彩色立方体。但问题是我可以看到所有6个面,以及立方体的所有12个边缘。我不确定但看起来隐藏表面移除失败。

这里我提供了一个结果图像的链接。 http://svgeqg.blu.livefilestore.com/y1p_TRCQ495hxOztZy3oi5qZiDPdN9hQil0KLTY9I-7fFfqCuVr_FiyJ-dIlflN5eHCMqZo5smpUwTaFDxAelq_rjO5hTU5kVzS/colorcube.JPG?psid=1

3 个答案:

答案 0 :(得分:0)

将CS_OWNDC添加到您的窗口类,否则嵌入式窗口将与其父窗口共享其DC。 OpenGL窗口应该总是得到自己的DC,所以对于OpenGL Window类:

wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

由于评论而编辑

我也没有看到PIXELFORMATDESCRIPTOR实际设置。您可以在代码中显示您选择最接近您的请求的一个PFD(API调用ChoosePixelFormatDescribePixelFormat)并在窗口上设置它(SetPixelFormat API调用)。同样,对于调试,您应该根据请求转储系统返回的PFD。

除此之外,应使用窗口样式WS_CLIPCHILDREN | WS_CLIPSIBLINGS

创建使用OpenGL的窗口

答案 1 :(得分:0)

我发现我提交了一个低级错误.OpenGL的初始化应该在创建子窗口之后,但我把它放在顶部,所以它不起作用。

答案 2 :(得分:0)

我已经解决了问题,它是关于OpenGL初始化的位置。初始化必须在创建OpenGL运行的子窗口之后。在上面的代码中,我在winmain()函数的开头初始化OpenGL,但那时子窗口不存在。