Level Up

謙卑學習,持之以恆,才能不斷的Level Up

最新回應

[C#][VB.NET]自定義.NET WindowForm表單介面

2008/11/11 23:09| 閱讀數 : 3940 | 1 人推薦 我要推薦 | 19 Comments | 文章分類: C# VB.NET 訂閱

Abstract

  • Introduction
  • 自定義WindowForm表單介面
  • Conclusion

 

Introduction

本篇將由一個簡單的小範例,試範如何實現自定義的WindowForm表單介面。

 

自定義WindowForm表單介面

Step1.首先,打開一個Window Form專案。

image

 

Step2.設定其表單的FormBorderStyle屬性值為None,你會發現設完後其表單的標題列與視窗本來的邊框都不見了。

image 

 

Step3.設定表單的BackgroundImage屬性,將其屬性值設定為自定義的介面圖片。設定完後表單會變成自定義的介面,記得要把表單的大小調整的跟圖片一樣。這邊若自定義的介面是非矩形的介面,則須利用Form.TransparencyKey屬性把介面多餘的部份變為透明。

image

 

Step4.為了後面方便做到自定表單標題列的拖曳動作。我們在表單中加入一個Panel控制項,並使其Dock在最上面,且剛好覆蓋標題列。

image

 

Step5.將剛放入的Panel的BackColor設為Transparent,設定完後Panel將會變成透明的,使用者無法用肉眼察覺此Panel的存在。

image 

 

Step6.針對標題列上Panel的MouseDown事件與MouseMove事件加入處理表單拖曳的程式碼,實現自定表單標題列的拖曳機制。

VB.NET

 

    Private Sub pnlTitleBar_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pnlTitleBar.MouseDown
       '紀錄滑鼠點選時的視窗位置與滑鼠點選位置
        nOldWndLeft = Me.Left
        nOldWndTop = Me.Top
        nClickX = e.X
        nClickY = e.Y
    End Sub

    Private Sub pnlTitleBar_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pnlTitleBar.MouseMove
        If pnlTitleBar.Capture = True Then		'如果滑鼠按著拖曳
            '設定新的視窗位置
            Me.Top = e.Y + nOldWndTop - nClickY
            Me.Left = e.X + nOldWndLeft - nClickX
           '更新紀錄的視窗位置
            nOldWndLeft = Me.Left
            nOldWndTop = Me.Top
        End If
    End Sub

 

C#

        private void pnlTitleBar_MouseDown(object sender, MouseEventArgs e)
        {
            //紀錄滑鼠點選時的視窗位置與滑鼠點選位置
            nOldWndLeft = this.Left;
            nOldWndTop = this.Top;
            nClickX = e.X;
            nClickY = e.Y;
        }

        private void pnlTitleBar_MouseMove(object sender, MouseEventArgs e)
        {
            if (pnlTitleBar.Capture == true)		//如果滑鼠按著拖曳
            {
                //'設定新的視窗位置
                this.Top = e.Y + nOldWndTop - nClickY;
                this.Left = e.X + nOldWndLeft - nClickX;
                //更新紀錄的視窗位置
                nOldWndLeft = this.Left;
                nOldWndTop = this.Top;
            }

        }

 

Step7.在標題列放入兩個PictureBox,並將其外觀設定的跟標題列的按鈕一樣。

image

 

Step8.加入實作標題列按鈕的程式碼。

VB.NET

    Private Sub pbxMinBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pbxMinBtn.Click
        Me.WindowState = FormWindowState.Minimized		'標題列縮小按鈕被按下=>縮小視窗
    End Sub

    Private Sub pbxCloseBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pbxCloseBtn.Click
        Me.Close()		'標題列關閉按鈕被按下=>關閉視窗
    End Sub

C#

 

        private void pbxMinBtn_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;		//標題列縮小按鈕被按下=>縮小視窗
        }

        private void pbxCloseBtn_Click(object sender, EventArgs e)
        {
            this.Close();		//標題列關閉按鈕被按下=>關閉視窗
        }

 

 

Step9.完成

image

 

完整範例如下:

VB.NET

 

Public Class Form1

    Dim nOldWndLeft As Integer
    Dim nOldWndTop As Integer
    Dim nClickX As Integer
    Dim nClickY As Integer

    Private Sub pbxMinBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pbxMinBtn.Click
        Me.WindowState = FormWindowState.Minimized		'標題列縮小按鈕被按下=>縮小視窗
    End Sub

    Private Sub pbxCloseBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pbxCloseBtn.Click
        Me.Close()		'標題列關閉按鈕被按下=>關閉視窗
    End Sub

    Private Sub pnlTitleBar_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pnlTitleBar.MouseDown
       '紀錄滑鼠點選時的視窗位置與滑鼠點選位置
        nOldWndLeft = Me.Left
        nOldWndTop = Me.Top
        nClickX = e.X
        nClickY = e.Y
    End Sub

    Private Sub pnlTitleBar_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pnlTitleBar.MouseMove
        If pnlTitleBar.Capture = True Then		'如果滑鼠按著拖曳
            '設定新的視窗位置
            Me.Top = e.Y + nOldWndTop - nClickY
            Me.Left = e.X + nOldWndLeft - nClickX
           '更新紀錄的視窗位置
            nOldWndLeft = Me.Left
            nOldWndTop = Me.Top
        End If
    End Sub

End Class

 

C#

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        int nOldWndLeft;
        int nOldWndTop;
        int nClickX;
        int nClickY;

        public Form1()
        {
            InitializeComponent();
        }

        private void pbxMinBtn_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;		//標題列縮小按鈕被按下=>縮小視窗
        }

        private void pbxCloseBtn_Click(object sender, EventArgs e)
        {
            this.Close();		//標題列關閉按鈕被按下=>關閉視窗
        }

        private void pnlTitleBar_MouseDown(object sender, MouseEventArgs e)
        {
            //紀錄滑鼠點選時的視窗位置與滑鼠點選位置
            nOldWndLeft = this.Left;
            nOldWndTop = this.Top;
            nClickX = e.X;
            nClickY = e.Y;
        }

        private void pnlTitleBar_MouseMove(object sender, MouseEventArgs e)
        {
            if (pnlTitleBar.Capture == true)		//如果滑鼠按著拖曳
            {
                //'設定新的視窗位置
                this.Top = e.Y + nOldWndTop - nClickY;
                this.Left = e.X + nOldWndLeft - nClickX;
                //更新紀錄的視窗位置
                nOldWndLeft = this.Left;
                nOldWndTop = this.Top;
            }

        }
    }
}

 

 

Conclusion

這篇以一個簡單的小範例試範了如何實現自定義的WindowForm表單介面。值得注意的是,該篇試範的是用簡單的矩形表單,當自定義的表單不是一般的矩形的話,則須要結合 設定.NET透明表單 與這篇的概念下去做,把介面多餘的部份變為透明的。表單介面在顯示上才不會有多餘的空白部份。


 

推到 Twitter!
推到 Plurk!

Share/Save/Bookmark


關連文章

回應

  • Hunter 2009/3/19 下午 04:38 回覆

    # re: 自定義.NET WindowForm表單介面

    大大您好,
    小弟有兩個問題,麻煩大大解惑
    1.FormBorderStyle屬性值設為None之後,From就沒有辦法改變大小了,是否有辦法做到隱藏標題列,但可以改變視窗大小。
    2.問題一將FormBorderStyle屬性設定為SizableToolWindow並且將Form的Text清空,即可改變視窗大小,但是就會變成這個Form沒有名字(導致系統列Taskbar顯示出來是空的),是否有解?

    綜合以上兩點,其實我想做到的功能如下:
    1.自訂Form (隱藏標題列)
    2.可以改變Form大小
    3.可以拖曳Form
    4.Form 要有名字
  • larrynung 2009/3/21 上午 08:23 回覆

    # re: 自定義.NET WindowForm表單介面

    直覺上若能直接呼叫Win32API去直接把Title隱藏
    應該是最快的方法
    但不知道有無這種Win32API
    這塊我不熟
    目前我只有較笨的解法
    且這樣做會有個問題是
    當滑鼠移到工作列上按右鍵
    選單會出不來
    作法如下
    Public Class Form1

        Enum Direction
            NONE
            TOP
            BOTTOM
            LEFT
            RIGHT
            LEFTTOP
            LEFTBOTTOM
            RIGHTTOP
            RIGHTBOTTOM
        End Enum


        Dim alreadyCaptured As Boolean
        Dim x As Integer
        Dim y As Integer
        Dim interval As Integer = 5
        Dim adjustDirection As Direction

        Private Sub ResizablePanel_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
            If Me.Capture Then
                If alreadyCaptured Then
                    AdjustBounds(e)
                End If

                x = e.X
                y = e.Y
            Else
                SetAdjustDirection(e)
                SetCursor()
            End If
            alreadyCaptured = Me.Capture
        End Sub

        Private Function IsMatch(ByVal n As Integer, ByVal xy As Integer) As Boolean
            Return (xy - interval < n) AndAlso (n < xy + interval)
        End Function


        Private Sub SetCursor()
            Select Case adjustDirection
                Case Direction.LEFTTOP, Direction.RIGHTBOTTOM
                    Me.Cursor = Cursors.SizeNWSE
                Case Direction.RIGHTTOP, Direction.LEFTBOTTOM
                    Me.Cursor = Cursors.SizeNESW
                Case Direction.LEFT, Direction.RIGHT
                    Me.Cursor = Cursors.SizeWE
                Case Direction.TOP, Direction.BOTTOM
                    Me.Cursor = Cursors.SizeNS
                Case Direction.NONE
                    Me.Cursor = Cursors.Default
            End Select
        End Sub


        Private Sub SetAdjustDirection(ByVal e As System.Windows.Forms.MouseEventArgs)
            If IsMatch(e.X, 0) AndAlso IsMatch(e.Y, 0) Then
                adjustDirection = Direction.LEFTTOP
            ElseIf IsMatch(e.X, 0) AndAlso IsMatch(e.Y, Me.Height - 1) Then
                adjustDirection = Direction.LEFTBOTTOM
            ElseIf IsMatch(e.X, Me.Width - 1) AndAlso IsMatch(e.Y, 0) Then
                adjustDirection = Direction.RIGHTTOP
            ElseIf IsMatch(e.X, Me.Width - 1) AndAlso IsMatch(e.Y, Me.Height - 1) Then
                adjustDirection = Direction.RIGHTBOTTOM
            ElseIf IsMatch(e.X, 0) Then
                adjustDirection = Direction.LEFT
            ElseIf IsMatch(e.X, Me.Width - 1) Then
                adjustDirection = Direction.RIGHT
            ElseIf IsMatch(e.Y, 0) Then
                adjustDirection = Direction.TOP
            ElseIf IsMatch(e.Y, Me.Height - 1) Then
                adjustDirection = Direction.BOTTOM
            Else
                adjustDirection = Direction.NONE
            End If
        End Sub

        Private Sub AdjustBounds(ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim x As Integer = e.X - Me.x
            Dim y As Integer = e.Y - Me.y
            Select Case adjustDirection
                Case Direction.LEFTTOP
                    Me.Left += e.X
                    Me.Width -= e.X
                    Me.Top += e.Y
                    Me.Height -= e.Y
                Case Direction.LEFTBOTTOM
                    Me.Left += e.X
                    Me.Width -= e.X
                    Me.Height += y
                Case Direction.RIGHTBOTTOM
                    Me.Width += x
                    Me.Height += y
                Case Direction.RIGHTTOP
                    Me.Top += e.Y
                    Me.Height -= e.Y
                    Me.Width += x
                Case Direction.LEFT
                    Me.Left += e.X
                    Me.Width -= e.X
                Case Direction.RIGHT
                    Me.Width += x
                Case Direction.TOP
                    Me.Top += e.Y
                    Me.Height -= e.Y
                Case Direction.BOTTOM
                    Me.Height += y
            End Select
        End Sub

    End Class
     

  • larrynung 2009/3/21 上午 09:23 回覆

    # re: 自定義.NET WindowForm表單介面

    發現更簡單的方法
    參考看看(FormBorderStyle不用改none)
    Dim r As Rectangle = New Rectangle(0, 30, Me.Width, Me.Height)
    Me.Region = New Region(r)

    這方法只是把標題列不秀
    因此縮放等基本功能都是表單本來就有的
    最多只要補上表單上方的縮放功能

  • KK 2009/7/6 下午 03:58 回覆

    # re: 自定義.NET WindowForm表單介面

    大大請教一下

    我把Title變成Panel後

    點在Panel上拖動整個Form

    但是發生我的ListBox再拖動後的ScrollBar上下鈕

    不能使用

    又拖動一下,才可使用

    就這樣循環下去!!
  • larrynung 2009/7/7 下午 03:52 回覆

    # re: 自定義.NET WindowForm表單介面

    有程式可以讓我測試嗎?
  • KK 2009/7/8 下午 05:56 回覆

    # re: 自定義.NET WindowForm表單介面

    可以~!!

    把MAIL給我
  • KK 2009/7/8 下午 06:32 回覆

    # re: 自定義.NET WindowForm表單介面

    MAIL不能用

    加MSN: kimenyeh@hotmail.com
  • larrynung 2009/7/8 下午 07:28 回覆

    # re: 自定義.NET WindowForm表單介面

    為何不能用呢?!你寫個簡單的範例丟到免費空間給我抓好了!!免費空間網址 http://www.toofiles.com/zh/
  • kennyshu 2009/10/16 上午 03:32 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    這篇讚!剛好派上用場

  • 新手 2010/1/25 下午 08:22 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    請問一下大大,改成沒有TitleBar之後,有設Icon,在XP以上的OS都可以在工具列上正常顯示Icon,但是在Win2000上面,卻發生不能顯示Icon問題,而且點擊工具列上的Button都沒反應,不能縮小也沒放大功能!!
  • 蹂躪 2010/1/26 上午 08:59 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    Hi,新手~我後面幾篇有談到這個問題,請往後瀏覽相關主題的文章。
  • 新手 2010/1/26 上午 10:03 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    大大~請問在哪一篇?新手小弟愚鈍,找不到!!請求賜教!
  • 蹂躪 2010/1/26 上午 10:31 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    Hi,
    [C#][VB.NET]自定義.NET WindowForm表單介面(二)
    http://www.dotblogs.com.tw/larrynung/archive/2009/03/21/7625.aspx
  • 新手 2010/1/26 上午 10:38 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    大大你說這方法我Try過了,2個方法在Win2000(P)上面都還是不能顯示Icon,當我把TitleBar叫出來,這時候就會有Icon了!真是無解....!
  • 蹂躪 2010/1/26 上午 11:24 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    Hi,那篇是有提供縮放與工具列上的圖示解法,至於您說的Icon,我看不太懂。因為都自定義控制項了,Icon部分不是自己處理嗎?我不知道這部分您是怎摸處理的!!
  • 新手 2010/1/26 上午 11:31 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    在大大那篇,方法2的STEP.3裡面,那個圖就是在Form的屬性Icon為預設值的關係,假如塞入一個Icon給他,那們就會有Icon出現,但是在Win2000上Run,假如沒有TitleBar如何才能讓TaskBar的Icon出現,並能夠正常縮放!
  • 蹂躪 2010/1/26 下午 01:00 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    Hi, 我這邊沒有Win2000可以測試,你提到的方法2的Step3基本上也無顯示表單上的字串,多半用這方法應該不會要顯示在TaskBar吧!您確定您使用的是方法2?另外,方法2不能達到的話,您不考慮一下其它方法?
  • 新手 2010/1/26 下午 02:01 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    其他方法我都TRY過了,目前大大所提供方法都沒法達到小弟的需求!
    不知道大大有無其他方法!小弟目前需求~AP可以在Win2000上的TaskBar顯示出AP的Icon,就這樣!
  • 新手 2010/1/27 下午 03:51 回覆

    # re: [C#][VB.NET]自定義.NET WindowForm表單介面

    小弟自行解決了,還是感謝大大指教^^V
標題 *
名稱 *
Email (將不會被顯示)
Url
回應
登入後使用進階評論
Please add 1 and 2 and type the answer here: