![计算机图形学:原理、算法及实践](https://wfqqreader-1252317822.image.myqcloud.com/cover/947/23400947/b_23400947.jpg)
2.2 VC++基本图素的绘制方法
2.2.1 相关类及函数
在实现计算机图形学的原理和算法时,会用到VC6.0中的相关类、函数、数组、头文件以及模板等,本节对此进行简单介绍。
CPoint point——存放视图窗口像素点的坐标,其中point.x是水平方向的x坐标值,point.y是垂直方向的y坐标值。
COLORREF crColor——像素点的颜色值类,可以直接写为RGB(r,g,b),r、g、b分别对应三基色中的红色值、绿色值和蓝色值,取值范围在0~255之间。其中RGB(255,0,0)是红色,RGB(0,255,0)是绿色,RGB(0,0,255)是蓝色,RGB(255,255,255)是黑色。
COLORREF SetPixel(intx,inty,COLORREF crColor)——在绘图窗口的绘制点的函数,x和y是点的x坐标和y坐标,crColor是该点的颜色。例如pDC->SetPixel(x,y,RGB(255,0,0));命令在视图窗口的(x,y)点会绘制一个红色的点。
为了在视图窗口拾取多个点,可以利用集合类CArray来保存这些点。CArray是模板类,使用前需要加入模板类的头文件afxtempl.h。例如,在视图类中使用CArray,则在视图类的头文件CGTest001View.h中加入模板类的头文件afxtempl.h:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P31_17144.jpg?sign=1738858485-ukkFQsiSqAc3rjB1JmuTD7y5JvKW71c4-0-daf03ab86f078d943bc5cb33dc57203f)
使用时,首先在视图类头文件CGTest001View.h中声明点集的对象,如:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P32_17146.jpg?sign=1738858485-AxNtU8aJHb4y4vVvDfSuQn17793z1RKe-0-d43b74a2732e04c54083df80e737a8eb)
CArray中常用的相关函数如下:
m_pt_array.Add(point)——在集合尾部增加一个元素(例如,增加一个点);
m_pt_array.GetSize()——计算集合的长度;
m_pt_array.GetAt(i)——得到第i位元素,从第0位开始;
m_ptarray.RemoveAt(i)——删除集合中某个索引位置的元素;
m_ptarray.RemoveAll()——将集合内的所有元素都清空;
m_pt_array.Append(m_array)——复制另外一个集合的元素到当前的集合中。
在程序中使用数学运算时,需要加入支持数学计算函数的头文件:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P32_17147.jpg?sign=1738858485-NKeBiMAU5KWPkIotxn51xvJdT5RCRzot-0-b9a2261a244ba85d62d7e417ed39d650)
2.2.2 基本像素点的交互式绘制方法
为了达到方便的交互效果,可以利用鼠标在视图窗口拾取像素点,然后记录和实时显示这些像素点。例如,每单击一次,就将该点记录在点的集合里,记录点的代码在左键单击函数OnLButtonUp()中实现,并调用OnDraw()函数,将点集中的点显示出来。OnLButtonUp()和OnDraw()中的代码分别如下:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P32_17148.jpg?sign=1738858485-UeGx05Ba6R9Mg9N5Ihd0gE33zHmINAlH-0-83519dbfad544133826f360b71683630)
执行程序,在视图窗口每单击一次,就会以红色显示鼠标所在点,并显示该点的坐标值,如图2.2-1所示。
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P33_6913.jpg?sign=1738858485-M1fCnFOXj21yr4omMGU8zul6vpv8NELQ-0-5f92b39ba2a944802bad62a709b0c790)
图2.2-1 交互式绘制像素点
2.2.3 非模式对话框交互式实现方法及颜色对话框的使用
在进行计算机图形原理和算法编程时,可以采用非模式对话框实现图形实时交互。非模式对话框是指在对话框打开的同时,其他窗口还能够继续操作。非模式对话框的创建方法如下。
首先,在菜单栏中选择“插入”→“资源”命令,选择“资源类型”对话框,在新建的对话框上单击鼠标右键,选择“属性”,打开对话框属性设置窗口,在“常规”选项卡中可以修改对话框的ID,例如IDD_MDLG,在“更多样式”选项卡中,选中“可见”复选框,如图2.2-2所示。
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P34_6923.jpg?sign=1738858485-4yDHIr8N1CfoFHqDVKcZg6EiwV15VNlB-0-e8700c0644439e26e3bd7beb9f5aaa69)
图2.2-2 对话框属性设置
在对话框上双击,或者右击,从弹出的快捷菜单中选择“建立类向导”命令,为创建的对话框生成类和类文件,例如,类名为CCMDlg,则生成的对应类头文件和源文件分别为CMDlg.h和CMDlg.cpp。
在CMDlg.h头文件的对话框类中手动添加对话框基类的Create()函数:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P33_17149.jpg?sign=1738858485-NlVoUaPfsv9JZW64CGzkP7RkiBZyjjkd-0-2bd802a7656b08ff106101959e105dd1)
在CMDlg.cpp执行文件中添加该函数的实现代码:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P33_17150.jpg?sign=1738858485-xzxruYyVMLIXXIAknG9SwTovRtKXeA08-0-75ceaacd6cd99bcc764e9f49a31b6ebd)
当在视图类中使用该对话框时,首先在视图类定义的代码前加入对话框的头文件:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P33_6920.jpg?sign=1738858485-v0MVjPidY556YbcabwBAbLe4YEiTb3s6-0-5f5f8fe3f3ed54f31481602cbf453d08)
并在类中定义对话框的指针变量:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P34_17155.jpg?sign=1738858485-OnB3ArxCaOqm0JUle7PePYp3PaAkgQas-0-77b9219bb3a59537cf02775555d67995)
然后,在视图类CGTest001View.cpp的类构造函数中,建立该对话框对象指针:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P34_17154.jpg?sign=1738858485-K1njzfX8BO6ZINqo5iNXKzd7hRydGW3S-0-102487f8e78c4a49acde2f1facca69ae)
并在析构函数中,删除建立的对话框对象指针:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P34_17156.jpg?sign=1738858485-O5nzw23zaK8QX0fR5CxAAhi8tIDOU7ok-0-a657e9894241f47848f27ef3240acfe6)
可以通过菜单项或者工具栏打开对话框。例如,利用工具栏打开对话框,在视图类里,建立工具栏的消息映射函数(方法见上节),在工具栏的消息映射函数里判断对话框是否创建,如没有创建,则创建;如已创建,则显示。代码如下:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P34_17157.jpg?sign=1738858485-HlsWyYnr3cg8NjqBINvaglRoY8GZ4vhq-0-501569b414a06e46bfde5ad5ca28c409)
执行程序,打开软件,单击工具栏上的图标,即可打开对话框,如图2.2-3所示,这时仍可在视图窗口操作。
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P35_6960.jpg?sign=1738858485-7Y1X5IDE0biNXMlmYJjZ75S4aAsNnEcc-0-cafe153cba6e2f1ea7806f552e77a982)
图2.2-3 创建非模式对话框
视图窗口的数据可以传入到对话框中。例如,将视图窗口上点的坐标传到对话框中,首先在对话框中放入两个从控件中拖入的编辑框来显示坐标值,ID分别为IDC-EDITX和IDC-EDITY,通过在菜单栏中选择“建立类向导”→在Member Variables选项卡中选择对话框类,分别选中两个编辑框ID,单击“Add Variable...”按钮,如图2.2-4所示,为两个编辑框建立变量名m_X和m_Y,变量类型都是int整型。
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P36_6994.jpg?sign=1738858485-K9B2UZOQpVAmOKpxTOGdiJbzT5qwFotl-0-251ee6b8bf72e2fcacbc7f711ff62a2d)
图2.2-4 建立变量
在视图窗口单击时,如果对话框是创建好的,则把当前点的坐标值赋给对话框里的编辑框,并实时显示出来。代码如下:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P35_17159.jpg?sign=1738858485-fIzSSlUBvtej8ODkr8jAet2IHnBC0FYD-0-1f0401e2ba861414d447c012db02a4e6)
执行程序,当在视图窗口单击时,当前点的坐标值会实时显示在对话框中,如图2.2-5所示。
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P36_6997.jpg?sign=1738858485-1jWtOcdM5r1daClpgGAc5jnRSjt9UvQ2-0-51fd0c76144a0a58aeed2d2369dc0c6e)
图2.2-5 对话框实时显示视图窗口的数据
如果要把对话框里的数据传给视图窗口,则在对话框类中加入视图窗口的类变量,通过视图窗口的类变量把对话框的数据赋给视图窗口。首先,在对话框类头文件CMDlg.h中添加视图窗口类的引用:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P37_17160.jpg?sign=1738858485-B9gCwSP3vm0A4CzsZOCBkH9cCPptu97s-0-a4e2fa24451e7f94dff1c81dc9dfb906)
并在CCMDlg类中增加视图窗口类指针变量:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P37_17161.jpg?sign=1738858485-YhRILApul9eQHjguXPJspZEDBsuVnA5V-0-64decbd949b0f5b309cca5567295268f)
在源文件CMDlg.cpp增加对视图窗口类文件的引用:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P37_17162.jpg?sign=1738858485-sJ7QOgoX5sKdYbzZsapToXvXQhIjjNkn-0-9293f7d8ef075add06391a89ac51623e)
在视图窗口类CCGTest001View的构造函数中,在声明创建对话框后,还需要将视图窗口类的指针赋给对话框类中的视图窗口类变量:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P37_17163.jpg?sign=1738858485-UgawdKbUOJzxH0jOFBPe2vazbNZAcrZa-0-023ce2adabbf82906060f8ee2843cea5)
进行上述设置后编译程序,如果出现关于GetDocument的相关错误,还需要在CGTest001View.h中增加对CCGTest001Doc文档类的引用:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P37_17164.jpg?sign=1738858485-hB30QN6FXxAKkPYz7TvhhuwfhSwKOrg9-0-865ffd656d425c56e134635d7db69a2e)
这样,对话框中的视图窗口对象就和当前的视图窗口建立了联系。在对话框中输入点的坐标值,通过“确定”按钮的消息函数,就将该坐标值传给视图窗口的点集合中,并显示出来:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P37_17165.jpg?sign=1738858485-pIICy5cq5ax1mdCq14UiX4QddyTaUoyl-0-8efacea08d759fd30b5bfbabd8d7a291)
程序执行效果如图2.2-6所示。单击“确定”按钮就可以把对话框中的坐标值加入点集合中,并在视图窗口显示出来。使用上述方法就可以实现对话框和视图窗口的双向交互。
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P38_7038.jpg?sign=1738858485-41WNLc8oWghG98bGef1AYSQuLeoFU8sx-0-daf5e2ef73cf053a2288fb61bfc810bf)
图2.2-6 对话框中数据在视图窗口显示
在应用程序中绘制图形时,会为图形设置各种颜色,可以直接调用类似RGB(0~255,0~255,0~255)这个结构来设置颜色,也可以通过VC6.0提供的颜色对话框类CColorDialog获取颜色。CColorDialog对话框对象通过DoModal()函数直接打开,然后通过调用CColorDialog的一个结构体m_cc的成员rgbResult来获取选定的颜色值,再将这个值保存在设定的颜色变量中,就可以利用这个变量来设置颜色。代码如下:
![](https://epubservercos.yuewen.com/BFC8F2/12023547903396406/epubprivate/OEBPS/Images/Figure-P38_19396.jpg?sign=1738858485-ai71TaPunTUAgavW53PXSAaxlpGyBmcK-0-480af4986842514282a6da8a3792b87c)