构建仪表、图表控件的绘制框架
開(kāi)發(fā)環(huán)境: VS2003 + Windows XP SP2
測(cè)試環(huán)境: Windows XP SP2
Demo截圖
?
編寫(xiě)圖形相關(guān)的控件需要完成兩部分:1 繪制;2 與窗口類(泛指)集成使之成為控件。本文重點(diǎn)在于“繪制”部分,提出一個(gè)較靈活的框架。用VC的GDI+實(shí)現(xiàn)框架,并在Demo中簡(jiǎn)單封裝成圓表和直表控件。圖一是要實(shí)現(xiàn)的目標(biāo)(圓表、直表等儀表,指示燈,圖表,旋鈕,滑塊等),由這些目標(biāo),經(jīng)需求分析后,設(shè)計(jì)出框架。
?
圖一
框架的建立
“如果說(shuō)我比別人看得更遠(yuǎn)些,那是因?yàn)槲艺驹诹司奕说募缟稀薄?Net上開(kāi)源圖表控件比較多,在這里我們分析一下MS Graph Demo。圖二 是其繪制Pie圖表的類圖。
?
圖二 MS Graph Demo繪制Pie圖表的結(jié)構(gòu)
PieSlice表示Pie中的單個(gè)扇形,_value用來(lái)計(jì)算百分比,_color是此扇形的填充顏色。
PieSliceCollection是PieSlice集合。
PieGraph類內(nèi)置一個(gè)PieSliceCollection對(duì)象,類中其它的數(shù)據(jù)是描述Pie整體的數(shù)據(jù)(寬高,邊框?qū)挾?#xff0c;背景顏色……)。
PieGraphRenderer類通過(guò) DrawGraph函數(shù)繪制Pie圖,類內(nèi)置一個(gè)PieGraph對(duì)象。
此結(jié)構(gòu)有諸如數(shù)據(jù)結(jié)構(gòu)和算法的分離等的優(yōu)點(diǎn),但也有它的局限性。1 它的框架是建立在功能分類上的,如,Pie圖、Bar圖。PieSlice中不僅有功能數(shù)據(jù)_value還有外觀數(shù)據(jù)_color。假如不再填充純色,而是填充圖像,那么就必須修改PieSlice,增加_image:Image屬性; PieGraphRenderer也需相應(yīng)的修改。假設(shè)將上述修改擴(kuò)展到Pie圖表以外的其它類型的圖表,如:Bar圖表、A圖表、B圖表,那么BarSlice、ASlice、BSlice,及三者相應(yīng)的Renderer類也必須修改,工作量多且重復(fù)。2 在應(yīng)用過(guò)程中,當(dāng)需要把Pie圖對(duì)象轉(zhuǎn)換成Bar圖對(duì)象時(shí),MS Graph Demo的現(xiàn)有框架便不能實(shí)現(xiàn)。
由此可見(jiàn),MS Graph Demo的框架不夠靈活,原因在于功能數(shù)據(jù)和外觀數(shù)據(jù)沒(méi)有分離。
圖三是我所設(shè)計(jì)的框架,用一句話概述:由YFillBase填充形狀(YShapeBase),邏輯(YPaintBase)負(fù)責(zé)把形狀組合起來(lái)。
?
圖三
框架由三個(gè)基礎(chǔ)類YPaintBase,YShapeBase和YFillBase組成。其中YFillBase是填充基礎(chǔ)類(簡(jiǎn)稱“填充”),它負(fù)責(zé)對(duì)象顏色、圖像的填充,邊框等。YShapeBase是基本圖形基礎(chǔ)類(簡(jiǎn)稱“形狀”),由此類派生出簡(jiǎn)單的基本圖形,如:圓,三角,五角星,特殊指針樣式……。YPaintBase是邏輯組合基礎(chǔ)類(簡(jiǎn)稱“邏輯”),由YPaintBase把YShapeBase和YFillBase進(jìn)行組合,構(gòu)建出復(fù)雜圖形,而復(fù)雜圖形可由YPaintBase的派生類再次組合。
圖四演示了應(yīng)用框架構(gòu)建儀表控件的背景和指針。
圖四
由YShapeBase派生出,將YPointer對(duì)象的pShape指向YRectangle對(duì)象,就可以得到矩形指針。同理將YBackground對(duì)象的pShape指向YRectangle對(duì)象,就得到了矩形背景(圖五)。
?
圖五
如果需要升級(jí),添加新的形狀如三角形YTriangle(圖六),也就相應(yīng)得到了三角型指針和三角形背景。
圖六
同樣由YFillBase派生一種特殊的圖片填充YFillImage(圖七),其它地方的代碼不用修改,就可以得到用這種填充的任意形狀指針和背景。
圖七
在實(shí)際項(xiàng)目中,類似指針,背景的元素很多,應(yīng)用此框架可以使編碼減少,功能倍增,易于升級(jí)、維護(hù)。
圖九
下圖演示應(yīng)用框架構(gòu)建類似MS Graph Demo的Pie圖表和Bar圖表,是不是很容易加入填充圖像和在Pie圖Bar圖間轉(zhuǎn)換^_^。
圖十
框架的在繪制儀表控件中的應(yīng)用
1、YFillBase和YShapeBase的配合使用:
?
1.YFillGradient fill;2.?3.YEllipse shape;4.?5.shape.SetFill(&fill);6.?7.shape.Draw(g);2、透明儀表罩的繪制
表罩由2個(gè)YRange和1個(gè)YEllipes,YRange和YEllipes用特定填充。
01.FillGradient glassFill;02.glassFill.Border.Hide();03.glassFill.Background.Show();04.glassFill.Background.FillColor.SetColor(20,240,240,240);05.glassFill.Background.FillEndColor.SetColor(180,120,120,120);06.glassFill.Background.SetGradientType(YGradientType_ForwardDiagonal);07.YEllipse glassBK;08.glassBK.SetFill(&glassFill);09.glassBK.Draw(g);10.?11.//反光12.YFillGradient lightFill;13.lightFill.Border.Hide();14.lightFill.Background.FillColor.SetColor(210,255,255,255);15.lightFill.Background.FillEndColor.SetColor(210,255,255,255);16.YRange range;17.range.SetStartWidth(width);18.range.SetEndWidth(width);19.range.SetFill(&lightFill);20.range.SetPlacement(Inside);21.range.SetSweepAngle(24);22.range.SetStartAngle(110);23.range.Draw(g);24.range.SetStartAngle(136);25.range.Draw(g);
3、刻度的繪制
由于框架的原因,可以非常方便的更改刻度的形狀和填充。(加入一個(gè)最基本的刻度)
?
YScaleTextCircular是環(huán)繞文字。
YScaleCircular是環(huán)形刻度。
YScaleXY是線型刻度。
?
4、圓表,直表與刻度對(duì)應(yīng)的文字
針對(duì)圓表的刻度文字的種類和位置定義。
?
圖 環(huán)繞排列文字的四種方式
環(huán)繞文字與環(huán)形刻度一般同時(shí)出現(xiàn),這就要求環(huán)繞文字必須遵循某種規(guī)則,使文字和刻度不重疊上,且很自然。
以下兩圖展示了這種規(guī)則的定義。
?
“向下”文字位置的定義
?
圖 "向心"文字位置定義
01.YScaleTextCircular ScaletextCircular;02.YTextHelper* pScaletextHelper = NULL;03.pScaletextHelper = new YTextHelper;04.pScaletextHelper->SetSize(10.f);05.pScaletextHelper->FontColor.SetColor(128,128,128);06.ScaletextCircular.AddText(pScaletextHelper);07.pScaletextHelper = new YTextHelper;08.pScaletextHelper->SetBold(TRUE);09.pScaletextHelper->SetSize(12.f);10.pScaletextHelper->SetFontName("黑體");11.pScaletextHelper->FontColor.SetColor(255,44,44);12.ScaletextCircular.AddText(pScaletextHelper);13.pScaletextHelper = new YTextHelper;14.pScaletextHelper->FontColor.SetColor(51,51,255);15.ScaletextCircular.AddText(pScaletextHelper);16.ScaletextCircular.SetType(1);17.ScaletextCircular.AddText("你");18.ScaletextCircular.AddText("有沒(méi)有");19.ScaletextCircular.AddText("想過(guò)");20.ScaletextCircular.AddText("罐頭");21.ScaletextCircular.AddText("的");22.ScaletextCircular.AddText("感受");23.ScaletextCircular.AddText("?");24.ScaletextCircular.SetDefault(FALSE);25.ScaletextCircular.SetOrigin(point_this.X,point_this.Y);26.ScaletextCircular.SetRadius((int)(cs_this.Width*0.3f));27.ScaletextCircular.SetPlacement(Inside);28.ScaletextCircular.Draw(g);29.pScaletextHelper = NULL;
繪制線型文字
01.水平文字02.// ∧03.// │04.//? Outside │? Inside05.// │06.// │ Inside07.// └───────>08.// Outside 09.//10.YScaleTextXY m_ScaleText;11.YTextHelper* pScaletext_helper = NULL;12.pScaletext_helper = new YTextHelper;13.pScaletext_helper->SetSize(8.5f);14.pScaletext_helper->SetAngle(-30);15.pScaletext_helper->SetHorizontal(StringAlignmentFar);16.m_ScaleText.AddText(pScaletext_helper);17.m_ScaleText.SetMin(0);18.m_ScaleText.SetMax(600);19.m_ScaleText.SetBoolY(FALSE);20.m_ScaleText.SetOrientation(TRUE);21.m_ScaleText.SetOrigin(30.f,50.f);22.m_ScaleText.SetLength(380.f);23.m_ScaleText.Draw(g);24.m_ScaleText.AddText("一月");25.m_ScaleText.AddText("二月");26.m_ScaleText.AddText("三月");27.m_ScaleText.AddText("四月");28.m_ScaleText.AddText("五月");29.m_ScaleText.AddText("六月");30.m_ScaleText.AddText("七月");31.m_ScaleText.SetDefault(FALSE);32.m_ScaleText.SetOrigin(30.f,80.f);33.m_ScaleText.Draw(g);34.pScaletext_helper = NULL;
總結(jié)
以上是生活随笔為你收集整理的构建仪表、图表控件的绘制框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 三种常见中文内码的转换方法
- 下一篇: Java调用C++webservice接