当前位置:网站首页>《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
边栏推荐
- 教你如何 分析 Android ANR 问题
- The vowels in the inverted string of leetcode
- Linked list
- When iperf is installed under centos7, the solution of make: * no targets specified and no makefile found. Stop
- Introduction skills of big data software learning
- MYCAT build
- 云计算之路-出海记-小目标:Hello World from .NET 5.0 on AWS
- 第五章编程
- salesforce零基础学习(九十八)Salesforce Connect & External Object
- API生命周期的5个阶段
猜你喜欢
Leetcode-11: container with the most water
salesforce零基础学习(九十八)Salesforce Connect & External Object
B. protocal has 7000eth assets in one week!
Why need to use API management platform
Table join
上线1周,B.Protocal已有7000ETH资产!
使用递增计数器的线程同步工具 —— 信号量,它的原理是什么样子的?
如何让脚本同时兼容Python2和Python3?
数据库设计:范式与反范式
Realization of file copy
随机推荐
The road of cloud computing - going to sea - small goal: Hello world from. Net 5.0 on AWS
Dynamic relu: Microsoft's refreshing device may be the best relu improvement | ECCV 2020
综合架构的简述
When we talk about data quality, what are we talking about?
Get the first cover image of video through canvas
SAP S/4HANA 2020安装实录
LeetCode-15:三数之和
[200 interview experience], programmer interview, common interview questions analysis
Factory Pattern模式(简单工厂、工厂方法、抽象工厂模式)
The vowels in the inverted string of leetcode
Why need to use API management platform
表连接
Have you ever thought about why the transaction and refund have to be split into different tables
Nodejs中request出现ESOCKETTIMEDOUT解决方案
C++邻接矩阵
老大问我:“建表为啥还设置个自增 id ?用流水号当主键不正好么?”
Queue with two stacks
Linked list
android开发中提示:requires permission android.permission write_settings解决方法
Brief introduction of Integrated Architecture