程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#完成義務欄告訴窗口

C#完成義務欄告訴窗口

編輯:C#入門知識

C#完成義務欄告訴窗口。本站提示廣大學習愛好者:(C#完成義務欄告訴窗口)文章只能為提供參考,不一定能成為您想要的結果。以下是C#完成義務欄告訴窗口正文


想必年夜部門網友都應用過QQ、MSN等聊天法式,它們的界面都相當華美,特別是當網友上線和新聞提醒時會有一個浮動的窗體從屏幕的右下方遲緩升起,既雅觀又人道化。本文重要講授用C#來完成義務欄告訴窗口。
簡介

QQ和MSN的義務欄告訴窗口很人道化,它可以在不喪失主窗體核心的條件下顯示一個具有皮膚Skin的告訴窗體,當它顯示一段時光後會主動消逝,所以用戶基本不消干涉它。

如許的告訴窗體和普通的具有題目欄、體系圖標和按鈕的窗體沒有太年夜的差別,窗體外面其實就是畫上去的一張位圖罷了,而窗體的浮動則會龐雜一點,我們會用到.Net框架的兩重緩沖區畫圖技巧(拜見作者編譯文章“Windows窗體的.Net框架畫圖技巧”)來包管挪動窗體時所顯示的內容膩滑且不閃耀,和應用P/Invoke平台挪用停止對Win32API

函數的挪用來完成不取得核心的窗體顯示和非題目欄窗體拖動。兩種位圖的皮膚運轉時的界面以下:

配景常識

告訴窗口就是將普通的窗體附加上一層皮膚,這裡所謂的皮膚就是一張位圖圖片,該位圖圖片經由過程窗體的OnPaintbackground事宜被繪制到窗體外面,在附加位圖之前須要調劑窗體的可視屬性,因為繪制操作是針關於窗體客戶區域的,所謂客戶區域就是指窗體題目欄下方和窗體邊框之內的一切區域,所以須要將窗體的邊框和外不雅屬性FormBorderStyle調劑為:None,如許所繪制的圖象就會填充全部窗體。

起首,我們會用到Region對象,Region對象可以准確的描寫出隨意率性外形的輪廓規模,經由過程一個位圖圖象創立Region對象後再將其傳遞給窗體的Region屬性便可以使窗體依照Region所界說的輪廓顯示出來。作為皮膚應用的位圖文件可以經由過程任何圖象編纂軟件諸如:Photeshop來創立和編纂,只是留意一點,須要將圖片的配景色彩成特定色彩以便法式繪制時將其消除,我們在這裡應用的配景色為粉白色。為了可以或許讓Region對象依照圖象中感興致的內容邊框來創立窗體,我們還須要應用GraphicsPath類將圖象輪廓依照必定途徑標注上去,稍後便依照該途徑創立Region對象。

然後經由過程窗體的畫圖事宜將位圖的內容顯示在窗體外面,我們沒有直接應用OnPaintbackground事宜而是重載了該辦法,如許做的利益就是一些低層的繪制操作還持續交由.Net框架運轉時來處置,我們只斟酌現實須要的繪制操作便可。在OnPaintbackground辦法中我們啟用了兩重緩沖區畫圖技巧,所謂該技巧就是指先在內存中的一塊畫布上把將要顯示的圖象顯示出來或停止處置,比及操作完成再將該畫布上所顯示的圖象放置到窗體外面,如許的機制可以異常有用的下降閃耀的湧現,使圖象顯示加倍膩滑。

告訴窗體從屏幕的右下方停止升起逗留一段時光後再漸漸回落,這裡須要用到前往屏幕區域的年夜小規模的.Net框架辦法Screen.GetWorkingArea(WorkAreaRectangle),經由過程必定算法盤算出告訴窗體顯示前的初始地位。

最初,我們將要顯示的文本依照必定格局和Rectangle對象所指定的區域規模繪制到窗體外面。告訴窗體的封閉操作是經由過程設定一個區域,當用戶用鼠標單擊時檢測單擊坐標能否在該區域內,若在區域內便可以履行隱蔽告訴窗體的代碼。

我們留意了,當QQ和MSN的告訴窗口顯示時其主窗體的核心沒有喪失,也就是說法式未將本身的核心轉移到顯示的告訴窗體上。經由測試,我們不管怎樣樣挪用.Net框架供給的窗體顯示例程比方:Form.Show都沒法包管主窗體的核心不喪失,在VC情況下我們可使用Win32API的 ShowWindows函數來完成龐雜的窗體顯示操作,然則.Net框架基本沒有供給相似的辦法,那末我們可否經由過程.Net框架挪用該API函數來顯示窗體呢?

幸虧.Net框架供給了P/Invoke平台挪用,應用平台挪用這類辦事,托管代碼便可以挪用在靜態鏈接庫中完成的非托管函數,並可以封送其參數,我們可以輕松的顯示但不取得核心的窗體。法式頂用到的Windows API和常量的界說都保留在WinUser.h頭文件中,其對應的靜態鏈接庫文件就是user32.dll,應用.Net框架供給的 DllImportAttribute類對導入的函數停止界說,然後便可以異常便利的在法式中挪用該函數了。

因為我們將告訴窗體的題目欄隱蔽了,所以對窗體拖動操作還須要我們本身著手停止處置。本文引見了若何加倍高效的停止拖動窗體操作,有些網友在關於非題目欄拖動窗體編程時傾向組合應用鼠標事宜來停止,如許做的實質沒有任何不當,然則頻仍的事宜呼應和處置反而使法式機能有所下降。我們將持續應用 Win32API的底層處置辦法來處理該成績,就是向窗體發送題目欄被單擊的新聞,模仿現實的拖動操作。

我們會經由過程2個計時器來完成窗體的顯示、逗留和隱蔽,經由過程設置速度變量可以轉變窗口顯示和隱蔽的速度。

[DllImportAttribute("user32.dll")] 
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); 
//發送新聞//winuser.h 中有函數原型界說 
[DllImportAttribute("user32.dll")] 
public static extern bool ReleaseCapture(); //釋放鼠標捕獲winuser.h 
[DllImportAttribute("user32.dll")] //winuser.h 
private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow); 

SendMessage向新聞輪回發送題目欄被按下的新聞來模仿窗體的拖動,ShowWindow用來將特定句柄的窗體顯示出來,留意第二個參數 nCmdShow,它表現窗體應當如何顯示出來,而我們須要窗體不取得核心顯示出來,SW_SHOWNOACTIVATE可以知足我們請求,持續在 WinUser.h文件中搜刮找到該常量對應的值為4,因而我們便可以如許挪用來顯示窗體了:

ShowWindow(this.Handle, 4); 
我們創立了一個自界說函數ShowForm用來封裝下面的ShowWindow用來是顯示窗體,同時傳遞了所用到的幾個Rectangle矩形區域對象,最初挪用ShowWindows函數將窗體顯示出來,代碼片斷以下:

public void ShowForm(string ftitletext, string fcontenttext, Rectangle fRegionofFormTitle, 
Rectangle fRegionofFormTitlebar, Rectangle fRegionofFormContent, Rectangle fRegionofCloseBtn) 
{ 
titleText = ftitletext; 
contentText = fcontenttext; 
WorkAreaRectangle = Screen.GetWorkingArea(WorkAreaRectangle); 
this.Top = WorkAreaRectangle.Height + this.Height; 
FormBorderStyle. = FormBorderStyle.None; 
WindowState = FormWindowState.Normal; 
this.SetBounds(WorkAreaRectangle.Width - this.Width, 
WorkAreaRectangle.Height - currentTop, this.Width, this.Height); 
CurrentState = 1; 
timer1.Enabled = true; 
TitleRectangle = fRegionofFormTitle; 
TitlebarRectangle = fRegionofFormTitlebar; 
ContentRectangle = fRegionofFormContent; 
CloseBtnRectangle = fRegionofCloseBtn; 
ShowWindow(this.Handle, 4); //#define SW_SHOWNOACTIVATE 
} 

CurrentState變量表現窗體的狀況是顯示中、逗留中照樣隱蔽中,兩個計時器依據窗體分歧狀況對窗體的地位停止更改,我們會應用SetBounds來履行該操作:

this.SetBounds(WorkAreaRectangle.Width - this.Width, WorkAreaRectangle.Height - currentTop, this.Width, this.Height);  
當窗體須要升起時將窗體的Top屬性值赓續削減,而窗體回落時將Top屬性值增長並跨越屏幕的高度窗體就消逝了,固然道理很簡略但仍需准確掌握。
SetBackgroundBitmap函數起首將窗體配景圖象保留到BackgroundBitmap變量中,然後依據該位圖圖象輪廓和通明色創立Region,BitmapToRegion就用於完成Bitmap到Region的轉換,法式再將這個Region付值給窗體的Region屬性以完成不規矩窗體的創立。

public void SetBackgroundBitmap(Image image, Color transparencyColor)  
{  
BackgroundBitmap = new Bitmap(image);  
Width = BackgroundBitmap.Width;  
Height = BackgroundBitmap.Height;  
Region = BitmapToRegion(BackgroundBitmap, transparencyColor);  
}  
public Region BitmapToRegion(Bitmap bitmap, Color transparencyColor)  
{  
if (bitmap == null)  
throw new ArgumentNullException("Bitmap", "Bitmap cannot be null!");  
int height = bitmap.Height;  
int width = bitmap.Width;  
GraphicsPath path = new GraphicsPath();  
for (int j = 0; j < height; j++)  
for (int i = 0; i < width; i++)  
{  
if (bitmap.GetPixel(i, j) == transparencyColor)  
continue;  
int x0 = i;  
while ((i < width) && (bitmap.GetPixel(i, j) != transparencyColor))  
i++;  
path.AddRectangle(new Rectangle(x0, j, i - x0, 1));  
}  
Region region = new Region(path);  
path.Dispose();  
return region;  
} 

告訴窗體配景和文字的繪制在重載的OnPaintBackground辦法中完成,並且應用了兩重緩沖區技巧來停止繪制操作,代碼以下:

protected override void OnPaintBackground(PaintEventArgs e) 
{ 
Graphics grfx = e.Graphics; 
grfx.PageUnit = GraphicsUnit.Pixel; 
Graphics offScreenGraphics; 
Bitmap offscreenBitmap; 
ffscreenBitmap = new Bitmap(BackgroundBitmap.Width, BackgroundBitmap.Height); 
ffScreenGraphics = Graphics.FromImage(offscreenBitmap); 
if (BackgroundBitmap != null) 
{ 
offScreenGraphics.DrawImage(BackgroundBitmap, 0, 0, 
BackgroundBitmap.Width, BackgroundBitmap.Height); 
} 
DrawText(offScreenGraphics); 
grfx.DrawImage(offscreenBitmap, 0, 0); 
} 

 上述代碼起首前往窗體繪制外面的Graphics並保留在變量grfx中,然後創立一個內存Graphics對象 offScreenGraphics和內存位圖對象offscreenBitmap,將內存位圖對象的援用付值給offScreenGraphics,如許一切對offScreenGraphics的繪制操作也都同時感化於offscreenBitmap,這時候就將須要繪制到告訴窗體外面的配景圖象 BackgroundBitmap繪制到內存的Graphics對象上,DrawText函數依據須要顯示文字的年夜小和規模挪用 Graphics.DrawString將文字顯示在窗體的特定區域。最初,挪用Graphics.DrawImage將內存中曾經繪制完成的圖象顯示到告訴窗體外面。

我們還須要捕捉窗體的鼠標操作,有三個操作在這裡停止,1、處置拖動窗體操作,2、處置告訴窗體的封閉操作,3、內容區域的單擊操作。三個操作都須要檢測鼠標確當前地位與每一個Rectangle區域的包括關系,只需單擊落在特定區域我們就停止響應的處置,代碼以下:

private void TaskbarForm_MouseDown(object sender, MouseEventArgs e) 
{ 
if (e.Button == MouseButtons.Left) 
{ 
if (TitlebarRectangle.Contains(e.Location)) //單擊題目欄時拖動 
{ 
ReleaseCapture(); //釋放鼠標捕獲 
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0); //發送左鍵點擊的 
//新聞至該窗體(題目欄) 
} 
if (CloseBtnRectangle.Contains(e.Location)) //單擊Close按鈕封閉 
{ 
this.Hide(); 
currentTop = 1; 
} 
if (ContentRectangle.Contains(e.Location )) //單擊內容區域 
{ 
System.Diagnostics.Process.Start("http://www.Rithia.com"); } 
} 
} 

結論

該法式可以很好的停止告訴窗體的顯示、逗留和隱蔽操作,而且具有簡略的換膚機制,在應用了兩重緩沖區畫圖技巧後,可以包管窗體的繪制膩滑且沒有閃耀。

若何應用C#完成義務欄告訴窗口,年夜家經由過程本文都有了年夜概的懂得了吧,願望可以或許有所收成吧1

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved