近一段時間由於項目需要一直專注於UI方面的編程
為了更加友好的將提示信息呈現給用戶
我們必須對標准的Windows消息提示窗口進行處理
我們大家在Windows XP下使用U盤
閃存等移動存儲設備
當插上或拔下這些設備時任務欄區域都會顯示一個淡黃色背景
且具有標注樣式的提示窗口彈出來
這樣的提示即友善又美觀
那麼這到底是怎麼實現的呢?其實道理並不復雜
該標注式提示窗口本身就是一個不規則窗體
當顯示時它會將標注窗口的箭頭指向不同控件
如下圖
一般情況下的標注式提示窗口
屏幕邊緣的標注式提示窗口
一
技術要點
就像本文開頭所說的
標注式消息提示窗口
其實就是一個具有不規則外形的窗體
但卻具備了更加復雜的屬性和行為
標注的箭頭會根據不同控件指向不同的位置
當需要標注的控件過於接近屏幕的邊緣時
標注窗口還會自動調整顯示位置以及箭頭的長短和大小
我們為新創建的窗體取名為InfoWindow
在類的頭部定義intArc和intArrowHeight兩個私有變量
可以適當調整它們的值來微調提示窗口的位置和箭頭的大小與位置
提示窗口的箭頭位置無非具有左上
右上
左下和右下四個可能性
我們為此定義了枚舉類型的變量ArrowLocation
根據提示窗口位於屏幕的不同位置
GetArrowLocation可以計算提示窗口的位置並且返回適當的ArrowLocation
定義如下
……
public enum ArrowLocation
{
TopLeft
TopRight
BottomLeft
BottomRight
}
SetInfoWindowRegion函數非常重要
它在Form
Load事件即裝載和顯示提示窗體時被調用
當計算出新的提示窗口的位置和箭頭顯示位置後
調用SetBounds將更新後的位置和大小應用到提示窗口
gPath是GraphicsPath類型的私有變量
它表示標注式窗口的不規則圖形路徑
該圖行路徑也是根據提示窗口的位置和箭頭顯示的位置來創建
gPath
AddArc方法用來繪制提示窗口四個邊角的弧度部分
和AddLine方法一起描繪出提示窗口包括箭頭的輪廓
一切就緒後我們就用這個gPath對象傳遞給Region對象
當將這個Region對象賦給Form窗體的Region屬性後
窗體就具備了標注式提示窗口樣式的不規則外形了
部分代碼如下
private void SetInfoWindowRegion()
{
if (!this
IsHandleCreated)
return;
System
Drawing
Size windowSize = this
Size;
Point[] ArrowPoints = new Point[
];
Point topLeftPoint = Point
Empty;
Point bottomRightPoint = (Point)windowSize;
switch (this
GetArrowLocation)
{
case ArrowLocation
TopLeft:
……
case ArrowLocation
TopRight:
……
case ArrowLocation
BottomLeft:
……
case ArrowLocation
BottomRight:
……
}
……
……
if ((this
GetArrowLocation == ArrowLocation
TopLeft) ||
(this
GetArrowLocation == ArrowLocation
TopRight))
{
gPath
AddArc(topLeftPoint
X
rectY
arcRadius
arcDia
arcDia
);
gPath
AddLine(topLeftPoint
X
rectY
topLeftPoint
X
rectY
);
gPath
AddArc(topLeftPoint
X
topLeftPoint
Y
arcDia
arcDia
);
gPath
AddLine(rectX
topLeftPoint
Y
ArrowPoints[
]
X
topLeftPoint
Y);
gPath
AddLines(ArrowPoints);
gPath
AddLine(ArrowPoints[
]
X
topLeftPoint
Y
rectX
topLeftPoint
Y);
gPath
AddArc(rectX
arcRadius
topLeftPoint
Y
arcDia
arcDia
);
gPath
AddLine(bottomRightPoint
X
rectY
bottomRightPoint
X
rectY
);
gPath
AddArc(rectX
arcRadius
rectY
arcRadius
arcDia
arcDia
);
gPath
AddLine(rectX
bottomRightPoint
Y
rectX
bottomRightPoint
Y);
}
else
{
gPath
AddLine(rectX
topLeftPoint
Y
rectX
topLeftPoint
Y);
gPath
AddArc(rectX
arcRadius
topLeftPoint
Y
arcDia
arcDia
);
gPath
AddLine(bottomRightPoint
X
rectY
bottomRightPoint
X
rectY
);
gPath
AddArc(rectX
arcRadius
rectY
arcRadius
arcDia
arcDia
);
gPath
AddLine(rectX
bottomRightPoint
Y
ArrowPoints[
]
X
bottomRightPoint
Y);
gPath
AddLines(ArrowPoints);
gPath
AddLine(ArrowPoints[
]
X
bottomRightPoint
Y
rectX
bottomRightPoint
Y);
gPath
AddArc(topLeftPoint
X
rectY
arcRadius
arcDia
arcDia
);
gPath
AddLine(topLeftPoint
X
rectY
topLeftPoint
X
rectY
);
gPath
AddArc(topLeftPoint
X
topLeftPoint
Y
arcDia
arcDia
);
}
gPath
CloseFigure();
this
Region = new Region(this
gPath);
}
ShowInfoWindow函數用來將提示窗口顯示出來該函數需要將提示窗口附著的控件和需要顯示的文本傳遞過來然後AnchorPointFromControl根據控件的位置返回提示窗口的箭頭應該顯示的坐標代碼如下
public static Point AnchorPointFromControl(Control anchorControl)
{
if (anchorControl == null)
throw new ArgumentException();
Point controlLocation = anchorControl
Location;
System
Drawing
Size controlSize = anchorControl
Size;
if (anchorControl
Parent != null)
controlLocation = anchorControl
Parent
PointToScreen(controlLocation);
return controlLocation + new Size(controlSize
Width /
controlSize
Height /
);
}
PointToScreen表明將工作區點的位置映射成屏幕坐標統一進行計算
上述代碼最後以行說明提示窗口的箭頭顯示在附著控件的中點
將提示窗口的背景顏色設置成Info
外觀如下圖
我們發現這樣的外觀有點別扭
沒錯!因為提示窗口缺少黑色邊框!所以
還需要在窗體的OnPaint事件中添加代碼
如下
protected override void OnPaint(PaintEventArgs e)
{
Pen p = new Pen(Color
Black
);
e
Graphics
DrawPath(p
gPath);
base
OnPaint(e);
}
二程序實現
啟動Visual Studio 新建Visual C#的Windows 應用程序項目並取名為ShowInfoWindow添加個Button組件個Label組件個textBox組件和個Panel組件其中個Button用來顯示標注式消息提示窗口並分別附著在三個組件之上代碼如下
……
private InfoWindow iw;
……
private void button_Click(object sender EventArgs e)
{
iw = new InfoWindow();
iwShowInfoWindow(label 關於標簽組件的提示說明);
}
private void button_Click(object sender EventArgs e)
{
iw = new InfoWindow();
iwShowInfoWindow(button 關於按鈕組件的提示說明);
}
private void button_Click(object sender EventArgs e)
{
iw = new InfoWindow();
iwShowInfoWindow(textBox 關於文本框組件的提示說明);
}
然後我們在項目中添加新Windows窗體取名為InfoWindow將InfoWindow的BackColor設為InfoFormBorderStyle設為None將ShowIcon和ShowInTaskbar都設為False在窗體上放置個Label組件和個Button組件分別用來顯示消息內容和關閉提示窗口的操作具體實現請參見文章附帶的源碼這裡不再詳述
三總結
本文演示了標注式消息提示窗口的創建和顯示利用GraphicsPath對象Region對象以及屏幕坐標映射等方法有效的實現了提示窗口的外觀和樣式提示窗口可以自動附著在相應控件之上並且根據附著控件在屏幕上的位置自動調整提示窗口箭頭的位置和大小演示程序在Windows XP SP以 框架 環境下運行通過
From:http://tw.wingwit.com/Article/program/net/201311/12745.html