国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

利用C#實(shí)現(xiàn)標(biāo)注式消息提示窗口

2024-07-21 02:28:33
字體:
供稿:網(wǎng)友

  近一段時(shí)間由于項(xiàng)目需要一直專注于ui方面的編程,為了更加友好的將提示信息呈現(xiàn)給用戶,我們必須對(duì)標(biāo)準(zhǔn)的windows消息提示窗口進(jìn)行處理。我們大家在windows xp下使用u盤、閃存等移動(dòng)存儲(chǔ)設(shè)備,當(dāng)插上或拔下這些設(shè)備時(shí)任務(wù)欄區(qū)域都會(huì)顯示一個(gè)淡黃色背景,且具有標(biāo)注樣式的提示窗口彈出來,這樣的提示即友善又美觀,那么這到底是怎么實(shí)現(xiàn)的呢?其實(shí)道理并不復(fù)雜,該標(biāo)注式提示窗口本身就是一個(gè)不規(guī)則窗體,當(dāng)顯示時(shí)它會(huì)將標(biāo)注窗口的箭頭指向不同控件。如下圖:


一般情況下的p標(biāo)注式提示窗口

屏幕邊緣的標(biāo)注式提示窗口


  一、技術(shù)要點(diǎn)

  就像本文開頭所說的"標(biāo)注式消息提示窗口"其實(shí)就是一個(gè)具有不規(guī)則外形的窗體,但卻具備了更加復(fù)雜的屬性和行為。標(biāo)注的箭頭會(huì)根據(jù)不同控件指向不同的位置,當(dāng)需要標(biāo)注的控件過于接近屏幕的邊緣時(shí),標(biāo)注窗口還會(huì)自動(dòng)調(diào)整顯示位置以及箭頭的長短和大小。

  我們?yōu)樾聞?chuàng)建的窗體取名為infowindow。在類的頭部定義intarc和intarrowheight兩個(gè)私有變量,可以適當(dāng)調(diào)整它們的值來微調(diào)提示窗口的位置和箭頭的大小與位置。

  提示窗口的箭頭位置無非具有左上、右上、左下和右下四個(gè)可能性,我們?yōu)榇硕x了枚舉類型的變量arrowlocation,根據(jù)提示窗口位于屏幕的不同位置,getarrowlocation可以計(jì)算提示窗口的位置并且返回適當(dāng)?shù)腶rrowlocation,定義如下:

……
public enum arrowlocation
{
 topleft,
 topright,
 bottomleft,
 bottomright
}

  setinfowindowregion函數(shù)非常重要,它在form.load事件即裝載和顯示提示窗體時(shí)被調(diào)用,當(dāng)計(jì)算出新的提示窗口的位置和箭頭顯示位置后,調(diào)用setbounds將更新后的位置和大小應(yīng)用到提示窗口,gpath是graphicspath類型的私有變量,它表示標(biāo)注式窗口的不規(guī)則圖形路徑,該圖行路徑也是根據(jù)提示窗口的位置和箭頭顯示的位置來創(chuàng)建,gpath.addarc方法用來繪制提示窗口四個(gè)邊角的弧度部分,和addline方法一起描繪出提示窗口包括箭頭的輪廓,一切就緒后我們就用這個(gè)gpath對(duì)象傳遞給region對(duì)象,當(dāng)將這個(gè)region對(duì)象賦給form窗體的region屬性后,窗體就具備了標(biāo)注式提示窗口樣式的不規(guī)則外形了,部分代碼如下:

private void setinfowindowregion()
{
 if (!this.ishandlecreated)
  return;
 system.drawing.size windowsize = this.size;
 point[] arrowpoints = new point[3];
 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, recty2 - arcradius, arcdia, arcdia, 90, 90);
  gpath.addline(topleftpoint.x, recty2, topleftpoint.x, recty1);
  gpath.addarc(topleftpoint.x, topleftpoint.y, arcdia, arcdia, 180, 90);
  gpath.addline(rectx1, topleftpoint.y, arrowpoints[0].x, topleftpoint.y);
  gpath.addlines(arrowpoints);
  gpath.addline(arrowpoints[2].x, topleftpoint.y, rectx2, topleftpoint.y);
  gpath.addarc(rectx2 - arcradius, topleftpoint.y, arcdia, arcdia, 270, 90);
  gpath.addline(bottomrightpoint.x, recty1, bottomrightpoint.x, recty2);
  gpath.addarc(rectx2 - arcradius, recty2 - arcradius, arcdia, arcdia, 0, 90);
  gpath.addline(rectx2, bottomrightpoint.y, rectx1, bottomrightpoint.y);
 }
 else
 {
  gpath.addline(rectx1, topleftpoint.y, rectx2, topleftpoint.y);
  gpath.addarc(rectx2 - arcradius, topleftpoint.y, arcdia, arcdia, 270, 90);
  gpath.addline(bottomrightpoint.x, recty1, bottomrightpoint.x, recty2);
  gpath.addarc(rectx2 - arcradius, recty2 - arcradius, arcdia, arcdia, 0, 90);
  gpath.addline(rectx2, bottomrightpoint.y, arrowpoints[0].x, bottomrightpoint.y);
  gpath.addlines(arrowpoints);
  gpath.addline(arrowpoints[2].x, bottomrightpoint.y, rectx1, bottomrightpoint.y);
  gpath.addarc(topleftpoint.x, recty2 - arcradius, arcdia, arcdia, 90, 90);
  gpath.addline(topleftpoint.x, recty2, topleftpoint.x, recty1);
  gpath.addarc(topleftpoint.x, topleftpoint.y, arcdia, arcdia, 180, 90);
 }
 gpath.closefigure();
 this.region = new region(this.gpath);
}

  showinfowindow函數(shù)用來將提示窗口顯示出來,該函數(shù)需要將提示窗口附著的控件和需要顯示的文本傳遞過來。然后,anchorpointfromcontrol根據(jù)控件的位置返回提示窗口的箭頭應(yīng)該顯示的坐標(biāo),代碼如下:

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 / 2, controlsize.height / 2);
}

  pointtoscreen表明將工作區(qū)點(diǎn)的位置映射成屏幕坐標(biāo)統(tǒng)一進(jìn)行計(jì)算。上述代碼最后以行說明提示窗口的箭頭顯示在附著控件的中點(diǎn)。

  將提示窗口的背景顏色設(shè)置成info,外觀如下圖:


  我們發(fā)現(xiàn)這樣的外觀有點(diǎn)別扭,沒錯(cuò)!因?yàn)樘崾敬翱谌鄙俸谏吙颍∷裕€需要在窗體的onpaint事件中添加代碼,如下:

protected override void onpaint(painteventargs e)
{
 pen p = new pen(color.black , 2);
 e.graphics.drawpath(p, gpath);
 base.onpaint(e);
}

  二、程序?qū)崿F(xiàn)

  啟動(dòng)visual studio 2005,新建visual c#的windows 應(yīng)用程序項(xiàng)目,并取名為showinfowindow,添加4個(gè)button組件、1個(gè)label組件、1個(gè)textbox組件和3個(gè)panel組件,其中3個(gè)button用來顯示標(biāo)注式消息提示窗口并分別附著在三個(gè)組件之上,代碼如下:

……
private infowindow iw;
……
private void button1_click(object sender, eventargs e)
{
 iw = new infowindow();
 iw.showinfowindow(label1, "關(guān)于標(biāo)簽組件的提示說明。");
}
private void button3_click(object sender, eventargs e)
{
 iw = new infowindow();
 iw.showinfowindow(button2, "關(guān)于按鈕組件的提示說明。");
}

private void button4_click(object sender, eventargs e)
{
 iw = new infowindow();
 iw.showinfowindow(textbox1, "關(guān)于文本框組件的提示說明。");
}

  然后,我們?cè)陧?xiàng)目中添加新windows窗體,取名為infowindow,將infowindow的backcolor設(shè)為info,formborderstyle設(shè)為none,將showicon和showintaskbar都設(shè)為false,在窗體上放置1個(gè)label組件和1個(gè)button組件,分別用來顯示消息內(nèi)容和關(guān)閉提示窗口的操作。具體實(shí)現(xiàn)請(qǐng)參見文章附帶的源碼,這里不再詳述。

  三、總結(jié)

  本文演示了標(biāo)注式消息提示窗口的創(chuàng)建和顯示,利用graphicspath對(duì)象、region對(duì)象以及屏幕坐標(biāo)映射等方法有效的實(shí)現(xiàn)了提示窗口的外觀和樣式,提示窗口可以自動(dòng)附著在相應(yīng)控件之上,并且根據(jù)附著控件在屏幕上的位置自動(dòng)調(diào)整提示窗口箭頭的位置和大小。演示程序在windows xp sp2以及.net 框架 2.0環(huán)境下運(yùn)行通過。,歡迎訪問網(wǎng)頁設(shè)計(jì)愛好者web開發(fā)。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 阳江市| 赣州市| 龙州县| 广安市| 新晃| 英超| 长武县| 绥滨县| 彩票| 安岳县| 游戏| 广德县| 兴安县| 固原市| 岢岚县| 沅江市| 舞阳县| 蛟河市| 巧家县| 台山市| 武川县| 镇雄县| 秀山| 镇安县| 滨州市| 宕昌县| 金华市| 广水市| 清水县| 东海县| 五大连池市| 隆回县| 汉寿县| 蛟河市| 寻甸| 秭归县| 定兴县| 苍梧县| 嘉禾县| 正安县| 正安县|