当前位置:网站首页>《MFC dialog中加入OpenGL窗体》
《MFC dialog中加入OpenGL窗体》
2020-11-09 00:28:00 【shzwork】
《MFC dialog中加入OpenGL窗体》
最近学习了如何在MFC对话框程序中加入OpenGL窗体的方法,在这里将自己的实现过程归纳一下。
步骤零: 加入PictureControl控件
新建MFC对话框程序,删除对话框上的按钮控件的Label控件,然后向窗体添加PictureControl控件,作为绘制的窗体。
将该控件的ID设置为:IDC_RENDER
步骤一: 加入OpenGL的lib文件和头文件
在项目上单击右键,添加OpenGL的lib文件,freeglut_static.lib和gltools.lib,如下。
然后在stdafx.h中包含相关的头文件如下:
步骤二: 设置对话框的头文件***Dlg.h
在对话框头文件中声明相关的变量:
1 HDC hrenderDC; //设备上下文
2 HGLRC hrenderRC; //渲染上下文
3 float m_yRotate; //转速
4 int PixelFormat; //像素格式
在对话框头文件中声明相关方法:
1 BOOL SetWindowPixelFormat(HDC hDC); //设定像素格式
2 BOOL CreateViewGLContext(HDC hDC); //view GL Context
3 void RenderScene(); //绘制场景
加入消息映射函数:
1 afx_msg void OnTimer(UINT nIDEvent);
具体的对话框头文件如下:
1 // OpenGLTest1Dlg.h : 头文件
2 //
3
4 #pragma once
5
6
7 // COpenGLTest1Dlg 对话框
8 class COpenGLTest1Dlg : public CDialogEx
9 {
10 // 构造
11 public:
12 COpenGLTest1Dlg(CWnd* pParent = NULL); // 标准构造函数
13
14 BOOL SetWindowPixelFormat(HDC hDC); //设定像素格式
15 BOOL CreateViewGLContext(HDC hDC); //view GL Context
16 void RenderScene(); //绘制场景
17
18 HDC hrenderDC; //设备上下文
19 HGLRC hrenderRC; //渲染上下文
20 float m_yRotate; //转速
21 int PixelFormat; //像素格式
22
23 // 对话框数据
24 enum { IDD = IDD_OPENGLTEST1_DIALOG };
25
26 protected:
27 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
28
29
30 // 实现
31 protected:
32 HICON m_hIcon;
33
34
35 // 生成的消息映射函数
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 };
步骤三: 设置对话框的源文件***Dlg.cpp
a. 开启定时器消息循环
在消息循环的代码块中加入ON_WM_TIMER()消息循环:
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()
这里的OnTimer函数用于相应SetTimer消息。当SetTimer设置的时间到了,就会自动调用OnTimer()函数。
写OnTimer函数的函数体,如下所示:
1 void COpenGLTest1Dlg::OnTimer(UINT nIDEvent) //实时绘制场景
2 {
3 // TODO: Add your message handler code here and/or call default
4 RenderScene();
5 m_yRotate +=3;
6 CDialog::OnTimer(nIDEvent);
7 }
b. 写函数SetWindowPixelFormat,用于生成像素格式
函数体如下所示:
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 }
c. 写函数CreateViewGLContext,用于生成渲染上下文
具体函数体如下:
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 }
d. 写函数RenderScene,用于绘制场景
具体函数体如下:
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 }
e. 在对话框初始化程序OnInitDialog中添加初始化代码
具体代码如下:
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 ////////////////////////////////////////////////////////////////
f. 整个.cpp源代码
1 // OpenGLTest1Dlg.cpp : 实现文件
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 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
16
17 class CAboutDlg : public CDialogEx
18 {
19 public:
20 CAboutDlg();
21
22 // 对话框数据
23 enum { IDD = IDD_ABOUTBOX };
24
25 protected:
26 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
27
28 // 实现
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 对话框
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 消息处理程序
71
72 BOOL COpenGLTest1Dlg::OnInitDialog()
73 {
74 CDialogEx::OnInitDialog();
75
76 // 将“关于...”菜单项添加到系统菜单中。
77
78 // IDM_ABOUTBOX 必须在系统命令范围内。
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 // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
97 // 执行此操作
98 SetIcon(m_hIcon, TRUE); // 设置大图标
99 SetIcon(m_hIcon, FALSE); // 设置小图标
100
101 // TODO: 在此添加额外的初始化代码
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; // 除非将焦点设置到控件,否则返回 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 // 如果向对话框添加最小化按钮,则需要下面的代码
151 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
152 // 这将由框架自动完成。
153
154 void COpenGLTest1Dlg::OnPaint()
155 {
156 if (IsIconic())
157 {
158 CPaintDC dc(this); // 用于绘制的设备上下文
159
160 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
161
162 // 使图标在工作区矩形中居中
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 // 绘制图标
171 dc.DrawIcon(x, y, m_hIcon);
172 }
173 else
174 {
175 CDialogEx::OnPaint();
176 }
177 }
178
179 //当用户拖动最小化窗口时系统调用此函数取得光标
180 //显示。
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) //实时绘制场景
279 {
280 // TODO: Add your message handler code here and/or call default
281 RenderScene();
282 m_yRotate +=3;
283 CDialog::OnTimer(nIDEvent);
284 }
步骤四: 运行调试
运行结果如下所示:
版权声明
本文为[shzwork]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4000302/blog/4708448
边栏推荐
- Table join
- The vowels in the inverted string of leetcode
- Realization of file copy
- 华为HCIA笔记
- How does semaphore, a thread synchronization tool that uses an up counter, look like?
- 使用容器存储表格数据
- Have you ever thought about why the transaction and refund have to be split into different tables
- 链表
- Pipedrive如何在每天部署50+次的情况下支持质量发布?
- Save code
猜你喜欢
随机推荐
使用递增计数器的线程同步工具 —— 信号量,它的原理是什么样子的?
API生命周期的5个阶段
Linked blocking queue based on linked list
Dynamic ReLU:微软推出提点神器,可能是最好的ReLU改进 | ECCV 2020
Python features and building environment
数据库设计:范式与反范式
Travel notes of csp-s 2020
14. Introduction to kubenetes
Concurrent linked queue: a non blocking unbounded thread safe queue
leetcode之反转字符串中的元音字母
Fiddler无法正常抓取谷歌等浏览器的请求_解决方案
对象
用两个栈实现队列
Have you ever thought about why the transaction and refund have to be split into different tables
c++11-17 模板核心知识(二)—— 类模板
选择API管理平台之前要考虑的5个因素
Tasks of the first week of information security curriculum design (analysis of 7 instructions)
Introduction and application of swagger
Introduction skills of big data software learning
链表