C# GDI+編程(四)

來源:互聯網
上載者:User
截屏
Grahpics類裡的CopyFromScreen函數,可以把螢幕拷貝到Graphics對象裡。如果Graphics對象是從視窗Form裡建立的,那麼螢幕就直接
顯示在視窗裡。看例子:給視窗添加一個按鈕,然後給這個按鈕添加單擊事件處理函數。
函數裡的代碼如下:
private void button1_Click(object sender, EventArgs e)
{
this.CreateGraphics().CopyFromScreen(50,50, 0, 0, this.Size,CopyPixelOperation.SourceCopy);
}
第一個參數和第二個參數,指明是從螢幕的哪裡開始複製,而後面的0,0,就是把螢幕複製到視窗裡了,從視窗哪裡開始顯示。
this.Size是要複製的大小(寬高)。

是VC++裡的。這裡只不過換了種說法而已。最終的結果還是一樣的。

之前的Graphics對象建立,都是通過視窗的, 這次我們通過圖片來建立Graphics對象,這樣我們就可以在圖片上進行繪製了。
而圖片對象的建立,並不是只有負載檔案這一個方式。我們可以建立一個“空”位元影像(通過建構函式),這種位元影像裡面沒有具體的資料,或者說裡面的預設資料,沒有用而已,我們只是需要這麼個容器。在裡面繪圖,添加資料進去。


例子:截屏並把圖片儲存為檔案
private void button1_Click(object sender, EventArgs e)
{
//建立Bitmap圖片,800寬,600高,這麼個大小的容器。
Bitmap bmp = new Bitmap(800, 600);
//從圖片裡建立Grahpics對象
Graphics gr = Graphics.FromImage(bmp);
//拷貝螢幕到Bitmap
gr.CopyFromScreen(0, 0, 0, 0, new Size(800, 600), CopyPixelOperation.SourceCopy);
//儲存為圖片檔案
bmp.Save("d:\\screen.jpg");
}
怎麼樣,夠簡單的吧,四行代碼就完成了螢幕,並儲存為檔案,VC++可是要很多行代碼。另Bitmap是從Image類裡派生出來的。

雙緩衝一次性繪圖
直接看一個沒有使用雙緩衝的例子吧,滑鼠在視窗內移動的時候,左上方的矩形就顯示滑鼠當前的位置
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseMove += formMouseMove;
}
private void formMouseMove(object sender, MouseEventArgs e)
{
Graphics gr = this.CreateGraphics();
Rectangle rect = new Rectangle(0, 0, 100, 35);
//填充矩形
LinearGradientBrush brush =
new LinearGradientBrush(rect, Color.FromArgb(44, 55, 66), Color.FromArgb(123, 150, 189),
LinearGradientMode.Horizontal);
gr.FillRectangle(brush, rect);
//畫矩形
Pen pen = new Pen(Color.Green, 2);
gr.DrawRectangle(pen, rect);
//顯示文本
gr.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
String str = String.Format("滑鼠位置:\n{0},{1}", e.X, e.Y);
gr.DrawString(str, new Font("黑體", 11),Brushes.White, rect);
}
}
可以看到,當滑鼠移動的時候,左上方的矩形明顯閃爍了,這是因為進行了三次繪製,填充矩形,畫矩形,顯示文本。才導致的。
當繪製的次數越多,這個閃爍就越明顯。
而這三次繪製最終只要得到一個結果,也就是得到一張圖片,那麼我們就可以使用雙緩衝來完成了,先把要繪製的圖形繪製到Bitmap裡面。然後再把Bitmap繪製到視窗就行了。
看例子:
private void formMouseMove(object sender, MouseEventArgs e)
{
Graphics graphics = this.CreateGraphics();
//從Bitmap裡建立Graphics對象
Bitmap bmp=new Bitmap(100,35);
Graphics gr = Graphics.FromImage(bmp);
Rectangle rect = new Rectangle(0, 0, 100, 35);
//填充矩形
LinearGradientBrush brush =
new LinearGradientBrush(rect, Color.FromArgb(44, 55, 66), Color.FromArgb(123, 150, 189),
LinearGradientMode.Horizontal);
gr.FillRectangle(brush, rect);
//畫矩形
Pen pen = new Pen(Color.Green, 2);
gr.DrawRectangle(pen, rect);
//顯示文本
gr.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
String str = String.Format("滑鼠位置:\n{0},{1}", e.X, e.Y);
gr.DrawString(str, new Font("黑體", 11),Brushes.White, rect);

//一次性繪製
graphics.DrawImage(bmp, 0, 0);
}

擷取視窗(控制項)的Bitmap
DrawToBitmap函數,可以把視窗或控制項的外觀繪製到Bitmap裡。它屬於Control類,而視窗類別和控制項類都是從Control類派生出來的。
看例子:(一個按鈕單擊事件處理函數的代碼)
private void button1_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(Width, Height);
this.DrawToBitmap(bmp, new Rectangle(0, 0, Width, Height));
bmp.Save("d:\\form.jpg");
}
DrawToBitmap的第二個參數,是視窗顯示在Bitmap裡的地區。這個是不能縮小或放大圖片的,視窗的大小和Bitmap的大小是一致的,
如果填10,10,50,50那就是視窗的0,0,50,50顯示在位元影像的10,10,50,50矩形地區內,視窗起始位置是不是能指定的,只能從位置0,0開始。

擷取一個像素點的值
Bitmap類裡GetPixel函數可以擷取一個像素點的Color值,如果要擷取視窗某一個像素點的顏色值,可以先調用DrawToBitmap函數,把
視窗儲存成Bitmap。然後再擷取。另:還有對應的函數SetPixel設定一個像素的顏色值。

擷取Png圖片顯示地區,建立不規則視窗。
擷取Png圖片地區可以用GetPixel函數,擷取圖片裡每一個像素點的顏色值,如果Alpha值為0的話,那就是透明的,否則把這個點加入地區。那麼要如何擷取一個Color對象的Alpah值呢,調用ToArgb成員函數,這個是32位整數,剛好可以儲存4個8位位元組的數值:A,R,G,B。
看下樣本吧,把Alpha值提取出來
{
Color cor1 = Color.FromArgb(123,225,229,230);
//擷取Color的argb值
int argb = cor2.ToArgb();
//轉換成字元數組
byte[] bargb = BitConverter.GetBytes(argb);
//bargb[3]儲存的是Alpha值
String str = String.Format("{0},{1},{2},{3}", bargb[0], bargb[1], bargb[2], bargb[3]);
MessageBox.Show(str);
}
一個完整的樣本,擷取PNG顯示地區

範例程式碼:

public Form1()
{
InitializeComponent();
//儲存PNG非透明部分的路徑
GraphicsPath path = new GraphicsPath();
//載入PNG圖片
Bitmap bmp = new Bitmap("d:\\Image\\win.png");
//判斷每個像素的顏色值,擷取圖片的顯示地區
for (int y = 0; y < bmp.Height; y++)
for (int x = 0; x < bmp.Width; x++)
{
Color cor = bmp.GetPixel(x, y);
int argb = cor.ToArgb();
byte[] bargb = BitConverter.GetBytes(argb);
//像素顏色值不是透明的
if (bargb[3] != 0)
{
//把這個像素點地區添加到路徑裡去
path.AddRectangle(new Rectangle(x, y, 1, 1));
}
}
//設定視窗顯示地區,通過路徑建立地區
this.Region = new Region(path);
}

但是這個方法有點不可靠,如果PNG圖片裡有些像素點的顏色值是半透明的,這樣就得不到想要的外觀結果。雖然看著PNG圖片裡有些地方好像是透明的。
解決方案就是自己來做PNG圖片,按你自己的規則來。不要從網上找。

設定了不規則視窗,就可以把那張PNG圖片繪製到視窗裡去了,但由於半透明的問題,得先用透明畫刷填充視窗,然後再繪製。

不過還有一個問題,非客戶區視窗繪製,像我們之前的繪製,都是在視窗客戶區裡繪製的。

如果要繪製的圖片和視窗對應起來的話,得從非用戶端區域開始繪製。這個要怎麼做到呢。下一章再說吧。


更多C# GDI+編程(四)相關文章請關注topic.alibabacloud.com!

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.