昨天是清明节,不能回老家为各位西逝先辈扫墓,只能在吃晚饭之前,供奉了一下,愿各位先辈无尘世之烦扰,享极乐之悠闲。
今天,生活继续,工作继续,还要上班呢,只不过上班可以在家里,也可以在户外,哈。
我还是编我的程序吧。
为了更丰富界面效果,我决定,即使不实现任意角度的旋转,也要实现填充方式的旋转处理,因此,就拿Brush来做事。
目前为止,已实现各种正常状态下的填充,包括单色、渐变、纹理与图案方式,但填充方式的旋转处理就需要进行变换了。
粗看一下,应该是调用Gdiplus下的RotateTransform进行,学习别的软件,发现旋转还有一个中心点,这个点需要用TranslateTransform来设置。
OK,万事俱备,开始实现吧。
先做界面,把变形所需要的界面编辑加入到已有界面,这个简单,10分钟就搞定。
顺便把平移与缩放做在一块。
第二步,实现模型处理,使得数据上流通可行,这也不是难事。
在TCbwBrushData类中加入
double
FTransX;
//
水平位移
double FTransY; // 垂直位移
double FScaleX; // 水平缩放
double FScaleY; // 垂直缩放
double FDegree; // 旋转角度
double FTransY; // 垂直位移
double FScaleX; // 水平缩放
double FScaleY; // 垂直缩放
double FDegree; // 旋转角度
并将之声明为相应属性即可。
第三步,实现文件I/O,将上述几个成员在I/O处理函数中进行考虑一下即可。
第四步,实现画图效果,在创建画刷时考虑到这些成员,以渐变型画刷为例,加入相应判断。
Gdiplus::LinearGradientBrush
*
brush
=
new
Gdiplus::LinearGradientBrush(rf, beginColor, endColor, lm);
brush -> SetGammaCorrection(data -> Gamma);
if (data -> MixStyle == 0 )
brush -> SetBlendTriangularShape(x, y);
else
brush -> SetBlendBellShape(x, y);
if (data -> Degree)
... {
brush->ResetTransform();
brush->TranslateTransform(r.left, r.top);
brush->RotateTransform(data->Degree);
}
if (data -> TransX || data -> TransY)
brush -> TranslateTransform(data -> TransX, data -> TransY);
if (data -> ScaleX != 1 || data -> ScaleY != 1 )
brush -> ScaleTransform(data -> ScaleX, data -> ScaleY);
brush -> SetGammaCorrection(data -> Gamma);
if (data -> MixStyle == 0 )
brush -> SetBlendTriangularShape(x, y);
else
brush -> SetBlendBellShape(x, y);
if (data -> Degree)
... {
brush->ResetTransform();
brush->TranslateTransform(r.left, r.top);
brush->RotateTransform(data->Degree);
}
if (data -> TransX || data -> TransY)
brush -> TranslateTransform(data -> TransX, data -> TransY);
if (data -> ScaleX != 1 || data -> ScaleY != 1 )
brush -> ScaleTransform(data -> ScaleX, data -> ScaleY);
在画图的时候,设置旋转角度为30,YEAH,效果出来了。
吸取以前的教训,不敢狂喜先,只好先欣赏一下,咋就这么漂亮呢,呵呵。
待平静了一下,然后拖动,结果发现一个问题,拖动时,里面的填充效果在不断变化,就好象那理发店前的灯柱效果一下,啊?这可不行,应该保证拖动时填充效果不变化。
应该较简单吧,回头修改brush->TranslateTransform(r.left, r.top);中的偏移量试试。
这一修改,耗时2个小时,各种参数均试过了,还是不行,以下为一些试验参数。
0, 0
r.left, r.top
r.left + r.Width() / 2, r.top
r.left + r.Width(), r.top
r.left, r.top + r.Height() / 2
r.left + r.Width() / 2, r.top + r.Height() / 2
r.left + r.Width(), r.top + r.Height()
-r.left, 0
…
刚开始试的时候,还不觉得什么,但越往后,心越凉。从原理的角度,这也说不通呀,应该绕r.left, r.top转呀,但为什么就不行呢。
开始上网找帮助,但所有资料均指向这一标准答案,即先TranslateTransform,然后RotateTransform,我简直失望了。
网上不行,再看书吧,把《GDI+图形程序设计》再翻了一遍,大致如此。
再上MSDN,简直是一通屁话。心情不好,把微软也稍带上。
现在,做还是不做,这是个问题。
休息一下,换换脑筋。
2小时后,重拾该问题,一切依然。
其间,甚至重启了计算机,看看是不是Windows运行的历史问题,做这事的时候,我不由苦笑,这比中500万大奖还难,就算是这样解决了,程序也不敢发行。
幸好,这是不问题的解决答案,不然,我找谁说理去。
呃,是不是乘的顺序问题,Preappend与Append?一试,还不如之前,因为,如果之前用r,top,至少垂直移动效果不会变。但改后,群魔乱舞。
再深入地看一下原理,变换是怎么回事,矩阵谁都懂,唉。
是不是CB实现的问题?这个CB里面的BUG时不时都会有一个,我想这也有可能。
把头文件仔细研究一下,发现里面的函数和别的程序语言差不多,都是那些函数。
不过,这次发现了,可以直接设置变换矩阵,试试吧。
if
(data
->
Degree)
... {
Gdiplus::Matrix * m = new Gdiplus::Matrix();
m->RotateAt(data->Degree, Gdiplus::PointF(r.left + r.Width() / 2, r.top + r.Height() / 2));
brush->SetTransform(m);
delete m;
}
... {
Gdiplus::Matrix * m = new Gdiplus::Matrix();
m->RotateAt(data->Degree, Gdiplus::PointF(r.left + r.Width() / 2, r.top + r.Height() / 2));
brush->SetTransform(m);
delete m;
}
运行一下,呀,我的那个心呀,都快飞出来了,一切效果都是我想要的。
再测试了一会,OK。
赶紧存盘,备份,关机,找朋友喝茶玩去。
一天就做了这点事,我也很高兴,也发给各位朋友看下,免得再走弯路。
想看看效果的可以到
http://www.drgraph.com/viewthread.php?tid=22&extra=page%3D1去下载。具体操作步骤就不再说了。