C#制作不规则窗口 ( 24bit Color 以上适用 )
時間: 2004/3/17
作者: Robert
參考: http://www.codeproject.com/csharp/bmprgnform.asp?target=region
電郵: [email protected]
關鍵字: Region Gif 不規則 窗口 視窗 GraphicsPath 按鈕 圖片 Form Button
目的: 幫助受 C# 不規則窗口困擾的人
介紹
這篇文章說明怎麼製作圖片按鈕和窗體. Region 技術不但能做不規則窗口, 也能做不規則控件外觀, 比
如說不規則按鈕.
程序介紹
說明: 我修改程序介紹中的注釋, 不修改程序列表的說明. 畢竟 E 文我們看起來沒有中文舒服.
1. 主函數說明
下面的程序用倆個主函數產生 位圖區域 (bitmap regionss ), 源代碼放在 BitmapRegion.cs中, 你可
以直接導入這個類別, 使用裡面的函數.
// Create and apply the given bitmap region on the supplied control
// 產生支持位圖區域 ( bitmap region ) 控件
public static void CreateControlRegion(Control control, Bitmap bitmap)
{
// 如果控件或者位圖不存在, 直接返回.
if(control == null || bitmap == null)
return;
// 根據位圖大小設置控件尺寸
control.Width = bitmap.Width;
control.Height = bitmap.Height;
// 處理 窗體 ( Form ) 類別
if(control is System.Windows.Forms.Form)
{
// 強制轉換 control object 到 Form object
Form form = (Form)control;
// 由於我們的Form邊界類型 ( Form.FormBorderStyle ) 不是 None,
// 所以我們的Form尺寸比位圖大一點
form.Width += 15;
form.Height += 35;
// 設定 Form 邊界類型是 None
form.FormBorderStyle = FormBorderStyle.None;
// 設定 Form 背景圖片
form.BackgroundImage = bitmap;
// 計算圖片中不透明部分的邊界 (建議用 Gif 圖片 )
GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
// 建立區域 ( Region )
form.Region = new Region(graphicsPath);
}
// 處理按鈕 ( button 類別 )
else if(control is System.Windows.Forms.Button)
{
// control object 轉成 Button object 類別
Button button = (Button)control;
// 清除 Button 上面的文字
button.Text = "";
// 更改鼠標樣式是手狀鼠標
button.Cursor = Cursors.Hand;
// 設定背景圖樣
button.BackgroundImage = bitmap;
//計算圖片中不透明部分的邊界 (建議用 Gif 圖片 )
GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
// 建立區域 ( Region )
button.Region = new Region(graphicsPath);
}
// 這裡你可以模仿 Form 或者 Button 建立心的類別出歷程序, 比如Panel
}
// 計算圖片不透明區域 返回 GraphicsPath
private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)
{
// 建立GraphicsPath, 給我們的位圖路徑計算使用
GraphicsPath graphicsPath = new GraphicsPath();
// 使用左上角 (0,0) 點作為透明色
// 如果這裡是紅色, 那麼我們計算是圖片中不包含紅色區域路徑
Color colorTransparent = bitmap.GetPixel(0, 0);
// 存儲第一個不透明點, 這個值決定我們開始檢查不透明區域.
int colOpaquePixel = 0;
// 檢查所有的行 ( Y axis )
for(int row = 0; row < bitmap.Height; row ++)
{
// 重置 colOpaquePixel 值
colOpaquePixel = 0;
// 檢查所有的列 ( X axis )
for(int col = 0; col < bitmap.Width; col ++)
{
// 如果是不透明點, 標記之後尋這個點之後的位置
if(bitmap.GetPixel(col, row) != colorTransparent)
{
// 找到不透明點, 標記這個位置
colOpaquePixel = col;
// 建立新變量保存當前點位置
int colNext = col;
// 從找到的不透明點開始繼續搜索不透明點,
//一直到找到透明點 或者 找到圖片寬度搜索完畢
for(colNext=colOpaquePixel; colNext
1<bitmap.width; "back.bmp");="" "bob.bmp");="" #="" (="" (i.e.="" )="" +="" -="" .="" 1));="" :="" <summary="" a="" allow="" alternate="" as="" be="" because="" bitmap="" bitmap(typeof(form1),="" bitmapregion.createcontrolregion(button1,="" bitmapregion.createcontrolregion(this,="" bitmapregion.cs="" bitmapregiontest="" bmpbob="new" bmpbob);="" bmpbobsay);="" bmpfrmback="new" bmpfrmback);="" break;="" button1_mouseenter(object="" button1_mouseleave(object="" calculate="" can="" causes="" change="" check="" class="" click="" clicked="" col="colNext;" colnext="" colnext++)="" colopaquepixel,="" commenting="" current="" deny="" do="" down.="" dragging="" due="" during="" e)="" e.x="" e.y="" e.y);="" else="" event="" events="" every="" first="" flag="" flicking="" for="" form="" form's="" form)="" form,="" form.formborderstyle是none,="" form1="" form1()="" form1_mousemove(object="" graphicspath.addrectangle(new="" graphicspath;="" has="" here="" i="" if="" if(bitmap.getpixel(colnext,="" if(e.button="MouseButtons.Left)" if(isfirst="true)" if(toblock="false)" in="" initializecomponent();="" is="" isfirst="true;" it="" left="" location="" location.="" mean="" mouse="" mouseleave和mouseenter="" move="" namespace="" new="" next="" not="" occur="" occurred="" of="" on="" or="" other="" out="" point="" point(e.x,="" point(this.location.x="" position="" previous="" prevleftclick="new" prevleftclick.x,="" prevleftclick.y);="" private="" processing="" public="" rectangle(colopaquepixel,="" released="" reset="" return="" row)="colorTransparent)" row,="" see="" sender,="" serious="" so="" store="" subsequent="" such="" system.drawing.drawing2d;="" system.drawing;="" system.eventargs="" system.windows.forms.form="" system.windows.forms.mouseeventargs="" system.windows.forms;="" system;="" that="" the="" this="" this.location="new" this.location.y="" time,="" to="" toblock="!toBlock;" treated="" try="" u="" until="" use="" using="" void="" we="" what="" when="" will="" with="" you="" {="" }="" 下面代碼給你答案,="" 下面這倆行代碼能產生不規則圖形.="" 代碼很簡單,="" 你不必改變="" 做中文的部分就是不規則窗體="" 只需要在按鈕的="" 和產生不規則窗體一樣產生不規則按鈕="" 因為不規則窗口沒有標題欄,="" 如果你想在鼠標盡入="" 完成程序列表="" 導入按鈕背景圖片="" 導入窗體背景圖片="" 導入背景圖片="" 怎麼移動呢?="" 我="" 我就不做中文解釋了="" 找到之後不用搜索不透明點="" 把不透明區域加入我們的graphicspath="" 產生不規則按鈕="" 產生不規則窗體="" 移動不規則窗口="" 程序自己幫你做這件事="" 裡面寫上下面的代碼就可以了.="" 讓你的床體透明吧="" 返回計算出來的不透明圖片路徑="" 離開按鈕的時候顯示不同不規則按鈕,="">
2/// Summary description for BitmapRegion.
3///
4public class BitmapRegion
5{
6public BitmapRegion()
7{}
8
9# /// <summary>
10/// Create and apply the region on the supplied control
11/// </summary>
12/// <param name="control"/>The Control object to apply the region to
13/// <param name="bitmap"/>The Bitmap object to create the region
14
15# from
16public static void CreateControlRegion(Control control, Bitmap bitmap)
17{
18// Return if control and bitmap are null
19if(control == null || bitmap == null)
20return;
21
22// Set our control's size to be the same as the bitmap
23control.Width = bitmap.Width;
24control.Height = bitmap.Height;
25
26# // Check if we are dealing with Form here
27if(control is System.Windows.Forms.Form)
28{
29// Cast to a Form object
30Form form = (Form)control;
31
32# // Set our form's size to be a little larger that the
33
34# bitmap just
35// in case the form's border style is not set to none in
36
37# the first place
38form.Width += 15;
39form.Height += 35;
40
41# // No border
42form.FormBorderStyle = FormBorderStyle.None;
43
44# // Set bitmap as the background image
45form.BackgroundImage = bitmap;
46
47# // Calculate the graphics path based on the bitmap supplied
48GraphicsPath graphicsPath =
49
50# CalculateControlGraphicsPath(bitmap);
51
52# // Apply new region
53form.Region = new Region(graphicsPath);
54}
55
56# // Check if we are dealing with Button here
57else if(control is System.Windows.Forms.Button)
58{
59// Cast to a button object
60Button button = (Button)control;
61
62# // Do not show button text
63button.Text = "";
64
65// Change cursor to hand when over button
66button.Cursor = Cursors.Hand;
67
68# // Set background image of button
69button.BackgroundImage = bitmap;
70
71// Calculate the graphics path based on the bitmap supplied
72GraphicsPath graphicsPath =
73
74# CalculateControlGraphicsPath(bitmap);
75
76# // Apply new region
77button.Region = new Region(graphicsPath);
78}
79}
80
81# /// <summary>
82/// Calculate the graphics path that representing the figure in the bitmap
83/// excluding the transparent color which is the top left pixel.
84/// </summary>
85/// <param name="bitmap"/>The Bitmap object to calculate our graphics path
86
87# from
88/// <returns>Calculated graphics path</returns>
89private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)
90{
91// Create GraphicsPath for our bitmap calculation
92GraphicsPath graphicsPath = new GraphicsPath();
93
94# // Use the top left pixel as our transparent color
95Color colorTransparent = bitmap.GetPixel(0, 0);
96
97# // This is to store the column value where an opaque pixel is first
98
99# found.
100// This value will determine where we start scanning for trailing
101
102# opaque pixels.
103int colOpaquePixel = 0;
104
105# // Go through all rows (Y axis)
106for(int row = 0; row < bitmap.Height; row ++)
107{
108// Reset value
109colOpaquePixel = 0;
110
111# // Go through all columns (X axis)
112for(int col = 0; col < bitmap.Width; col ++)
113{
114// If this is an opaque pixel, mark it and search
115
116# for anymore trailing behind
117if(bitmap.GetPixel(col, row) != colorTransparent)
118{
119// Opaque pixel found, mark current
120
121# position
122colOpaquePixel = col;
123
124# // Create another variable to set the
125
126# current pixel position
127int colNext = col;
128
129# // Starting from current found opaque
130
131# pixel, search for anymore opaque pixels
132// trailing behind, until a transparent
133
134# pixel is found or minimum width is reached
135for(colNext = colOpaquePixel; colNext <
136
137# bitmap.Width; colNext ++)
138if(bitmap.GetPixel(colNext, row) ==
139
140# colorTransparent)
141break;
142
143# // Form a rectangle for line of opaque
144
145# pixels found and add it to our graphics path
146graphicsPath.AddRectangle(new
147
148# Rectangle(colOpaquePixel, row, colNext - colOpaquePixel, 1));
149
150# // No need to scan the line of opaque
151
152# pixels just found
153col = colNext;
154}
155}
156}
157
158# // Return calculated graphics path
159return graphicsPath;
160}
161}
162}
163///////////////////////////////////////////////////////////////////////////////////////////
164
165# //////////
166Form1.cs
167using System;
168using System.Drawing;
169using System.Collections;
170using System.ComponentModel;
171using System.Windows.Forms;
172using System.Data;
173//using System.Runtime.InteropServices;
174
175# namespace BitmapRegionTest
176{
177/// <summary>
178/// Summary description for Form1.
179/// </summary>
180public class Form1 : System.Windows.Forms.Form
181{
182// [DllImport("user32.dll")]
183// private static extern bool PostMessage(IntPtr hWnd, int msg, long wParam,
184
185# long lParam);
186
187# private System.Windows.Forms.Button button1;
188private System.Windows.Forms.Button button2;
189private System.Windows.Forms.Button button3;
190private System.Windows.Forms.Button button4;
191
192# /// <summary>
193/// Required designer variable.
194/// </summary>
195private System.ComponentModel.Container components = null;
196
197# // Load our bitmaps
198private Bitmap bmpFrmBack = new Bitmap(typeof(Form1), "back.bmp");
199private Bitmap bmpBob = new Bitmap(typeof(Form1), "bob.bmp");
200private Bitmap bmpBobSay = new Bitmap(typeof(Form1), "bobsay.bmp");
201private Bitmap bmpSmiles = new Bitmap(typeof(Form1), "smiles.bmp");
202private Bitmap bmpSmilesAngry = new Bitmap(typeof(Form1),
203
204# "smilesangry.bmp");
205private Bitmap bmpGreenBtnUp = new Bitmap(typeof(Form1), "greenbtnup.bmp");
206private Bitmap bmpGreenBtnDown = new Bitmap(typeof(Form1),
207
208# "greenbtndown.bmp");
209private Bitmap bmpX = new Bitmap(typeof(Form1), "x.bmp");
210private Bitmap bmpXSmile = new Bitmap(typeof(Form1), "xsmile.bmp");
211
212# // To store the location of previous mouse left click in the form
213// so that we can use it to calculate the new form location during dragging
214private Point prevLeftClick;
215
216# // To determine if it is the first time entry for every dragging of the
217
218# form
219private bool isFirst = true;
220
221# // Acts like a gate to do allow or deny
222private bool toBlock = true;
223
224# public Form1()
225{
226//
227// Required for Windows Form Designer support
228//
229InitializeComponent();
230
231# // Make our bitmap region for the form
232BitmapRegion.CreateControlRegion(this, bmpFrmBack);
233
234# // Make our bitmap regions for the buttons
235BitmapRegion.CreateControlRegion(button1, bmpBob);
236BitmapRegion.CreateControlRegion(button2, bmpSmiles);
237BitmapRegion.CreateControlRegion(button3, bmpGreenBtnUp);
238BitmapRegion.CreateControlRegion(button4, bmpX);
239}
240
241# /// <summary>
242/// Clean up any resources being used.
243/// </summary>
244protected override void Dispose( bool disposing )
245{
246if( disposing )
247{
248if (components != null)
249{
250components.Dispose();
251}
252}
253base.Dispose( disposing );
254}
255
256# #region Windows Form Designer generated code
257/// <summary>
258/// Required method for Designer support - do not modify
259/// the contents of this method with the code editor.
260/// </summary>
261private void InitializeComponent()
262{
263this.button1 = new System.Windows.Forms.Button();
264this.button2 = new System.Windows.Forms.Button();
265this.button3 = new System.Windows.Forms.Button();
266this.button4 = new System.Windows.Forms.Button();
267this.SuspendLayout();
268//
269// button1
270//
271this.button1.Location = new System.Drawing.Point(104, 88);
272this.button1.Name = "button1";
273this.button1.TabIndex = 0;
274this.button1.Text = "button1";
275this.button1.Click += new System.EventHandler(this.button1_Click);
276this.button1.MouseEnter += new
277
278# System.EventHandler(this.button1_MouseEnter);
279this.button1.MouseLeave += new
280
281# System.EventHandler(this.button1_MouseLeave);
282//
283// button2
284//
285this.button2.Location = new System.Drawing.Point(328, 80);
286this.button2.Name = "button2";
287this.button2.TabIndex = 1;
288this.button2.Text = "button2";
289this.button2.Click += new System.EventHandler(this.button2_Click);
290this.button2.MouseEnter += new
291
292# System.EventHandler(this.button2_MouseEnter);
293this.button2.MouseLeave += new
294
295# System.EventHandler(this.button2_MouseLeave);
296//
297// button3
298//
299this.button3.Location = new System.Drawing.Point(184, 200);
300this.button3.Name = "button3";
301this.button3.TabIndex = 2;
302this.button3.Text = "button3";
303this.button3.Click += new System.EventHandler(this.button3_Click);
304this.button3.MouseEnter += new
305
306# System.EventHandler(this.button3_MouseEnter);
307this.button3.MouseLeave += new
308
309# System.EventHandler(this.button3_MouseLeave);
310//
311// button4
312//
313this.button4.Location = new System.Drawing.Point(344, 232);
314this.button4.Name = "button4";
315this.button4.TabIndex = 3;
316this.button4.Text = "button4";
317this.button4.Click += new System.EventHandler(this.button4_Click);
318this.button4.MouseEnter += new
319
320# System.EventHandler(this.button4_MouseEnter);
321this.button4.MouseLeave += new
322
323# System.EventHandler(this.button4_MouseLeave);
324//
325// Form1
326//
327this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
328this.ClientSize = new System.Drawing.Size(432, 270);
329this.Controls.AddRange(new System.Windows.Forms.Control[] {
330
331
332# this.button4,
333
334
335# this.button3,
336
337
338# this.button2,
339
340
341# this.button1});
342this.Name = "Form1";
343this.Text = "Form1";
344this.MouseMove += new
345
346# System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
347this.ResumeLayout(false);
348
349# }
350#endregion
351
352# /// <summary>
353/// The main entry point for the application.
354/// </summary>
355[STAThread]
356static void Main()
357{
358Application.Run(new Form1());
359}
360
361# private void button1_MouseEnter(object sender, System.EventArgs e)
362{
363// Make bitmap region for button
364BitmapRegion.CreateControlRegion(button1, bmpBobSay);
365}
366
367# private void button1_MouseLeave(object sender, System.EventArgs e)
368{
369// Make bitmap region for button
370BitmapRegion.CreateControlRegion(button1, bmpBob);
371}
372
373# private void button2_MouseEnter(object sender, System.EventArgs e)
374{
375// Make bitmap region for button
376BitmapRegion.CreateControlRegion(button2, bmpSmilesAngry);
377}
378
379# private void button2_MouseLeave(object sender, System.EventArgs e)
380{
381// Make bitmap region for button
382BitmapRegion.CreateControlRegion(button2, bmpSmiles);
383}
384
385# private void button3_MouseEnter(object sender, System.EventArgs e)
386{
387// Make bitmap region for button
388BitmapRegion.CreateControlRegion(button3, bmpGreenBtnDown);
389}
390
391# private void button3_MouseLeave(object sender, System.EventArgs e)
392{
393// Make bitmap region for button
394BitmapRegion.CreateControlRegion(button3, bmpGreenBtnUp);
395}
396
397# private void button4_MouseEnter(object sender, System.EventArgs e)
398{
399// Make bitmap region for button
400BitmapRegion.CreateControlRegion(button4, bmpXSmile);
401}
402
403# private void button4_MouseLeave(object sender, System.EventArgs e)
404{
405// Make bitmap region for button
406BitmapRegion.CreateControlRegion(button4, bmpX);
407}
408
409# private void button1_Click(object sender, System.EventArgs e)
410{
411MessageBox.Show("bob");
412}
413
414# private void button2_Click(object sender, System.EventArgs e)
415{
416MessageBox.Show("smiles");
417}
418
419# private void button3_Click(object sender, System.EventArgs e)
420{
421MessageBox.Show("green button");
422}
423
424# private void button4_Click(object sender, System.EventArgs e)
425{
426MessageBox.Show("Exiting now...");
427Close();
428}
429/*
430protected override void OnMouseDown(MouseEventArgs e)
431{
432if(e.Button == MouseButtons.Left)
433{
434const int HTCAPTION = 2;
435const int WM_NCLBUTTONDOWN = 161;
436
437int ix = e.X & 0xffff;
438int iy = e.Y & 0xffff;
439long ll = ix | iy << 16;
440
441# PostMessage(this.Handle, WM_NCLBUTTONDOWN, HTCAPTION, ll);
442}
443}
444*/
445private void Form1_MouseMove(object sender,
446
447# System.Windows.Forms.MouseEventArgs e)
448{
449// Check if dragging of the form has occurred
450if(e.Button == MouseButtons.Left)
451{
452// If this is the first mouse move event for left click
453
454# dragging of the form,
455// store the current point clicked so that we can use it to
456
457# calculate the form's
458// new location in subsequent mouse move events due to left
459
460# click dragging of the form
461if(isFirst == true)
462{
463// Store previous left click position
464prevLeftClick = new Point(e.X, e.Y);
465
466# // Subsequent mouse move events will not be treated
467
468# as first time, until the
469// left mouse click is released or other mouse
470
471# click occur
472isFirst = false;
473}
474
475# // On subsequent mouse move events with left mouse click
476
477# down. (During dragging of form)
478else
479{
480// This flag here is to allow alternate processing
481
482# for dragging the form because it
483// causes serious flicking when u allow every such
484
485# events to change the form's location.
486// You can try commenting this out to see what i
487
488# mean
489if(toBlock == false)
490this.Location = new Point(this.Location.X +
491
492# e.X - prevLeftClick.X, this.Location.Y + e.Y - prevLeftClick.Y);
493
494# // Store new previous left click position
495prevLeftClick = new Point(e.X, e.Y);
496
497# // Allow or deny next mouse move dragging event
498toBlock = !toBlock;
499}
500}
501
502# // This is a new mouse move event so reset flag
503else
504isFirst = true;
505}
506}
507}</bitmap.width;>