头文件,定义WinMain入口函数,使用WNDCLASS结构体填充窗口类信息,并注册窗口类。窗口的创建、风格设置、显示以及消息循环和回调函数的处理过程被详细阐述,以实现窗口的显示与关闭功能。
摘要由CSDN通过智能技术生成
初学C++时,控制台会给我们提供一个黑窗口,而这篇文章所做的就是:创建一个属于图形界面窗口,而不是使用控制台黑窗口
如图,这是一个标题为XSZY的窗口
这都是自定义的
所有有关视窗的基本函数和类型都定义在头文件 <windows.h> 中
我们只需要引用就好了
#include<windows.h>
然后定义程序的入口函数main
int __stdcall WinMain(HINSTANCE hInst,
HINSTANCE hPrev,
LPSTR lpCmdLine,
int nCmdShow)
说到这个入口函数,其实使用main()也是可以的
int main() {
int main(int argc, char** argv) {
int main(int argc, char* argv[]) {
其实C++定义了很多程序入口,只要程序中包含其中一个,程序就可以运行了
而WinMain的声明同样也是有依据可寻的
在头文件 <winbase.h> 中, 有这样两句话
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd);
它们分别声明了两种程序入口
WinMain 和 wWinMain
wWinMain 是 WinMain 的宽字符版本, 形参列表中的LPWSTR说明了这个事实
顺带说一下吧 基本所有的函数、类型、结构体、宏等都带有A 和 W,
比如 WNDCLASSA 和 WNDCLASSW
一般A是窄字符, W是宽字符
LPSTR 其实就是 char* ; 而LPWSTR 是 wchar_t*
表示宽字符时需要标记L
比如定义宽字符串HelloWorld应该写为 L"HelloWorld!" ,系统就会识别为宽字符了
说了这么多,该定义窗口实例句柄了
这是用来指向一个实例( instance ) 的类型 HINSTANCE
前缀H就是Handle句柄的意思, instance就是实例的意思
这个句柄的作用就是:指定一个窗口实例
如果你使用的时WinMain,那么可以选择直接使用形参表中的第一个或第二个参数,但是如果你使用的时int main(),那么就需要定义一个新的实例句柄
int WINAPI WinMain(HINSTANCE hInst,
HINSTANCE hPrev,
LPSTR lpCmdLine,
int nShowCmd)
int main()
HINSTANCE hInst;
定义来有什么用呢?
我们需要做一个窗口,就需要创建它,而定义它的标准,是由结构体WNDCLASS来完成的,能够让窗口和窗口结构体链接上的,需要实例句柄一致,并且和窗口类名一致
窗口类在 <winuser.h> 中的定义
typedef struct tagWNDCLASSA {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCSTR lpszMenuName;
LPCSTR lpszClassName;
} WNDCLASSA,*PWNDCLASSA,*NPWNDCLASSA,*LPWNDCLASSA;
typedef struct tagWNDCLASSW {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
初学C++时,控制台会给我们提供一个黑窗口,而这篇文章所做的就是:创建一个属于图形界面窗口,而不是使用控制台黑窗口如图,这是一个标题为XSZY的窗口看完这篇文章,你想要的窗口大小,图标等都可以自己定义甚至是在窗口上鼠标的样子,都是可以随意改的所有有关视窗的基本函数和类型都定义在头文件 <windows.h> 中我们只需要引用就好了//引用头文件 windows.h#include<windows.h> 然后定义程序的入口函数mainint __stdcall W
//6、处理消息(窗口过程)
//CALLBACK代表__stdcall参数传递顺序 从右往左依次入栈,并且在函数返回前自动清空堆栈内容
LRESULT CALLBACK WindowProc(
使用C++完成以栈为基础的简易计算器,并使用Qt5制作可视化界面
一.计算器内部逻辑构造:
在完成计算器时选用栈数据结构(自己编写的和标准模板库中的都可),要求支持加减乘除和逻辑与或非运算,可计算整数和小数。这一部分有很多思路都可以实现,我的写法是将整个步骤分为表达式抽离,出入栈操作和运算符运算三个步骤。
1.表达式抽离
首先,在没有做出交互界面的情况下我们假定用户以英文键盘输入所要计算的表达式,这时你就会得到一个字符串,为了将字符串中每一个数字或运算符进行分割抽离,我们可以选用一个vector容器储存单独
if (Index m_FigArray.GetUpperBound ())
return 0;
return (CFigure *)m_FigArray.GetAt (Index);
int CMiniDrawDoc::GetNumFigs ()
return m_FigArray.GetSize ();
void CMiniDrawDoc::DeleteContents()
// TODO: Add your specialized code here and/or call the base class
int Index = m_FigArray.GetSize ();
while (Index--)
delete m_FigArray.GetAt (Index);
m_FigArray.RemoveAll ();
CDocument::DeleteContents();
void CMiniDrawDoc::OnEditClearAll()
// TODO: Add your command handler code here
DeleteContents ();
UpdateAllViews (0);
SetModifiedFlag ();
void CMiniDrawDoc::OnUpdateEditClearAll(CCmdUI* pCmdUI)
// TODO: Add your command update UI handler code here
pCmdUI->Enable (m_FigArray.GetSize ());
void CMiniDrawDoc::OnEditUndo()
// TODO: Add your command handler code here
int Index = m_FigArray.GetUpperBound ();
if (Index > -1)
delete m_FigArray.GetAt (Index);
m_FigArray.RemoveAt (Index);
UpdateAllViews (0);
SetModifiedFlag ();
void CMiniDrawDoc::OnUpdateEditUndo(CCmdUI* pCmdUI)
// TODO: Add your command update UI handler code here
pCmdUI->Enable (m_FigArray.GetSize ());
// implementation of figure classes:
IMPLEMENT_SERIAL (CFigure, CObject, 3)
CRect CFigure::GetDimRect ()
return CRect
(min (m_X1, m_X2),
min (m_Y1, m_Y2),
max (m_X1, m_X2) + 1,
max (m_Y1, m_Y2) + 1);
void CFigure::Serialize (CArchive& ar)
if (ar.IsStoring ())
ar << m_X1 << m_Y1 << m_X2 << m_Y2 <> m_X1 >> m_Y1 >> m_X2 >> m_Y2 >> m_Color;
IMPLEMENT_SERIAL (CLine, CFigure, 3)
CLine::CLine (int X1, int Y1, int X2, int Y2, COLORREF Color, int Thickness)
m_X1 = X1;
m_Y1 = Y1;
m_X2 = X2;
m_Y2 = Y2;
m_Color = Color;
m_Thickness = Thickness;
void CLine::Serialize (CArchive& ar)
CFigure::Serialize (ar);
if (ar.IsStoring ())
ar <> m_Thickness;
void CLine::Draw (CDC *PDC)
CPen Pen, *POldPen;
// select pen/brush:
Pen.CreatePen (PS_SOLID, m_Thickness, m_Color);
POldPen = PDC->SelectObject (&Pen);
// draw figure:
PDC->MoveTo (m_X1, m_Y1);
PDC->LineTo (m_X2, m_Y2);
// remove pen/brush:
PDC->SelectObject (POldPen);
IMPLEMENT_SERIAL (CRectangle, CFigure, 3)
CRectangle::CRectangle (int X1, int Y1, int X2, int Y2,
COLORREF Color, int Thickness)
m_X1 = X1;
m_Y1 = Y1;
m_X2 = X2;
m_Y2 = Y2;
m_Color = Color;
m_Thickness = Thickness;
void CRectangle::Serialize (CArchive& ar)
CFigure::Serialize (ar);
if (ar.IsStoring ())
ar <> m_Thickness;
void CRectangle::Draw (CDC *PDC)
CPen Pen, *POldPen;
// select pen/brush:
Pen.CreatePen (PS_INSIDEFRAME, m_Thickness, m_Color);
POldPen = PDC->SelectObject (&Pen);
PDC->SelectStockObject (NULL_BRUSH);
// draw figure:
PDC->Rectangle (m_X1, m_Y1, m_X2, m_Y2);
// remove pen/brush:
PDC->SelectObject (POldPen);
IMPLEMENT_SERIAL (CRectFill, CFigure, 3)
CRectFill::CRectFill (int X1, int Y1, int X2, int Y2, COLORREF Color)
m_X1 = min (X1, X2);
m_Y1 = min (Y1, Y2);
m_X2 = max (X1, X2);
m_Y2 = max (Y1, Y2);
m_Color = Color;
void CRectFill::Draw (CDC *PDC)
CBrush Brush, *POldBrush;
CPen Pen, *POldPen;
// select pen/brush:
Pen.CreatePen (PS_INSIDEFRAME, 1, m_Color);
POldPen = PDC->SelectObject (&Pen);
Brush.CreateSolidBrush (m_Color);
POldBrush = PDC->SelectObject (&Brush);
// draw figure:
PDC->Rectangle (m_X1, m_Y1, m_X2, m_Y2);
// remove pen/brush:
PDC->SelectObject (POldPen);
PDC->SelectObject (POldBrush);
IMPLEMENT_SERIAL (CRectRound, CFigure, 3)
CRectRound::CRectRound (int X1, int Y1, int X2, int Y2,
COLORREF Color, int Thickness)
m_X1 = min (X1, X2);
m_Y1 = min (Y1, Y2);
m_X2 = max (X1, X2);
m_Y2 = max (Y1, Y2);
m_Color = Color;
m_Thickness = Thickness;
void CRectRound::Serialize (CArchive& ar)
CFigure::Serialize (ar);
if (ar.IsStoring ())
ar <> m_Thickness;
void CRectRound::Draw (CDC *PDC)
CPen Pen, *POldPen;
// select pen/brush:
Pen.CreatePen (PS_INSIDEFRAME, m_Thickness, m_Color);
POldPen = PDC->SelectObject (&Pen);
PDC->SelectStockObject (NULL_BRUSH);
// draw figure:
int SizeRound = (m_X2 - m_X1 + m_Y2 - m_Y1) / 6;
PDC->RoundRect (m_X1, m_Y1, m_X2, m_Y2, SizeRound, SizeRound);
// remove pen/brush:
PDC->SelectObject (POldPen);
IMPLEMENT_SERIAL (CRectRoundFill, CFigure, 3)
CRectRoundFill::CRectRoundFill (int X1, int Y1, int X2, int Y2, COLORREF Color)
m_X1 = min (X1, X2);
m_Y1 = min (Y1, Y2);
m_X2 = max (X1, X2);
m_Y2 = max (Y1, Y2);
m_Color = Color;
void CRectRoundFill::Draw (CDC *PDC)
CBrush Brush, *POldBrush;
CPen Pen, *POldPen;
// select pen/brush:
Pen.CreatePen (PS_INSIDEFRAME, 1, m_Color);
POldPen = PDC->SelectObject (&Pen);
Brush.CreateSolidBrush (m_Color);
POldBrush = PDC->SelectObject (&Brush);
// draw figure:
int SizeRound = (m_X2 - m_X1 + m_Y2 - m_Y1) / 6;
PDC->RoundRect (m_X1, m_Y1, m_X2, m_Y2, SizeRound, SizeRound);
// remove pen/brush:
PDC->SelectObject (POldPen);
PDC->SelectObject (POldBrush);
IMPLEMENT_SERIAL (CCircle, CFigure, 3)
CCircle::CCircle (int X1, int Y1, int X2, int Y2,
COLORREF Color, int Thickness)
m_X1 = min (X1, X2);
m_Y1 = min (Y1, Y2);
m_X2 = max (X1, X2);
m_Y2 = max (Y1, Y2);
m_Color = Color;
m_Thickness = Thickness;
void CCircle::Serialize (CArchive& ar)
CFigure::Serialize (ar);
if (ar.IsStoring ())
ar <> m_Thickness;
void CCircle::Draw (CDC *PDC)
CPen Pen, *POldPen;
// select pen/brush:
Pen.CreatePen (PS_INSIDEFRAME, m_Thickness, m_Color);
POldPen = PDC->SelectObject (&Pen);
PDC->SelectStockObject (NULL_BRUSH);
// draw figure:
PDC->Ellipse (m_X1, m_Y1, m_X2, m_Y2);
// remove pen/brush:
PDC->SelectObject (POldPen);
IMPLEMENT_SERIAL (CCircleFill, CFigure, 3)
CCircleFill::CCircleFill (int X1, int Y1, int X2, int Y2, COLORREF Color)
m_X1 = min (X1, X2);
m_Y1 = min (Y1, Y2);
m_X2 = max (X1, X2);
m_Y2 = max (Y1, Y2);
m_Color = Color;
void CCircleFill::Draw (CDC *PDC)
CBrush Brush, *POldBrush;
CPen Pen, *POldPen;
// select pen/brush:
Pen.CreatePen (PS_INSIDEFRAME, 1, m_Color);
POldPen = PDC->SelectObject (&Pen);
Brush.CreateSolidBrush (m_Color);
POldBrush = PDC->SelectObject (&Brush);
// draw figure:
PDC->Ellipse (m_X1, m_Y1, m_X2, m_Y2);
// remove pen/brush:
PDC->SelectObject (POldPen);
PDC->SelectObject (POldBrush);
使用 C 语言编写可视化数据的方法可以使用图形库来实现。常见的图形库有 GTK、Qt 和 SDL。
- GTK(GIMP Toolkit)是一个多平台的图形工具库,用于开发图形用户界面,可以使用 C 语言来编写。使用 GTK 可以轻松地创建漂亮的图形界面,并支持 Windows、Linux 和 Mac OS 等操作系统。
- Qt 是一个跨平台的 C++ 图形工具库,也可以使用 C 语言来开发。Qt 提供了丰富的图形界面和工具,可以让你轻松地创建可视化数据。
- SDL(Simple DirectMedia Layer)是一个跨平台的多媒体开发库,可以使用 C 语言来编写可视化数据。SDL 提供了丰富的图形和多媒体功能,可以让你开发出各种各样的可视化应用程序。
具体的实现方法可以参考各个图形库的文档和教程,并根据你的需求来选择合适的图形库。
### 回答2:
编写一个可视化的数据,可以使用C语言的图形库来进行实现。图形库可以是常见的图形库,比如OpenGL或者SDL等。
首先,需要在C代码中引入相关的图形库的头文件,并且初始化图形库的相关函数。然后,可以定义一个窗口,并设置窗口的大小和位置等属性。
接下来,可以利用C语言的相关功能实现数据的可视化。可以通过鼠标点击或者键盘输入来获取用户的操作,以便对数据进行相应的处理和展示。比如,可以通过绘制不同的图形来表示不同的数据,例如绘制折线图、柱状图、饼状图等。
在绘制图形的过程中,可以根据数据的大小、比例和属性等,来决定绘制图形的位置、形状和颜色等。可以使用不同的颜色或者图案来区分不同的数据,以便更直观地展示数据的特点和变化情况。
同时,可以添加相应的标签、标题、轴线和网格等来增加图形的可读性和美观性。可以通过设置字体、大小和颜色等来调整文本的显示效果。
最后,在图形绘制完成后,可以通过保存图形为图片或者直接在窗口中显示的方式来保存和展示数据的可视化结果。
需要注意的是,在进行图形可视化的过程中,要注意处理异常情况和错误输入,以确保程序的稳定性和用户体验。
总的来说,使用C编写可视化数据需要熟悉相关的图形库和C语言的图形编程功能,需要对数据的结构和处理方法有一定的了解,以便正确地展示和解读数据的图形结果。
### 回答3:
使用C编写一个可视化的数据可以通过图形库来实现。常见的图形库有OpenGL、SDL、SFML等。下面以使用OpenGL来展示一个简单的例子进行说明。
首先,需要导入OpenGL的头文件,并进行初始化。然后,创建一个窗口,在窗口中进行绘制。在绘制时,可以使用OpenGL提供的函数来绘制基本的几何图形,例如点、线段、多边形等。
例如,我们可以使用OpenGL来绘制一个简单的二维坐标系。首先,使用glOrtho函数来设置投影矩阵,将屏幕的一部分坐标映射到窗口中进行绘制。然后,使用glBegin和glEnd函数来定义绘制的区域,并使用glVertex2f来绘制各个坐标点。
具体代码如下:
#include <GL/glut.h>
void display()
glClear(GL_COLOR_BUFFER_BIT);
// 绘制x轴
glBegin(GL_LINES);
glVertex2f(-1.0, 0.0);
glVertex2f(1.0, 0.0);
glEnd();
// 绘制y轴
glBegin(GL_LINES);
glVertex2f(0.0, -1.0);
glVertex2f(0.0, 1.0);
glEnd();
// 刷新窗口
glutSwapBuffers();
int main(int argc, char** argv)
// 初始化窗口
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(400, 400);
glutCreateWindow("Visualization");
// 设置窗口的绘制函数
glutDisplayFunc(display);
// 进入主循环
glutMainLoop();
return 0;
上述代码使用OpenGL绘制了一个简单的二维坐标系,窗口大小为400x400。通过编译运行该程序,即可看到一个可视化的数据,即一个坐标系。
使用C++编写一个可视化窗口
AWINX:
使用C++编写一个可视化窗口
么么哒小新:
使用C++编写一个可视化窗口
haoziccy: