当前位置:网站首页>Adding OpenGL form to MFC dialog

Adding OpenGL form to MFC dialog

2020-11-09 00:28:00 shzwork

《MFC dialog Add OpenGL forms 》

    Recently I learned how to work in MFC Add... To the dialog program OpenGL Form method , Here, I will summarize my own implementation process .

 

Step zero : Join in PictureControl Control

    newly build MFC Dialog program , Delete the button control on the dialog box Label Control , Then add... To the form PictureControl Control , As a drawing form .

    Set the control's ID Set to :IDC_RENDER

 

Step one : Join in OpenGL Of lib Files and header files

    Right click on the project , add to OpenGL Of lib file ,freeglut_static.lib and gltools.lib, as follows .

 

    And then in stdafx.h The related header files are as follows :

Step two : Set the header file of the dialog box ***Dlg.h

    Declare the relevant variables in the dialog header file :

1     HDC hrenderDC;  // Device context 
2     HGLRC hrenderRC;  // Rendering context 
3     float m_yRotate;  // speed 
4     int PixelFormat;    // Pixel format 

    Declare the relevant methods in the dialog header file :

1     BOOL SetWindowPixelFormat(HDC hDC);  // Set pixel format 
2     BOOL CreateViewGLContext(HDC hDC);   //view GL Context
3     void RenderScene();  // Drawing the scene 

     Add message mapping function :

 1 afx_msg void OnTimer(UINT nIDEvent); 

    The specific dialog header file is as follows :

 Copy code
 1 // OpenGLTest1Dlg.h :  The header file 
 2 //
 3 
 4 #pragma once
 5 
 6 
 7 // COpenGLTest1Dlg  Dialog box 
 8 class COpenGLTest1Dlg : public CDialogEx
 9 {
10 //  structure 
11 public:
12     COpenGLTest1Dlg(CWnd* pParent = NULL);    //  Standard constructors 
13 
14     BOOL SetWindowPixelFormat(HDC hDC);  // Set pixel format 
15     BOOL CreateViewGLContext(HDC hDC);   //view GL Context
16     void RenderScene();  // Drawing the scene 
17 
18     HDC hrenderDC;  // Device context 
19     HGLRC hrenderRC;  // Rendering context 
20     float m_yRotate;  // speed 
21     int PixelFormat;    // Pixel format 
22 
23 //  Dialog data 
24     enum { IDD = IDD_OPENGLTEST1_DIALOG };
25 
26     protected:
27     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV  Support 
28 
29 
30 //  Realization 
31 protected:
32     HICON m_hIcon;
33 
34 
35     //  Generated message mapping function 
36     virtual BOOL OnInitDialog();
37     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
38     afx_msg void OnPaint();
39     afx_msg HCURSOR OnQueryDragIcon();
40     afx_msg void OnTimer(UINT nIDEvent);
41     DECLARE_MESSAGE_MAP()
42 };
 Copy code

Step three : Set the source file of the dialog box ***Dlg.cpp

    a. Turn on timer message loop

    Add... To the code block of the message loop ON_WM_TIMER() Message loop :

1 BEGIN_MESSAGE_MAP(COpenGLTest1Dlg, CDialogEx)
2     ON_WM_SYSCOMMAND()
3     ON_WM_PAINT()
4     ON_WM_QUERYDRAGICON()
5     ON_WM_TIMER() 
6 END_MESSAGE_MAP()

    there OnTimer Function is used to correspond to SetTimer news . When SetTimer It's time to set up , Will automatically call OnTimer() function .

    Write OnTimer The body of a function , As shown below :

 Copy code
1 void COpenGLTest1Dlg::OnTimer(UINT nIDEvent) // Drawing scenes in real time  
2 { 
3  // TODO: Add your message handler code here and/or call default 
4  RenderScene(); 
5  m_yRotate +=3; 
6  CDialog::OnTimer(nIDEvent); 
7 }
 Copy code

 

     b. Write function SetWindowPixelFormat, Used to generate pixel formats

     The body of the function is shown below :

 

 Copy code
 1 BOOL COpenGLTest1Dlg::SetWindowPixelFormat(HDC hDC) 
 2 { 
 3 PIXELFORMATDESCRIPTOR pixelDesc; 
 4 
 5 pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
 6 pixelDesc.nVersion = 1; 
 7 
 8 pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW |  
 9      PFD_SUPPORT_OPENGL | 
10      PFD_DOUBLEBUFFER | 
11      PFD_TYPE_RGBA; 
12 
13 pixelDesc.iPixelType = PFD_TYPE_RGBA; 
14 pixelDesc.cColorBits = 32; 
15 pixelDesc.cRedBits = 0; 
16 pixelDesc.cRedShift = 0; 
17 pixelDesc.cGreenBits = 0; 
18 pixelDesc.cGreenShift = 0; 
19 pixelDesc.cBlueBits = 0; 
20 pixelDesc.cBlueShift = 0; 
21 pixelDesc.cAlphaBits = 0; 
22 pixelDesc.cAlphaShift = 0; 
23 pixelDesc.cAccumBits = 0; 
24 pixelDesc.cAccumRedBits = 0; 
25 pixelDesc.cAccumGreenBits = 0; 
26 pixelDesc.cAccumBlueBits = 0; 
27 pixelDesc.cAccumAlphaBits = 0; 
28 pixelDesc.cDepthBits = 0; 
29 pixelDesc.cStencilBits = 1; 
30 pixelDesc.cAuxBuffers = 0; 
31 pixelDesc.iLayerType = PFD_MAIN_PLANE; 
32 pixelDesc.bReserved = 0; 
33 pixelDesc.dwLayerMask = 0; 
34 pixelDesc.dwVisibleMask = 0; 
35 pixelDesc.dwDamageMask = 0; 
36 
37 PixelFormat = ChoosePixelFormat(hDC,&pixelDesc); 
38 if(PixelFormat==0) // Choose default 
39 { 
40  PixelFormat = 1; 
41  if(DescribePixelFormat(hDC,PixelFormat, 
42   sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0) 
43  { 
44   return FALSE; 
45  } 
46 } 
47 
48 if(SetPixelFormat(hDC,PixelFormat,&pixelDesc)==FALSE) 
49 
50 {  
51  return FALSE; 
52 } 
53 
54 return TRUE; 
55 }
 Copy code

 

     c. Write function CreateViewGLContext, Used to generate rendering context

    The specific function body is as follows :

 Copy code
 1 BOOL COpenGLTest1Dlg::CreateViewGLContext(HDC hDC) 
 2 { 
 3 hrenderRC = wglCreateContext(hDC); 
 4 
 5 if(hrenderRC==NULL) 
 6  return FALSE; 
 7 
 8 if(wglMakeCurrent(hDC,hrenderRC)==FALSE) 
 9  return FALSE; 
10 
11   
12 
13 return TRUE; 
14 }
 Copy code

    d. Write function RenderScene, For drawing scenes

    The specific function body is as follows :

 Copy code
 1 void COpenGLTest1Dlg::RenderScene()    
 2 { 
 3 
 4 
 5  ///////////////////////////////////////////////// 
 6  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
 7 
 8   
 9  glLoadIdentity(); 
10  glTranslatef(0.0f,0.0f,-6.0f);      // Move Left 1.5 Units And Into The Screen 6.0 
11  glRotated(m_yRotate, 0.0, 1.0, 0.0); 
12  glBegin(GL_TRIANGLES); // Drawing Using Triangles 
13   
14   glVertex3f( 0.0f, 1.0f, 0.0f);     // Top 
15   glVertex3f(-1.0f,-1.0f, 0.0f);     // Bottom Left 
16   glVertex3f( 1.0f,-1.0f, 0.0f);     // Bottom Right 
17  glEnd();           // Finished Drawing The Triangle 
18  SwapBuffers(hrenderDC); 
19 }
 Copy code

    e. In the dialog initialization program OnInitDialog Add initialization code

    The specific code is as follows :

 Copy code
 1 ///////////////////////OPENGL INIT///////////////////////// 
 2     CWnd *wnd=GetDlgItem(IDC_RENDER); 
 3     hrenderDC=::GetDC(wnd->m_hWnd); 
 4     if(SetWindowPixelFormat(hrenderDC)==FALSE) 
 5       return 0; 
 6   
 7      if(CreateViewGLContext(hrenderDC)==FALSE) 
 8       return 0; 
 9 
10     glPolygonMode(GL_FRONT,GL_FILL); 
11     glPolygonMode(GL_BACK,GL_FILL); 
12     /////////////////////////////////////////// 
13     glEnable(GL_TEXTURE_2D); 
14     glShadeModel(GL_SMOOTH); 
15     glViewport(0,0,259,231); 
16     glMatrixMode(GL_PROJECTION); 
17     glLoadIdentity(); 
18     gluPerspective(45,1,0.1,100.0); 
19     glMatrixMode(GL_MODELVIEW); 
20     glLoadIdentity(); 
21     glShadeModel(GL_SMOOTH);       // Enable Smooth Shading 
22     glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    // Black Background 
23     glClearDepth(1.0f);         // Depth Buffer Setup 
24     glEnable(GL_DEPTH_TEST);       // Enables Depth Testing 
25     glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do 
26     ///////////////////////////////////////////////////////////////////////// 
27     glEnableClientState(GL_VERTEX_ARRAY); 
28     glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
29 
30     SetTimer(1,10,0); 
31 
32     //////////////////////////////////////////////////////////////// 
 Copy code

    f. Whole .cpp Source code

 Copy code
  1 // OpenGLTest1Dlg.cpp :  Implementation file 
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "OpenGLTest1.h"
  6 #include "OpenGLTest1Dlg.h"
  7 #include "afxdialogex.h"
  8 
  9 
 10 #ifdef _DEBUG
 11 #define new DEBUG_NEW
 12 #endif
 13 
 14 
 15 //  For applications “ About ” Menu items  CAboutDlg  Dialog box 
 16 
 17 class CAboutDlg : public CDialogEx
 18 {
 19 public:
 20     CAboutDlg();
 21 
 22 //  Dialog data 
 23     enum { IDD = IDD_ABOUTBOX };
 24 
 25     protected:
 26     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV  Support 
 27 
 28 //  Realization 
 29 protected:
 30     DECLARE_MESSAGE_MAP()
 31 };
 32 
 33 CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
 34 {
 35 }
 36 
 37 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 38 {
 39     CDialogEx::DoDataExchange(pDX);
 40 }
 41 
 42 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
 43 END_MESSAGE_MAP()
 44 
 45 
 46 // COpenGLTest1Dlg  Dialog box 
 47 
 48 
 49 
 50 
 51 COpenGLTest1Dlg::COpenGLTest1Dlg(CWnd* pParent /*=NULL*/)
 52     : CDialogEx(COpenGLTest1Dlg::IDD, pParent)
 53 {
 54     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 55 }
 56 
 57 void COpenGLTest1Dlg::DoDataExchange(CDataExchange* pDX)
 58 {
 59     CDialogEx::DoDataExchange(pDX);
 60 }
 61 
 62 BEGIN_MESSAGE_MAP(COpenGLTest1Dlg, CDialogEx)
 63     ON_WM_SYSCOMMAND()
 64     ON_WM_PAINT()
 65     ON_WM_QUERYDRAGICON()
 66     ON_WM_TIMER() 
 67 END_MESSAGE_MAP()
 68 
 69 
 70 // COpenGLTest1Dlg  Message handler 
 71 
 72 BOOL COpenGLTest1Dlg::OnInitDialog()
 73 {
 74     CDialogEx::OnInitDialog();
 75 
 76     //  take “ About ...” Menu items are added to the system menu .
 77 
 78     // IDM_ABOUTBOX  Must be within the scope of the system command .
 79     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 80     ASSERT(IDM_ABOUTBOX < 0xF000);
 81 
 82     CMenu* pSysMenu = GetSystemMenu(FALSE);
 83     if (pSysMenu != NULL)
 84     {
 85         BOOL bNameValid;
 86         CString strAboutMenu;
 87         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
 88         ASSERT(bNameValid);
 89         if (!strAboutMenu.IsEmpty())
 90         {
 91             pSysMenu->AppendMenu(MF_SEPARATOR);
 92             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
 93         }
 94     }
 95 
 96     //  Set the icon for this dialog . When the application's main window is not a dialog box , The frame will automatically 
 97     //   Do this 
 98     SetIcon(m_hIcon, TRUE);            //  Set the big icon 
 99     SetIcon(m_hIcon, FALSE);        //  Set up small icons 
100 
101     // TODO:  Add additional initialization code here 
102     ///////////////////////OPENGL INIT///////////////////////// 
103     CWnd *wnd=GetDlgItem(IDC_RENDER); 
104     hrenderDC=::GetDC(wnd->m_hWnd); 
105     if(SetWindowPixelFormat(hrenderDC)==FALSE) 
106       return 0; 
107   
108      if(CreateViewGLContext(hrenderDC)==FALSE) 
109       return 0; 
110 
111     glPolygonMode(GL_FRONT,GL_FILL); 
112     glPolygonMode(GL_BACK,GL_FILL); 
113     /////////////////////////////////////////// 
114     glEnable(GL_TEXTURE_2D); 
115     glShadeModel(GL_SMOOTH); 
116     glViewport(0,0,259,231); 
117     glMatrixMode(GL_PROJECTION); 
118     glLoadIdentity(); 
119     gluPerspective(45,1,0.1,100.0); 
120     glMatrixMode(GL_MODELVIEW); 
121     glLoadIdentity(); 
122     glShadeModel(GL_SMOOTH);       // Enable Smooth Shading 
123     glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    // Black Background 
124     glClearDepth(1.0f);         // Depth Buffer Setup 
125     glEnable(GL_DEPTH_TEST);       // Enables Depth Testing 
126     glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do 
127     ///////////////////////////////////////////////////////////////////////// 
128     glEnableClientState(GL_VERTEX_ARRAY); 
129     glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
130 
131     SetTimer(1,10,0); 
132 
133     //////////////////////////////////////////////////////////////// 
134     return TRUE;  //  Unless you set the focus to the control , Otherwise return to  TRUE
135 }
136 
137 void COpenGLTest1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
138 {
139     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
140     {
141         CAboutDlg dlgAbout;
142         dlgAbout.DoModal();
143     }
144     else
145     {
146         CDialogEx::OnSysCommand(nID, lParam);
147     }
148 }
149 
150 //  If you add a minimize button to the dialog , You need the following code 
151 //   To draw the icon . For using documents / View model  MFC  Applications ,
152 //   This will be done automatically by the framework .
153 
154 void COpenGLTest1Dlg::OnPaint()
155 {
156     if (IsIconic())
157     {
158         CPaintDC dc(this); //  Device context for drawing 
159 
160         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
161 
162         //  Center the icon in the workspace rectangle 
163         int cxIcon = GetSystemMetrics(SM_CXICON);
164         int cyIcon = GetSystemMetrics(SM_CYICON);
165         CRect rect;
166         GetClientRect(&rect);
167         int x = (rect.Width() - cxIcon + 1) / 2;
168         int y = (rect.Height() - cyIcon + 1) / 2;
169 
170         //  draw icon 
171         dc.DrawIcon(x, y, m_hIcon);
172     }
173     else
174     {
175         CDialogEx::OnPaint();
176     }
177 }
178 
179 // When the user drags the minimized window, the system calls this function to get the cursor 
180 // Show .
181 HCURSOR COpenGLTest1Dlg::OnQueryDragIcon()
182 {
183     return static_cast<HCURSOR>(m_hIcon);
184 }
185 
186 BOOL COpenGLTest1Dlg::SetWindowPixelFormat(HDC hDC) 
187 { 
188 PIXELFORMATDESCRIPTOR pixelDesc; 
189 
190 pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
191 pixelDesc.nVersion = 1; 
192 
193 pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW |  
194      PFD_SUPPORT_OPENGL | 
195      PFD_DOUBLEBUFFER | 
196      PFD_TYPE_RGBA; 
197 
198 pixelDesc.iPixelType = PFD_TYPE_RGBA; 
199 pixelDesc.cColorBits = 32; 
200 pixelDesc.cRedBits = 0; 
201 pixelDesc.cRedShift = 0; 
202 pixelDesc.cGreenBits = 0; 
203 pixelDesc.cGreenShift = 0; 
204 pixelDesc.cBlueBits = 0; 
205 pixelDesc.cBlueShift = 0; 
206 pixelDesc.cAlphaBits = 0; 
207 pixelDesc.cAlphaShift = 0; 
208 pixelDesc.cAccumBits = 0; 
209 pixelDesc.cAccumRedBits = 0; 
210 pixelDesc.cAccumGreenBits = 0; 
211 pixelDesc.cAccumBlueBits = 0; 
212 pixelDesc.cAccumAlphaBits = 0; 
213 pixelDesc.cDepthBits = 0; 
214 pixelDesc.cStencilBits = 1; 
215 pixelDesc.cAuxBuffers = 0; 
216 pixelDesc.iLayerType = PFD_MAIN_PLANE; 
217 pixelDesc.bReserved = 0; 
218 pixelDesc.dwLayerMask = 0; 
219 pixelDesc.dwVisibleMask = 0; 
220 pixelDesc.dwDamageMask = 0; 
221 
222 PixelFormat = ChoosePixelFormat(hDC,&pixelDesc); 
223 if(PixelFormat==0) // Choose default 
224 { 
225  PixelFormat = 1; 
226  if(DescribePixelFormat(hDC,PixelFormat, 
227   sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0) 
228  { 
229   return FALSE; 
230  } 
231 } 
232 
233 if(SetPixelFormat(hDC,PixelFormat,&pixelDesc)==FALSE) 
234 
235 {  
236  return FALSE; 
237 } 
238 
239 return TRUE; 
240 } 
241 
242 
243 BOOL COpenGLTest1Dlg::CreateViewGLContext(HDC hDC) 
244 { 
245 hrenderRC = wglCreateContext(hDC); 
246 
247 if(hrenderRC==NULL) 
248  return FALSE; 
249 
250 if(wglMakeCurrent(hDC,hrenderRC)==FALSE) 
251  return FALSE; 
252 
253   
254 
255 return TRUE; 
256 } 
257 
258 void COpenGLTest1Dlg::RenderScene()    
259 { 
260 
261 
262  ///////////////////////////////////////////////// 
263  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
264 
265   
266  glLoadIdentity(); 
267  glTranslatef(0.0f,0.0f,-6.0f);      // Move Left 1.5 Units And Into The Screen 6.0 
268  glRotated(m_yRotate, 0.0, 1.0, 0.0); 
269  glBegin(GL_TRIANGLES); // Drawing Using Triangles 
270   
271   glVertex3f( 0.0f, 1.0f, 0.0f);     // Top 
272   glVertex3f(-1.0f,-1.0f, 0.0f);     // Bottom Left 
273   glVertex3f( 1.0f,-1.0f, 0.0f);     // Bottom Right 
274  glEnd();           // Finished Drawing The Triangle 
275  SwapBuffers(hrenderDC); 
276 } 
277 
278 void COpenGLTest1Dlg::OnTimer(UINT nIDEvent) // Drawing scenes in real time  
279 { 
280  // TODO: Add your message handler code here and/or call default 
281  RenderScene(); 
282  m_yRotate +=3; 
283  CDialog::OnTimer(nIDEvent); 
284 }
 Copy code

Step four : Operation and debugging

    The running results are as follows :

 

版权声明
本文为[shzwork]所创,转载请带上原文链接,感谢