[C#]透過API移除表單的控制功能表方塊中的功能表項目

[C#]透過API移除表單的控制功能表方塊中的功能表項目

Introduction

看到了rico寫的[C#][WinForm]如何關閉表單"X"這篇文章,覺得還滿好玩的。又是一個沒玩過的寫法。在處理上也不難,只要透過GetSystemMenuRemoveMenu這兩個簡單的API,就可以達到關閉視窗的關閉按鈕的效果了。這邊隨手記錄一下。

 

透過API移除表單的控制功能表方塊中的功能表項目

欲使用API移除表單的控制功能表方塊中的功能表項目,只需透過GetSystemMenu API取得SystemMenu的Handle,再把取得的SystemMenu Handle與要關閉的功能選單索引當作參數,傳進RemoveMenu API即可。
image

 

API詳細的使用方式可參考GetSystemMenuRemoveMenu的MSDN說明文件。值得注意的是,RemoveMenu方法第二個參數所帶的索引值,為SystemMenu選單項目的索引。預設的系統選單畫面如下:
image

 

其索引值如下:

功能表項目 索引值
Restore 0
Move 1
Size 2
Minimize 3
Maximize 4
Seperator 5
Close 6

 

了解了實作方法,我們可以把此功能整理成如下類別:


    {
        [DllImport("user32.dll")]
        private static extern int GetSystemMenu(Int32 hWnd, Int32 bRevert);
        [DllImport("user32.dll")]
        private static extern int RemoveMenu(Int32 hMenu, Int32 nPosition, Int32 wFlags);

        const Int32 MF_BYPOSITION = 1024;//&H400  

        public enum SystemMenuItemType
        {
            Restore,
            Move,
            Size,
            Min,
            Max,
            Seperator,
            Close
        }

       public static void RemoveSystemMenuItem(Form form, SystemMenuItemType menuItem)
        {
            RemoveMenu(GetSystemMenu(form.Handle.ToInt32(), 0),(int)menuItem, MF_BYPOSITION); 
        }
        public static void RemoveRestoreSystemMenuItem(Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Restore);
        }

        public static void RemoveMoveSystemMenuItem(Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Move);
        }

        public static void RemoveSizeSystemMenuItem(Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Size);
        }

        public static void RemoveMinSystemMenuItem(Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Min);
        }

        public static void RemoveMaxSystemMenuItem(Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Max);
        }

        public static void RemoveSeperatorSystemMenuItem(Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Seperator);
        }

        public static void RemoveCloseSystemMenuItem(Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Close);
        }
    }

 

使用上可以直接叫用,像這樣:

 

也可以把它整理成擴充方法:


    {
        [DllImport("user32.dll")]
        private static extern int GetSystemMenu(Int32 hWnd, Int32 bRevert);
        [DllImport("user32.dll")]
        private static extern int RemoveMenu(Int32 hMenu, Int32 nPosition, Int32 wFlags);

        const Int32 MF_BYPOSITION = 1024;//&H400  

        public enum SystemMenuItemType
        {
            Restore,
            Move,
            Size,
            Min,
            Max,
            Seperator,
            Close
        }

        public static void RemoveSystemMenuItem(this Form form, SystemMenuItemType menuItem)
        {
            RemoveMenu(GetSystemMenu(form.Handle.ToInt32(), 0), (int)menuItem, MF_BYPOSITION);
        }

        public static void RemoveRestoreSystemMenuItem(this Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Restore);
        }

        public static void RemoveMoveSystemMenuItem(this Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Move);
        }

        public static void RemoveSizeSystemMenuItem(this Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Size);
        }

        public static void RemoveMinSystemMenuItem(this Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Min);
        }

        public static void RemoveMaxSystemMenuItem(this Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Max);
        }

        public static void RemoveSeperatorSystemMenuItem(this Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Seperator);
        }

        public static void RemoveCloseSystemMenuItem(this Form form)
        {
            RemoveSystemMenuItem(form, SystemMenuItemType.Close);
        }

    }

 

在使用上會更為方便:


        {
            this.RemoveCloseSystemMenuItem();
        }

 

運行效果

值得注意的是,透過API移除不同的功能表項目,會對程式造成不一樣的效果。這邊我們可以大致了解一下。

 

當移除了Restore功能表項目,系統功能表選單項目會少了Restore選項。當視窗放到最大後,視窗的右上角的按鈕仍舊會跟一般的視窗放大後一樣。

image

 

但按下中間的還原按鈕卻會沒有效果。

 

移除Move功能表項目,視窗會變得無法搬移。

 

移除Size功能表項目時,當滑鼠移至視窗邊緣,滑鼠游標仍會像一般視窗一樣變為可調整的游標圖示。

image

 

但若真的試圖調整視窗大小,會發現調整大小的功能已經喪失。

 

若移除的是Minimize或是Maximize功能表選單。在視窗的外觀上無差異,視窗右上角的按鈕仍舊存在。只是在按下視窗上對應的功能按鈕時會變得無任何效果。

 

而若是移除Close功能表項目。在視窗右上角我們可以看到按鈕會變為灰階,且不可用滑鼠按下關閉。

image

 

Link

  1. [C#][WinForm]如何關閉表單"X"
  2. 如何移除表單的控制功能表方塊中的功能表項目