我正在尝试使用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个边缘。我不确定但看起来隐藏表面移除失败。
答案 0 :(得分:0)
将CS_OWNDC添加到您的窗口类,否则嵌入式窗口将与其父窗口共享其DC。 OpenGL窗口应该总是得到自己的DC,所以对于OpenGL Window类:
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
由于评论而编辑
我也没有看到PIXELFORMATDESCRIPTOR实际设置。您可以在代码中显示您选择最接近您的请求的一个PFD(API调用ChoosePixelFormat
,DescribePixelFormat
)并在窗口上设置它(SetPixelFormat
API调用)。同样,对于调试,您应该根据请求转储系统返回的PFD。
除此之外,应使用窗口样式WS_CLIPCHILDREN | WS_CLIPSIBLINGS
答案 1 :(得分:0)
我发现我提交了一个低级错误.OpenGL的初始化应该在创建子窗口之后,但我把它放在顶部,所以它不起作用。
答案 2 :(得分:0)
我已经解决了问题,它是关于OpenGL初始化的位置。初始化必须在创建OpenGL运行的子窗口之后。在上面的代码中,我在winmain()函数的开头初始化OpenGL,但那时子窗口不存在。