將氣球Windows新增到. net應用程式
介紹 計算形狀 制約該地區 突出一個影子 結論 類結構 建立歷史 版權 介紹 本文介紹了BalloonWindow類。BalloonWindow的設計目標是允許任何。net應用程式顯示功能類似於作業系統的氣球,如圖2所示。 用c#編寫的,BalloonWindow公開了必要的功能來完全定製氣球的外觀。自定義的例子包括:設定背景樣式或顏色;通過調整錨點位置、角曲率或陰影效果來定義氣球的佈局;並像所有其他表單類一樣在氣球中放置控制元件。 計算形狀 氣球的形狀由GraphicsPath物件維護,並通過RecalcLayout方法計算。隱藏,複製Code
private GraphicsPath RecalcLayout(Rectangle rect, Point target) { GraphicsPath gp = new GraphicsPath();
兩個獨立的部件控制錨的形狀和位置:錨象限指示四個邊中的一個,錨偏移指示沿指定錨象限增加的距離。圖3顯示了這兩個元件與氣球整體之間的關係。 一個重要的設計考慮是讓它們獨立,因為如圖4所示,有12種錨點排列。在任何象限中,錨點的位置可以是前中心、中心或後中心。中心是最小和最大偏移量之間的精確位置。當錨點居中時,它的掃描角是90度,而所有其他位置的角度都是45度,垂直邊總是背向中心。 下面的程式碼片段計算錨象限的必要調整。象限的計算簡單,只需要使用矩陣和錨翻轉變數,這是簡單的解釋。這個編碼是基於一個旋轉的“頂級”氣球為了確定其他錨的位置,也就是說如果他需要錨的三個“頂級”錨位置,不會利用旋轉,然而,如果需要錨左右兩邊的氣球,一個90度或90度旋轉,分別將被使用。隱藏,收縮,複製Code
switch(anchorQuadrant) { case AnchorQuadrant.Top: break; case AnchorQuadrant.Bottom: matrix.Translate(balloonBounds.Width, balloonBounds.Height); matrix.Rotate(180); anchorFlipped = true; break; case AnchorQuadrant.Left: balloonBounds.Size = newSize(balloonBounds.Height, balloonBounds.Width); matrix.Translate(0, balloonBounds.Width); matrix.Rotate(-90); anchorFlipped = true; break; case AnchorQuadrant.Right: balloonBounds.Size = new Size(balloonBounds.Height, balloonBounds.Width); matrix.Translate(balloonBounds.Height, 0); matrix.Rotate(90); break; }
如前所述,當構建路徑時,所有的計算都假設錨在上象限。這樣做是為了使計算簡單和可預測。一旦路徑完成,它被調整使用矩陣變數旋轉氣球,使錨在正確的象限。然而,使用底部錨的象限的頂部提出了一個有趣的問題。當氣球旋轉180度或270度時,錨定偏移會在需要的中心的另一邊結束。圖5演示了這種情況。錨翻轉變數標記此條件,允許錨的偏移量重新計算,如下所示。從圖5可以看出,當錨被旋轉180度時,錨被拉到“右下角”。在錨點被放置到正確的位置之前,需要進行一個後續的移動,在這個例子中是“左下角”。“隱藏,複製Code
if(anchorFlipped) anchorOffset = (int)balloonBounds.Width-(offsetFromEdge*2)-anchorOffset;
不管偏移是前中心,中心還是後中心,錨總是有三個點。下面的程式碼計算這三個點。隱藏,收縮,複製Code
if(anchorOffset < balloonEdgeCenter) { anchorPoints[0] = new Point(anchorOffset+offsetFromEdge, (int)balloonBounds.Y+anchorMargin); anchorPoints[1] = new Point(anchorOffset+offsetFromEdge, (int)balloonBounds.Y); anchorPoints[2] = new Point(anchorOffset+anchorMargin+offsetFromEdge, (int)balloonBounds.Y+anchorMargin); } else if(anchorOffset > balloonEdgeCenter) { anchorPoints[0] = new Point(anchorOffset-anchorMargin+offsetFromEdge, (int)balloonBounds.Y+anchorMargin); anchorPoints[1] = new Point(anchorOffset+offsetFromEdge, (int)balloonBounds.Y); anchorPoints[2] = new Point(anchorOffset+offsetFromEdge, (int)balloonBounds.Y+anchorMargin); } else { anchorPoints[0] = new Point(anchorOffset-anchorMargin+offsetFromEdge, (int)balloonBounds.Y+anchorMargin); anchorPoints[1] = new Point(anchorOffset+offsetFromEdge, (int)balloonBounds.Y); anchorPoints[2] = new Point(anchorOffset+anchorMargin+offsetFromEdge, (int)balloonBounds.Y+anchorMargin); }
計算完成後,路徑最終可以構建如下所示。隱藏,複製Code
gp.AddArc(balloonBounds.Left, balloonBounds.Top+anchorMargin, cornerDiameter, cornerDiameter,180, 90); gp.AddLine(anchorPoints[0], anchorPoints[1]); gp.AddLine(anchorPoints[1], anchorPoints[2]); gp.AddArc(balloonBounds.Width-cornerDiameter, balloonBounds.Top+anchorMargin, cornerDiameter, cornerDiameter, -90, 90); gp.AddArc(balloonBounds.Width-cornerDiameter, balloonBounds.Bottom-cornerDiameter, cornerDiameter, cornerDiameter, 0, 90); gp.AddArc(balloonBounds.Left, balloonBounds.Bottom-cornerDiameter, cornerDiameter, cornerDiameter, 90, 90);
最後一個問題;調整路徑,使錨點位於正確的象限。隱藏,複製Code
gp.Transform(matrix);
制約該地區 GraphicsPathWindow類提供了對非標準視窗形狀的支援。這個類本身並不知道視窗的形狀;相反,在需要時呼叫虛擬PreparePath方法,如下所示。這裡的GetPath方法檢查路徑是否被快取,如果沒有,它要求派生類提供路徑。隱藏,複製Code
public GraphicsPath GetPath() { GraphicsPath gp = __graphicsPath; if(gp == null) gp = PreparePath(); SetPath(gp); return gp; }
這為所有派生類提供了根據需要定義路徑的能力。下面是BalloonWindow用來定義其路徑的程式碼。隱藏,複製Code
protected override GraphicsPath PreparePath() { return __layout.Path; }
視窗定義了一個區域,該區域指示作業系統僅在該區域內繪製。下面的程式碼約束該區域並確保視窗看起來像一個氣球。從GraphicsPath物件定義區域時,該區域被定義為路徑的內部區域。下面的程式碼包括了路徑邊界的調整。隱藏,複製Code
private Region RegionFromPath(GraphicsPath gp) { if(gp == null) throw(new ArgumentNullException("gp")); Region region = new Region(gp); float inflateBy = 1F+2F/(float)Width; Matrix matrix = new Matrix(); matrix.Scale(inflateBy, inflateBy); matrix.Translate(-1, -1); region.Transform(matrix); return region; }
突出一個影子 Windows 2000引入了分層Windows。層視窗允許作業系統將視窗的內容與背景進行字母混合。這方面的一個例子就是windows 2000和XP中氣球視窗投射的陰影。 BalloonWindow的設計目標就是支援同樣的陰影效果。幾個設計,標本口糧研究並最終最好的方法是實現內容背後的陰影在單獨的視窗中定位視窗如圖6所示。 類ShadowedWindow維護BalloonWindow繼承的陰影效果。當一個影子是第一次顯示,CreateShadowProjection建立一個投影物件。記住,ShadowedWindow不是影子本身。影子視窗本身實際上是封裝的投影物件由ShadowedWindow維護。隱藏,複製Code
private Projection CreateShadowProjection() { Projection shadow = new Projection(this); shadow.BackColor = Color.White; BindShadowToOwner(shadow, this); return shadow; }
投射的影子總是背後的內容視窗,具有相同的尺寸。因此,陰影需要抵消略這是可見的。隱藏,複製Code
public void ShowShadow() { GraphicsPathWindow shadow = __shadow; if(shadow == null) shadow = __shadow = CreateShadowProjection(); int shadowMargin = ShadowMargin; Point shadowLocation = new Point(Location.X+shadowMargin, Location.Y+shadowMargin); Size shadowSize = Size; shadow.Location = shadowLocation; shadow.Size = shadowSize; shadow.Show(); }
一個影子上建立一個螢幕點陣圖呈現梯度模式。隱藏,複製Code
Bitmap img = new Bitmap(Width, Height); GraphicsPath path = GetPath(); Graphics grx = Graphics.FromImage(img); float scaleFactor = 1F-((float)__owner.ShadowMargin*2/(float)Width); PathGradientBrush backStyle = new PathGradientBrush(path); backStyle.CenterPoint = new Point(0, 0); backStyle.CenterColor = __owner.ShadowColor; backStyle.FocusScales = new PointF(scaleFactor, scaleFactor); backStyle.SurroundColors = new Color[]{Color.Transparent}; Region region = new Region(path); region.Translate(-__owner.ShadowMargin, -__owner.ShadowMargin); grx.SetClip(region, CombineMode.Xor); grx.FillPath(backStyle, path);
SetBitmap方法初始化和更新層面板使用程式碼提供的魯伊Godinho Lopes解釋在他每畫素α融入c#檔案”。“隱藏,複製Code
SetBitmap(img);
結論 BalloonWindow是一個強大的庫生成一個簡單的UI元素。 類結構 BalloonWindow被設計成一個健壯的和任何應用程式的關鍵元件。圖7顯示了用於BalloonWindow公共物件模型。 構建HistoryFor每個構建的資訊,請參閱BalloonWindow圖書館為。net門戶。 版權 版權©2002 - 2003由彼得·傾斜層的開採 原始檔和二進位制檔案可能會重新分配以任何方式修改的提供他們不賣利潤沒有作者表達的書面同意,並提供此通知和作者的名字和所有版權宣告保持不變。 任何使用軟體的原始碼或二進位制形式,有或沒有修改,必須包括,在使用者文件(“關於“盒子和列印文件)和內部註釋程式碼,對終端使用者通知如下: ”彼得部分版權©2002 - 2003可選裡林” 電子郵件讓我知道你是使用它就好了。這不是多問考慮進這個的工作量。 這個軟體提供了“是”,沒有任何型別的保證,明示或默示。使用它在你自己的風險。作者不接受任何責任這種產品可能會導致資料損壞/損失。 本文轉載於:http://www.diyabc.com/frontweb/news5016.html