技术标签: 利用c语言在屏幕上画出窗口
跟我一起学图形编程
作者:姚明联系方式:
欢迎使用我的图形学教程。我是计算机专业的学生,对图形图像技术有浓厚的兴趣,就读期间广泛的涉及相关知识,但始终没有深入研究。原因很简单,我认为广度可以决定深度,大学期间应博学,不宜专于细节。现在毕业了,我选择了图形学作为自己深入研究的方向。
关于图形学,我也算是初学者,也许,与大家不同的是,在深入研究之前,我做了充分的知识准备,我计划从点的绘制开始,实现一套完整的三维渲染流水线。朋友们,跟我一起学吧,让我们披荆斩棘,一起攀上这座美丽的高峰!
下面,开始我们的第一步,创建一个windows下的窗口程序。
理论:
Windows程序中,在写图形用户界面时需要调用大量的标准Windows Gui函数。其实这对用户和程序员来说都有好处,对于用户,面对的是同一套标准的窗口,对这些窗口的操作都是一样的,所以使用不同的应用程序时无须重新学习操作。对程序员来说,这些Gui源代码都是经过了微软的严格测试,随时拿来就可以用的。当然至于具体地写程序对于程序员来说还是有难度的。为了创建基于窗口的应用程序,必须严格遵守规范。作到这一点并不难,只要用模块化或面向对象的编程方法即可。
下面我就列出在桌面显示一个窗口的几个步骤:
得到您应用程序的句柄(必需);
得到命令行参数(如果您想从命令行得到参数,可选);
注册窗口类(必需,除非您使用Windows预定义的窗口类,如MessageBox或dialog box;
产生窗口(必需);
在桌面显示窗口(必需,除非您不想立即显示它);
刷新窗口客户区;
进入无限的获取窗口消息的循环;
如果有消息到达,由负责该窗口的窗口回调函数处理;
如果用户关闭窗口,进行退出处理。
相对于单用户的DOS下的编程来说,Windows下的程序框架结构是相当复杂的。但是Windows和DOS在系统架构上是截然不同的。Windows是一个多任务的操作系统,故系统中同时有多个应用程序彼此协同运行。这就要求Windows程序员必须严格遵守编程规范,并养成良好的编程风格。
Windows中的文本是一个GUI(图形用户界面)对象。每一个字符实际上是由许多的像素点组成,这些点在有笔画的地方显示出来,这样就会出现字符。这也是为什么我说“绘制”字符,而不是写字符。通常您都是在您应用程序的客户区“绘制”字符串(尽管您也可以在客户区外“绘制”)。Windows下的“绘制”字符串方法和Dos下的截然不同,在Dos下,您可以把屏幕想象成85 x 25的一个平面,而Windows下由于屏幕上同时有几个应用程序的画面,所以您必须严格遵从规范。Windows通过把每一个应用程序限制在他的客户区来做到这一点。当然客户区的大小是可变的,您随时可以调整。
在您在客户区“绘制”字符串前,您必须从Windows那里得到您客户区的大小,确实您无法像在DOS下那样随心所欲地在屏幕上任何地方“绘制”,绘制前您必须得到Windows的允许,然后Windows会告诉您客户区的大小,字体,颜色和其它GUI对象的属性。您可以用这些来在客户区“绘制”。
什么是“设备环境”(DC)呢? 它其实是由Windows内部维护的一个数据结构。一个“设备环境”和一个特定的设备相连。像打印机和显示器。对于显示器来说,“设备环境”和一个个特定的窗口相连。
“设备环境”中的有些属性和绘图有关,像:颜色,字体等。您可以随时改动那些缺省值,之所以保存缺省值是为了方便。您可以把“设备环境”想象成是Windows为您准备的一个绘图环境,而您可以随时根据需要改变某些缺省属性。
当应用程序需要绘制时,您必须得到一个“设备环境”的句柄。通常有几种方法。
在WM_PAINT消息中使用call BeginPaint
在其他消息中使用call GetDC
call CreateDC建立你自己的DC
您必须牢记的是,在处理单个消息后你必须释放“设备环境”句柄。不要在一个消息处理中获得“设备环境”句柄,而在另一个消息处理中在释放它。
我们在Windows发送WM_PAINT消息时处理绘制客户区,Windows不会保存客户区的内容,它用的是方法是“重绘”机制(譬如当客户区刚被另一个应用程序的客户区覆盖),Windows会把WM_PAINT消息放入该应用程序的消息队列。重绘窗口的客户区是各个窗口自己的责任,您要做的是在窗口过程处理WM_PAINT的部分知道绘制什么和何如绘制。
您必须了解的另一个概念是“无效区域”。Windows把一个最小的需要重绘的正方形区域叫做“无效区域”。当Windows发现了一个”无效区域“后,它就会向该应用程序发送一个WM_PAINT消息,在WM_PAINT的处理过程中,窗口首先得到一个有关绘图的结构体,里面包括无效区的坐标位置等。您可以通过调用BeginPaint让“无效区”有效,如果您不处理WM_PAINT消息,至少要调用缺省的窗口处理函数DefWindowProc,或者调用ValidateRect让“无效区”有效。否则您的应用程序将会收到无穷无尽的WM_PAINT消息。
下面是响应该消息的步骤:
取得“设备环境”句柄
绘制客户区
释放“设备环境”句柄
注意,您无须显式地让“无效区”有效,这个动作由BeginPaint自动完成。您可以在BeginPaint和Endpaint之间,调用所有的绘制函数。几乎所有的GDI函数都需要“设备环境”的句柄作为参数。
内容:
下面是我们简单的窗口程序的源代码。在进入复杂的细节前,我将提纲挈领地指出几点要点:
您应当把程序中要用到的所有常量和结构体的声明放到一个头文件中,并且在源程序的开始处包含这个头文件。这么做将会节省您大量的时间,也免得一次又一次的敲键盘。您也可以定义您自己的常量和结构体,但最好把它们放到独立的头文件中。
在其它地方运用头文件中定义函数原型,常数和结构体时,要严格保持和头文件中的定义一致,包括大小写。在查询函数定义时,这将节约您大量的时间;
如果想详细系统的学习Windows编程,可以参考《windows程序设计》,
如果你的系统中没有安装VC,或不会使用VC,我准备了精简版本,只有10MB左右,无需复杂操作,也能编译本教程中的代码,生成程序,
如果你对下面的代码视如天书,那么请先看《谭浩强C语言教程》,务必熟读,
1
/**//*------------------------------------------------------------------------2 HELLOWIN.CPP -- Displays "你好, 欢迎使用YM的图形学教程!" in client area3 (c) Charles Petzold, 19984-----------------------------------------------------------------------*/5#include67LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;89intWINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,10 PSTR szCmdLine,intiCmdShow)11
{12staticTCHAR szAppName[]=TEXT ("HelloWin") ;13 HWND hwnd ;14 MSG msg ;15 WNDCLASS wndclass ;16 wndclass.style=CS_HREDRAW|CS_VREDRAW ;17 wndclass.lpfnWndProc=WndProc ;18 wndclass.cbClsExtra=0;19 wndclass.cbWndExtra=0;20 wndclass.hInstance=hInstance ;21 wndclass.hIcon=LoadIcon (NULL, IDI_APPLICATION) ;22 wndclass.hCu
文章浏览阅读3k次。问题:java.sql.SQLException: Record length exceed maximum size转【原文】根据个人工程实践,略有修改数据库:Oracle 9i数据库字段类型:varchar2(4000)输入汉字:大于600字(左右)问题1:当遇到“java.sql.SQLException:数据大小超出此类型的最大值”时...解决办法:这是jdbc驱动..._record length exceed maximum size
文章浏览阅读4.7k次,点赞3次,收藏14次。HDMI、喇叭音频同时输出文章目录HDMI、喇叭音频同时输出方案一方案二方案三Android默认音频输出逻辑,不接HDMI默认喇叭音频输出,若检测到HDMI接入后,关闭喇叭输出,开启HDMI音频输出BOX产品的使用场景需要插入HDMI后,喇叭仍然输出,可加入此补丁方案一适用平台:RK3399 Android8.1$ vim frameworks/base/services/core/java/com/android/server/WiredAccessoryManager.java _rockchip android 耳机和hdmi同时输出音频
文章浏览阅读5k次,点赞2次,收藏2次。可视化的使用场景我们在请求一个接口时,其响应结果往往是一串Json或者其他字符串,缺乏对应的可视化效果。如图这样的结果虽然能在一般情况下能满足后端人员调试的需要,但是针对其他人员,比如前端或者测试人员,看起来就有些不太直观。我们可以通过可视化功能,将这段json通过自定义表格的方式呈现出来。如图:如何实现响应结果可视化?如何实现这样的效果呢?从ApiPost V5.3.1版本开始,我们在后执行脚本中新增了apt.Visualizing(template, obj) 方法,用于实现响应可视化。以_接口自动化中的响应数据可视化一般做什么可视化
文章浏览阅读1w次,点赞12次,收藏67次。获取表单document.getElementById(“id属性值”),通过表单的id属性值获取属性对象document.表单的name属性值,通过表单的name属性值获取表单对象document.forms[下标],通过指定下标获取表单元素document.forms[表单的name属性值获取],通过表单的name属性值获取表单对象document.forms:获取HTML文档中所有的表单对象<body> <!-- 获取表单(前两种常用) 1.._js 获取表单某个属性值
文章浏览阅读3.2k次,点赞7次,收藏43次。决策树是一种机器学习的方法。决策树的生成算法有ID3, C4.5和C5.0等。决策树是一种树形结构,其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果。
文章浏览阅读1.4k次。国密SM4的Python实现其他人也写了,本程序的优点在于考虑了明文输入不足128bits(二进制下)的情况,并给出了大量注释即调试用代码(已注释),方便大家进行调试、优化。希望大家通过本程序一起学习呀。_python sm4
文章浏览阅读1k次。由于刚更换tomcat 9 ,没有修改配置文件,致使项目运行之后,web端出现个别乱码的情况。接下来将配置文件中的设置一一调整。tomcat 9 项目运行之后web界面乱码,该方案不适用于控制台乱码_tomcat9启动出现乱码
文章浏览阅读351次。1. 下载android ndkhttps://developer.android.google.cn/ndk/downloads/2. 下载Boost-for-Androidhttps://github.com/moritz-wundke/Boost-for-Android3. 在linux设置ndk环境变量export PATH=$PATH:/home/test/android/android-ndk-r21d4. 进入Boost-for-Android执行./build-a_linux android boost
文章浏览阅读254次,点赞10次,收藏2次。灰狼算法GWO求解置换流水车间调度问题PFSP完整的代码,方可运行;可提供运行操作视频!适合小白!
文章浏览阅读739次。1.准备工作1.1 roscore在新的终端中,运行roscore1.2 turtlesim运行turtlesim$ rosrun turtlesim turtlesim_node1.3 乌龟键盘遥操作我们需要有东西来操控乌龟移动。打开新的终端输入$ rosrun turtlesim turtle_teleop_key现在可以使用键盘的箭头按钮来控制乌龟移动。切记一定要在tu..._ubuntu用什么指令查看话题数据
文章浏览阅读95次。正常情况下,发动机转速降低时,喷油脉宽应变小,由此怀疑发动机熄火是由供油不足引起的。,这说明虽然燃油泵电流降低,但燃油泵转速升高,由此推断此时燃油泵抽吸不到燃油,在空转,负载变小。接车后试车,起动发动机,发动机怠速运转正常,且组合仪表上没有故障灯点亮。所示,其中蓝色线为曲轴位置传感器信号,黄色线为进气歧管绝对压力传感器信号,红色线为气缸。喷油信号,绿色线为燃油压力,橙色线是根据曲轴位置传感器信号计算的发动机转速(利用。所示,其中蓝色线为曲轴位置传感器信号,黄色线为燃油泵电流,红色线为气缸。
文章浏览阅读1.9k次,点赞2次,收藏7次。Matlab SVM最近项目要用到SVM,时间紧,所以就直接用Matlab提供的库函数。另外,这个最负盛名的libsvm,台湾林智仁教授开发的开源包,http://www.csie.ntu.edu.tw/~cjlin/libsvm/业界很有名的一个包,有各种各样的接口,现在最新更新到Python。 Matlab中SVM的函数主要有两个:%svmtrain:s_matlab svm函数