轉(zhuǎn)帖|其它|編輯:郝浩|2010-10-18 13:47:10.000|閱讀 722 次
概述:本文主要講述如何構(gòu)建儀表、圖表控件的繪制框架,希望對(duì)大家有用。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
編寫圖形相關(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ì)出框架。
框架的建立
“如果說我比別人看得更遠(yuǎn)些,那是因?yàn)槲艺驹诹司奕说募缟?rdquo;。.Net上開源圖表控件比較多,在這里我們分析一下MS Graph Demo。
PieSlice表示Pie中的單個(gè)扇形,_value用來(lái)計(jì)算百分比,_color是此扇形的填充顏色。
PieSliceCollection是PieSlice集合。
PieGraph類內(nèi)置一個(gè)PieSliceCollection對(duì)象,類中其它的數(shù)據(jù)是描述Pie整體的數(shù)據(jù)(寬高,邊框?qū)挾龋尘邦伾?hellip;…)。
PieGraphRenderer類通過 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)用過程中,當(dāng)需要把Pie圖對(duì)象轉(zhuǎn)換成Bar圖對(duì)象時(shí),MS Graph Demo的現(xiàn)有框架便不能實(shí)現(xiàn)。
由此可見,MS Graph Demo的框架不夠靈活,原因在于功能數(shù)據(jù)和外觀數(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的派生類再次組合。
由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)用
1、YFillBase和YShapeBase的配合使用:
YFillGradient fill; YEllipse shape; shape.SetFill(&fill); shape.Draw(g);
2、透明儀表罩的繪制
表罩由2個(gè)YRange和1個(gè)YEllipes,YRange和YEllipes用特定填充。
FillGradient glassFill;
glassFill.Border.Hide();
glassFill.Background.Show();
glassFill.Background.FillColor.SetColor(20,240,240,240);
glassFill.Background.FillEndColor.SetColor(180,120,120,120);
glassFill.Background.SetGradientType(YGradientType_ForwardDiagonal);
YEllipse glassBK;
glassBK.SetFill(&glassFill);
glassBK.Draw(g);
//反光
YFillGradient lightFill;
lightFill.Border.Hide();
lightFill.Background.FillColor.SetColor(210,255,255,255);
lightFill.Background.FillEndColor.SetColor(210,255,255,255);
YRange range;
range.SetStartWidth(width);
range.SetEndWidth(width);
range.SetFill(&lightFill);
range.SetPlacement(Inside);
range.SetSweepAngle(24);
range.SetStartAngle(110);
range.Draw(g);
range.SetStartAngle(136);
range.Draw(g);
3、刻度的繪制
由于框架的原因,可以非常方便的更改刻度的形狀和填充。(加入一個(gè)最基本的刻度)
YScaleTextCircular是環(huán)繞文字。
YScaleCircular是環(huán)形刻度。
YScaleXY是線型刻度。
4、圓表,直表與刻度對(duì)應(yīng)的文字
針對(duì)圓表的刻度文字的種類和位置定義。
環(huán)繞文字與環(huán)形刻度一般同時(shí)出現(xiàn),這就要求環(huán)繞文字必須遵循某種規(guī)則,使文字和刻度不重疊上,且很自然。
以下兩圖展示了這種規(guī)則的定義。
圖 "向心"文字位置定義
YScaleTextCircular ScaletextCircular;
YTextHelper* pScaletextHelper = NULL;
pScaletextHelper = new YTextHelper;
pScaletextHelper->SetSize(10.f);
pScaletextHelper->FontColor.SetColor(128,128,128);
ScaletextCircular.AddText(pScaletextHelper);
pScaletextHelper = new YTextHelper;
pScaletextHelper->SetBold(TRUE);
pScaletextHelper->SetSize(12.f);
pScaletextHelper->SetFontName("黑體");
pScaletextHelper->FontColor.SetColor(255,44,44);
ScaletextCircular.AddText(pScaletextHelper);
pScaletextHelper = new YTextHelper;
pScaletextHelper->FontColor.SetColor(51,51,255);
ScaletextCircular.AddText(pScaletextHelper);
ScaletextCircular.SetType(1);
ScaletextCircular.AddText("你");
ScaletextCircular.AddText("有沒有");
ScaletextCircular.AddText("想過");
ScaletextCircular.AddText("罐頭");
ScaletextCircular.AddText("的");
ScaletextCircular.AddText("感受");
ScaletextCircular.AddText("?");
ScaletextCircular.SetDefault(FALSE);
ScaletextCircular.SetOrigin(point_this.X,point_this.Y);
ScaletextCircular.SetRadius((int)(cs_this.Width*0.3f));
ScaletextCircular.SetPlacement(Inside);
ScaletextCircular.Draw(g);
pScaletextHelper = NULL;
水平文字
// ∧
// │
// Outside │ Inside
// │
// │ Inside
// └───────>
// Outside
//
YScaleTextXY m_ScaleText;
YTextHelper* pScaletext_helper = NULL;
pScaletext_helper = new YTextHelper;
pScaletext_helper->SetSize(8.5f);
pScaletext_helper->SetAngle(-30);
pScaletext_helper->SetHorizontal(StringAlignmentFar);
m_ScaleText.AddText(pScaletext_helper);
m_ScaleText.SetMin(0);
m_ScaleText.SetMax(600);
m_ScaleText.SetBoolY(FALSE);
m_ScaleText.SetOrientation(TRUE);
m_ScaleText.SetOrigin(30.f,50.f);
m_ScaleText.SetLength(380.f);
m_ScaleText.Draw(g);
m_ScaleText.AddText("一月");
m_ScaleText.AddText("二月");
m_ScaleText.AddText("三月");
m_ScaleText.AddText("四月");
m_ScaleText.AddText("五月");
m_ScaleText.AddText("六月");
m_ScaleText.AddText("七月");
m_ScaleText.SetDefault(FALSE);
m_ScaleText.SetOrigin(30.f,80.f);
m_ScaleText.Draw(g);
pScaletext_helper = NULL;
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:網(wǎng)絡(luò)轉(zhuǎn)載