天天看點

C# winform中不規則窗體制作的解決方案(已經解決24位色以上不能正常顯示問題)

這篇文章中關于圖象的問題是:最好使用PNG格式,在項目中我們用過各種格式,覺得還是PNG格式在做圖象背景時候更合理。實作一個不規則窗體,沒有下面介紹的方法那麼複雜,我轉載這篇文章的原因就是因為它多出了一個BitmapRegion.cs 類。

----------uestc_terry

----------------------------------------------

相信每個程式設計愛好者都希望自己的程式不僅性能優越而且有一個美觀的界面,一個差別于别人的程式的個性化的界面。然而以前煩瑣的API調用和大量的代碼使大家望而卻步。現在好了,在C#中通過少量的代碼就可以實作不規則窗體的制作。如果您有興趣就接着往下看吧。

一、在說我用的方法前,我不得不說一下另一種方法,這種方法在實作不規則窗體自身顯示效果(即除開窗體的移動、最大最小話、關閉等)時是不用編代碼的。非常簡便,但它的緻命缺點就是要要求程式運作環境在24位色以下,否則不規則窗體的透明部分就會顯示出來,窗體會非常難看。

方法1:

步驟1:先用圖象處理軟體制作您的不規則窗體的位圖BMP(最好是位圖,其它的我沒有試過:))。制作時請注意将背景色(即需要設定成透明的顔色部分)設定成與非背景圖檔顔色反差較大的顔色,并且使用一種容易記憶的顔色。如下圖:

圖中黃顔色背景将要設定成透明部分

步驟2:建立windows應用程式。建立windows窗體并設定窗體基本屬性。

(1)将 FormBorderStyle 屬性設定為 None。

(2)将窗體的 BackgroundImage 屬性設定為先前建立的位圖檔案。不必将檔案添加到項目系統中;這将在指定該檔案作為背景圖像時自動完成。

(3)将 TransparencyKey 屬性設定為位圖檔案的背景色,本例中為×××。(此屬性告訴應用程式窗體中的哪些部分需要設定為透明。 )

  上面兩個步驟已經完成了不規則窗體自身顯示效果的制作,此刻您要做的就是為窗體添加移動、關閉、最大最小化的事件。這個将在方法2中詳細介紹。

  方法1在24位色以下的環境中可以顯示正常,但在24位色以上時×××背景不能消失,是以方法1不能勝任24位色以上環境。

    為了解決這個問題,我們可以用到方法2。

方法2

步驟1:同方法1,先用圖象處理軟體制作您的不規則窗體的位圖BMP

步驟2:建立windows應用程式。建立windows窗體。

      由于方法2是調用類來實作制作不規則窗體,是以您隻需要在窗體的LOAD事件中加入以下代碼:

複制   儲存

private void login_Load(object sender, System.EventArgs e)

{

    //初始化調用不規則窗體生成代碼

    BitmapRegion BitmapRegion = new BitmapRegion();//此為生成不規則窗體和控件的類

    BitmapRegion.CreateControlRegion(this, new Bitmap("HMlogin.bmp"));

}

其中"HMlogin.bmp"為您制作的位圖。

下面就是檔案BitmapRegion.cs 我在網上找到的是英文的,自己翻譯了一下,英語水準有限,有錯的地方還請大家指出。

/***************************************************************************************/

//

//  功能描述:不規則窗體和控件的生成類

//  撰 寫 人:不祥(網上搜集)

//  //

//  修改說明:2005.8.31 楊丹翻譯和修改

using System;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Windows.Forms;

namespace MsgClassLibrary

    /// <summary>

    /// Summary description for BitmapRegion.

    /// </summary>

    public class BitmapRegion

    {

        public BitmapRegion()

        { }

        /// <summary>

        /// Create and apply the region on the supplied control

        /// 建立支援位圖區域的控件(目前有button和form)

        /// </summary>

        /// <param name="control">The Control object to apply the region to控件</param>

        /// <param name="bitmap">The Bitmap object to create the region from位圖</param>

        public static void CreateControlRegion(Control control, Bitmap bitmap)

        {

            // Return if control and bitmap are null

            //判斷是否存在控件和位圖

            if (control == null || bitmap == null)

                return;

            // Set our control''s size to be the same as the bitmap

            //設定控件大小為位圖大小

            control.Width = bitmap.Width;

            control.Height = bitmap.Height;

            // Check if we are dealing with Form here

            //當控件是form時

            if (control is System.Windows.Forms.Form)

            {

                // Cast to a Form object

                //強制轉換為FORM

                Form form = (Form) control;

                // Set our form''s size to be a little larger that the  bitmap just

                // in case the form''s border style is not set to none in the first place

                //當FORM的邊界FormBorderStyle不為NONE時,應将FORM的大小設定成比位圖大小稍大一點

                form.Width = control.Width;

                form.Height = control.Height;

                // No border

                //沒有邊界

                form.FormBorderStyle = FormBorderStyle.None;

                // Set bitmap as the background p_w_picpath

                //将位圖設定成窗體背景圖檔

                form.BackgroundImage = bitmap;

                // Calculate the graphics path based on the bitmap supplied

                //計算位圖中不透明部分的邊界

                GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);

                // Apply new region

                //應用新的區域

                form.Region = new Region(graphicsPath);

            }

            // Check if we are dealing with Button here

            //當控件是button時

            else if (control is System.Windows.Forms.Button)

                // Cast to a button object

                //強制轉換為 button

                Button button = (Button) control;

                // Do not show button text

                //不顯示button text

                button.Text = "";

                // Change cursor to hand when over button

                //改變 cursor的style

                button.Cursor = Cursors.Hand;

                // Set background p_w_picpath of button

                //設定button的背景圖檔

                button.BackgroundImage = bitmap;

                button.Region = new Region(graphicsPath);

        }

        /// Calculate the graphics path that representing the figure in the bitmap

        /// excluding the transparent color which is the top left pixel.

        /// //計算位圖中不透明部分的邊界

        /// <param name="bitmap">The Bitmap object to calculate our graphics path from</param>

        /// <returns>Calculated graphics path</returns>

        private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)

            // Create GraphicsPath for our bitmap calculation

            //建立 GraphicsPath

            GraphicsPath graphicsPath = new GraphicsPath();

            // Use the top left pixel as our transparent color

            //使用左上角的一點的顔色作為我們透明色

            Color colorTransparent = bitmap.GetPixel(0, 0);

            // This is to store the column value where an opaque pixel is first found.

            // This value will determine where we start scanning for trailing opaque pixels.

            //第一個找到點的X

            int colOpaquePixel = 0;

            // Go through all rows (Y axis)

            // 偏曆所有行(Y方向)

            for (int row = 0; row < bitmap.Height; row++)

                // Reset value

                //重設

                colOpaquePixel = 0;

                // Go through all columns (X axis)

                //偏曆所有列(X方向)

                for (int col = 0; col < bitmap.Width; col++)

                {

                    // If this is an opaque pixel, mark it and search for anymore trailing behind

                    //如果是不需要透明處理的點則标記,然後繼續偏曆

                    if (bitmap.GetPixel(col, row) != colorTransparent)

                    {

                        // Opaque pixel found, mark current position

                        //記錄目前

                        colOpaquePixel = col;

                        // Create another variable to set the current pixel position

                        //建立新變量來記錄目前點

                        int colNext = col;

                        // Starting from current found opaque pixel, search for anymore opaque pixels

                        // trailing behind, until a transparent   pixel is found or minimum width is reached

                        ///從找到的不透明點開始,繼續尋找不透明點,一直到找到或則達到圖檔寬度

                        for (colNext = colOpaquePixel; colNext < bitmap.Width; colNext++)

                            if (bitmap.GetPixel(colNext, row) == colorTransparent)

                                break;

                        // Form a rectangle for line of opaque   pixels found and add it to our graphics path

                        //将不透明點加到graphics path

                        graphicsPath.AddRectangle(new Rectangle(colOpaquePixel, row, colNext - colOpaquePixel, 1));

                        // No need to scan the line of opaque pixels just found

                        col = colNext;

                    }

                }

            // Return calculated graphics path

            return graphicsPath;

    }

完成視窗自身效果後此刻您要做的就是為窗體添加移動、關閉、最大最小化的事件代碼了。

 1、首先,關閉很簡單,隻需要在您的事件中加入

this.Close();//關閉此窗體

//或

Application.Exit();//退出應用程式

2、最大最小化事件也很簡單

this.WindowState=FormWindowState.Minimized;//視窗最小化   

this.WindowState=FormWindowState.Maximized;//視窗最大化

3、移動相對比較麻煩

   你先需要建立兩個全局變量:

private Point mouseOffset;        //記錄滑鼠指針的坐标

private bool isMouseDown = false; //記錄滑鼠按鍵是否按下

然後為您的事件加入相應的代碼:

private void form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

    int xOffset;

    int yOffset;

    if (e.Button == MouseButtons.Left)

        xOffset = -e.X - SystemInformation.FrameBorderSize.Width;

        yOffset = -e.Y - SystemInformation.CaptionHeight -

         SystemInformation.FrameBorderSize.Height;

        mouseOffset = new Point(xOffset, yOffset);

        isMouseDown = true;

private void form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)

    if (isMouseDown)

        Point mousePos = Control.MousePosition;

        mousePos.Offset(mouseOffset.X, mouseOffset.Y);

        Location = mousePos;

private void form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)

    // 修改滑鼠狀态isMouseDown的值

    // 確定隻有滑鼠左鍵按下并移動時,才移動窗體

        isMouseDown = false;

程式的執行情況如下圖:

總結:

我在了解到方法2前也是一直用的方法1,在24位色下不能正常顯示的問題我也頭疼了很久,當時在MSDN上找的文章居然都說是------------“請確定您的使用者是在24位色以下環境中使用本程式”!!!暈死了,這個怎麼行?!現在有了方法2就好了,自己解決了問題不敢獨享,那出來給大家看看。

    另外,方法2中的類也支援制作不規則的button控件,有興趣的朋友可以試試

繼續閱讀