MFC--教你如何使用画刷(2)
接下来我们用另外一个类CClientDC来实现我们的画线功能。
CClientDC是由CDC派生出来的一个类,在函数构造的时候就会去调用GetDC来获得一个句柄,而在析构的时候便调用ReleaseDC来释放一个句柄,来实现画线功能。
接下来让我们看一下代码的实现。
CClientDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
如今实现了我们实现了在View视图内画线,那么,现在,我们如何实现在Frame框架上实现画线呢?
下面我将为你展示一下如何在Frame框架 上画图的实现:由于Frame是view的父窗口,要想实现此功能仅需在源代码中修改CClientDC dc(this)这句代码:
CClientDC dc(GetParent());
编译运行即可。
既然可以在工具栏上画图,那么又该如何实现在视图整个窗口画图呢。要想实现此功能,我们先要来认识一下WindowDC这个类,WindowDC是CDC派生出来的一个类,当在构造函数时,WindowDC会调用GetWindowDC来获得一个句柄,而在析构的时候去调用ReleaseDC来释放一个句柄。在视图类相应的类中编辑一下代码就可实现:
CWindowDC dc(GetParent());
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
编译运行即可。
我们再来看看如何实现在桌面窗口画图。首先,要介绍一下一个类,那就是GetDesktopWindow类,通过这个类我们就可以获得整个windows的桌面窗口。实现的原理就是这样。接下来让我们来看一下代码的实现:
CWindowDC dc(GetDesktopWindow());
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
学会了如何画出一条线,那么是不是要来看一下如何该变线条的颜色属性呢?首先,让我们来了解一下Cpen这个类:
CPen( int nPenStyle, int nWidth, COLORREF crColor );其中,第一个参数是画笔的类型,第二个参数是画笔的宽度,第三个参数是画笔的颜色,画笔的颜色可以通过RGB三原色来修改。
COLORREF RGB( BYTE byRed, // red component of color BYTE byGreen, // green component of color BYTEbyBlue // blue component of color );
接下来让我们看看代码的编辑:
Cpen pen(PS_SOLD,1,RGB(255,0,0)); //创建画笔
CClient dc(this);
Cpen *pOldPen=dc.SelectObject(&pen); //选用新的画笔去替换旧的画笔
dc.MOveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen); //选回旧的画笔
有了画笔,那么,如何创建画刷和位图画刷呢?首先来看一下画刷是个什么情况:画刷分为颜色画刷CBrush( COLORREF crColor )和位图画刷CBrush( int nIndex, COLORREF crColor )
CBrush( CBitmap* pBitmap ),先来看看颜色画刷:
CBrush brush(RGB(255,0,0)); //创建画刷
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush); //设计画刷
位图画刷的创建:位图画刷创建之后我们不能直接使用这个画刷,我们要使用他的初始化函数初始化之后才能使用。
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
CBrush brush(&bitmap);
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);
到这里就有一个很有趣的问题了,在很多地方我们需要的不仅仅是位图的全部,有时候我们只需要他的一部分,比如只需框架就行,这时候,我们就需要一个透明的画刷。那么我们怎么样才可以去获得一个透明的画刷呢?我们可以试着从CBrush中找,但是结果很是糟糕。那怎么办呢,别急别急,我们还有一个好东西,就是GetStockObject这个类,但是,问题又来了,我们的GetStockObject返回的是一个句柄,而我们现在需要的是一个对象,我们该如何把一个句柄转换成一个对象呢?这是我们就要用到另一个类,那就是FromHandle,这个类的作用是:Returns a pointer to a CBrush object when given a handle to a Windows HBRUSH object.,即让一个句柄转化成一个C++类的指针返回。问题决绝的差不多了,我们来试着实现一下吧:
CClientDC dc(this);
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrush *pOldBrush=dc.SelectObject(pBrush);
dc.Rectangle(CRect(m_ptOrigin,point));
dc.SelectObject(pOldBrush);
这里又有个有趣的问题:那就是在
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));这句中我们引用FromHandle是不是用的点引用的方法,而是用两个冒号引用,这是为什么呢?这是因为
static CBitmap* PASCAL FromHandle( HPALETTE hPalette );
在这里,FromHandle是定义为静态的变量,在引用静态变量的时候,我们可以用两个冒号,因为静态的变量在我们调用这个类的时候已经在内存内为它分配好了内存空间,所以可以直接引用,而非静态的函数变量或类就只能用点引用方法引用。
到这里,画图,我们就只剩下一个知识点了,那就是实现画笔画连续曲线的功能。
要画出一条连续的曲线,我们首先还是要捕捉到画笔的起点,要捕捉到其他的点,我们就要有一个鼠标移动的消息,在鼠标移动中做一个命令响应,通过这个命令传进来的点不断的画一条条很短很短的线段,吧线段全部连起来之后就是一条曲线了。按照这种思路,我们就来写写代码,看看如何实现这种功能:
1、在view类上右击,添加windows中的MOUSEMOVE消息处理。这个消息只要我们的鼠标有移动就会把消息传进来,这并不是我们想要的,我们要的是,当鼠标左键按下去之后的点,知道鼠标左键松开时的所有的点传进来,开始作图。这时候,我们可以设置一个bool类型的变量,来判断是否按下了鼠标左键。当鼠标左键按下去的时候,我们把这个变量设置为真,当鼠标左键松开的时候,就设置为假。
2、在view类上右击,添加一个成员变量。在view的构造函数中把这个变量初始化为FALSE。当鼠标左键按下去的时候,我们把这个变量设置为TRUE。当鼠标左键弹起来的时候,我们把这个变量设置为FALSE。
3、首先创建一个DC,然后在鼠标移动里面先判断一下。实现代码如下:
CClientDC dc(this);
//CPen pen(PS_SOLD,1,RGB(255,0,0));
//CPen *pOldPen=dc.SelectObject(&pen);
if(m_Draw==TRUE)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(point); //在这里,我们要稍稍做一下手脚,到这里,第一小段的线段画完了,作为一条,我们还要继续画小线段,这是就要把原来的终点变成现在的始点了
m_ptOrigin=point;
}
//dc.SelectObject(pOldPen);
添加注释掉的部分可以改变曲线的颜色哦亲。
画了曲线,就一定可以画出扇形滴,我们来看看怎么画出个扇形。
1、我们先添加一个私有成员变量用来标记上一线条的终点,m_ptOld,并在构造函数中对其做初始化m_pOld=0,当鼠标左键按下去的时候,我们就让ptOld等于原点。
2、在鼠标移动命令里面添加代码。首先,我们从m_ptOrigin出发,划出一条线到m_ptOld,然后再画一条线从m_ptOrigin到point。代码如下:
CClientDC dc(this);
//CPen pen(PS_SOLD,1,RGB(255,0,0));
//CPen *pOldPen=dc.SelectObject(&pen);
if(m_Draw==TRUE)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(m_pOld); //在这里,我们要稍稍做一下手脚,到这里,第一小段的线段画完了,作为一条,我们还要继续画小线段,这是就要把原来的终点变成现在的始点了
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
m_ptOld=point;
}
//dc.SelectObject(pOldPen);
嘻嘻,人类的贪婪是不会得到满足滴哦,让我们在来画带边界的扇形吧。这时我们只要做小小的改动就可以实现哦。
我们只要把dc.MoveTo(m_ptOrigin)这句改为:dc.MoveTo(m_ptOld),这样,我们就大功告成了。
我们的MFC画图学习到这就差不到了,在这里,祝各位看我的博客的读者学有所成,当然,如果有什么不足之处,还请见谅。
到这,我还有送读者一个函数:SetROP2
这个函数主要是用来设置绘画模式的一个函数,在这个函数中只有一个参数,用来设置绘画模式,一下是这个函数的可用参数:
Parameters
- nDrawMode
- The new drawing mode. It can be any of the following values:
- R2_BLACK Pixel is always black.
- R2_WHITE Pixel is always white.
- R2_NOP Pixel remains unchanged.
- R2_NOT Pixel is the inverse of the screen color.
- R2_COPYPEN Pixel is the pen color.
- R2_NOTCOPYPEN Pixel is the inverse of the pen color.
- R2_MERGEPENNOT Pixel is a combination of the pen color and the inverse of the screen color (final pixel = (NOT screen pixel) OR pen).
- R2_MASKPENNOT Pixel is a combination of the colors common to both the pen and the inverse of the screen (final pixel = (NOT screen pixel) AND pen).
- R2_MERGENOTPEN Pixel is a combination of the screen color and the inverse of the pen color (final pixel = (NOT pen) OR screen pixel).
- R2_MASKNOTPEN Pixel is a combination of the colors common to both the screen and the inverse of the pen (final pixel = (NOT pen) AND screen pixel).
- R2_MERGEPEN Pixel is a combination of the pen color and the screen color (final pixel = pen OR screen pixel).
- R2_NOTMERGEPEN Pixel is the inverse of the R2_MERGEPEN color (final pixel = NOT(pen OR screen pixel)).
- R2_MASKPEN Pixel is a combination of the colors common to both the pen and the screen (final pixel = pen AND screen pixel).
- R2_NOTMASKPEN Pixel is the inverse of the R2_MASKPEN color (final pixel = NOT(pen AND screen pixel)).
- R2_XORPEN Pixel is a combination of the colors that are in the pen or in the screen, but not in both (final pixel = pen XOR screen pixel).
- R2_NOTXORPEN Pixel is the inverse of the R2_XORPEN color (final pixel = NOT(pen XOR screen pixel)).
MFC--教你如何使用画刷(2)的更多相关文章
- MFC更换画笔(画刷)颜色以及画眼睛(GDI画图)
MFC画眼睛 换画笔(画刷)颜色(参考链接:https://blog.csdn.net/sunxiving/article/details/51272001) 由于画笔一旦创建后就无法修改.所以要修改 ...
- VS2010/MFC编程入门之五十一(图形图像:GDI对象之画刷CBrush)
上一节中鸡啄米主要讲的是画笔CPen的用法,前面也说了,GDI对象中最常用的就是画笔和画刷,本节就讲讲画刷CBrush. 鸡啄米依然是通过实例的方式来说明画刷的用法.此实例要实现的功能是,对话框上有一 ...
- MFC 画笔CPen、画刷CBrush
新建单个文档的MFC应用程序,类视图——View项的属性——消息,WM_PAINT,创建OnPaint()函数 dc默认有一个画笔(实心1像素宽黑线). CPen画笔非实心线像素宽必须为1,否则膨胀接 ...
- 撩妹技能 get,教你用 canvas 画一场流星雨
开始 妹子都喜欢流星,如果她说不喜欢,那她一定是一个假妹子. 现在就一起来做一场流星雨,用程序员的野路子浪漫一下. 要画一场流星雨,首先,自然我们要会画一颗流星. 玩过 canvas 的同学,你画圆画 ...
- VS2010-MFC(图形图像:GDI对象之画刷CBrush)
转自:http://www.jizhuomi.com/software/248.html 上一节讲的是画笔CPen的用法,前面也说了,GDI对象中最常用的就是画笔和画刷,本节就讲讲画刷CBrush. ...
- WPF样式之画刷结合样式
第一种画刷,渐变画刷GradientBrush (拿线性渐变画刷LinearGradientBrush(其实它涵盖在GradientBrush画刷内.现在拿他来说事.),还有一个圆心渐变画刷Radia ...
- C#GDI+基础(三)画刷详解
SolidBrush:一般的画刷,通常只用一种颜色去填充GDI+图形 创建一般画刷: SolidBrush sbBrush1 = new SolidBrush(Color.Green); HatchB ...
- [游戏模版3] Win32 画笔 画刷 图形
>_<:introduce the functions of define\create\use pen and brush to draw all kinds of line and s ...
- Unity3D-terrain brush地形画刷无法出现在Scene中,无法刷地图2
原因大概是 画刷brush 太小了,地图也太小了,没出出现. 如图,非正常状态: 解决方法: tag: terrain brush not working unity
- WPF 动画(形状、画刷)
一:形状 在WPF用户界面中,可以通过形状(Shape)来绘制直线.椭圆.矩形及一些多边形的类.通过这些基本的图像,组合成为复杂的图形. Shape类中,主要的形状有Rectangle(),Ellip ...
随机推荐
- WPF开发快速入门【5】DataGrid的使用
概述 DataGrid是最常用的一种列表数据展现控件,本文介绍DataGrid的一些常用操作,包括:展示.新增.删除.修改等.以下代码基于Stylet框架实现. 数据展示 DataGrid用于对象列表 ...
- 【已解决】docker overlay2占用大量磁盘空间处理方法
在使用docker容器的时候遇到了容量上的问题,做一个记录 处理方式1:在使用docker时,往往会出现磁盘空间不足,导致该问题的通常原因是因为docker中部署的系统输出了大量的日志内容. 此时,可 ...
- ABP邮件发送
ABP Vnext发邮件要使用AbpMailKitModule的实现IEmailSender,要检查添加了Volo.Abp.MailKit,其dependon 要添加typeof() 它使用Sett ...
- iOS 如何保持线程一直在运转
1.简单的可以想到,写一个while循环 while (TRUE) { } 但是这种方式存在缺陷,将导致CPU占用100%,两个核. p.p1 { margin: 0; font: 12px &quo ...
- umount 报错umount: /new_room: target is busy. (In some cases useful info about processes that use the device is found by lsof(8) or fuser(1))
挂载逻辑卷后,尝试更新逻辑卷的文件系统 [root@server lost+found]# umount /new_room/ umount: /new_room: target is busy. ( ...
- TypeScript keyof
keyof 是 TypeScript 中的一个关键字,用于获取一个类型的所有键(属性名)构成的联合类型.它主要用于在类型系统中引用对象类型的键. 以下是一些 keyof 的用法和示例: 1. 获取对象 ...
- react跨组件通信
在react没有类似vue中的事件总线来解决这个问题,一是我们借助它们共同的父级组件通过代理的方式来实现,但过程会相当繁锁.react提供了Context来实现跨组件通信, 而不必显式地通过组件树的逐 ...
- ssh进阶
1.ssh客户端工具 查看参数和帮助方法 ==ssh --help== ==man ssh== 常见参数 windows linux macos 提供的ssh命令,会有些区别,查看帮助后使用即可. l ...
- 说一下 JSP 的 4 种作用域?
page:代表与一个页面相关的对象和属性. request:代表与客户端发出的一个请求相关的对象和属性.一个请求可能跨越多个页面,涉及多个 Web 组件:需要在页面显示的临时数据可以置于此作用域. s ...
- npm 发布自己的组件库
npm 发布组件库步骤 第一步:注册 npm 账号 第二步:编写自己的组件库 第三部:编写 package.json 可以通过命令生成 npm init { "name": &qu ...