C#+WindowsAPI操縱系統(tǒng)菜單

字號:

一、前言
    本文針對C#.net中沒有提供直接的類似SystemMenu的屬性或類似GetSystemMenu的成員函數(shù)的情況,通過調(diào)用Windows API設(shè)計了一個C#類SystemMenu,從而實現(xiàn)了傳統(tǒng)的對于系統(tǒng)菜單的操作。
    二、系統(tǒng)菜單簡介
    當你單擊窗口圖標或右擊窗口標題欄時系統(tǒng)菜單即彈出。它包含當前窗口的默認行為。不同窗口的系統(tǒng)菜單看起來有些不同,如一個正常窗口的系統(tǒng)菜單看起來與一個工具欄子對話框窗口的菜單就不一樣。
    修改系統(tǒng)菜單的好處:
    ·添加應(yīng)用程序自己定義的菜單項。
    ·在WW被最小化時,SS是一個很好的地方來放置動作,可以被存取,因為SS可以顯示,通過在任務(wù)欄窗口圖標上單擊右鍵。
    ·使某菜單項失去能力,如從系統(tǒng)菜單中移去“化”,“最小化”“關(guān)閉”等。由于這種改動還影響到窗口右上角的三個按鈕,所以這是一個使窗口右上角“X”失去能力的不錯的辦法。
    操縱系統(tǒng)菜單
    通過調(diào)用 API函數(shù)GetSystemMenu,你就檢索到了系統(tǒng)菜單的一個拷貝。該函數(shù)的第二個參數(shù)指明是否你要復(fù)位系統(tǒng)菜單到它的缺省狀態(tài)。再加上另外幾個API菜單函數(shù)如AppendMenu, InsertMenu等,你就能實現(xiàn)對于系統(tǒng)菜單的靈活控制。
    下面我僅簡單介紹如何添加菜單項以及如何實現(xiàn)新項與用戶的交互。
    三、SystemMenu 類介紹
    SystemMenu類的實現(xiàn)使得整個系統(tǒng)菜單存取變得非常容易。你可以使用這個類來修改一個窗口的菜單。 通過調(diào)用靜態(tài)成員函數(shù)FromForm你得到一個對象,該函數(shù)要求一個Form對象或一個從Form繼承的類作為它的參數(shù)。然后它創(chuàng)建一個新的對象,當然如果GetSystemMenu API調(diào)用失敗的話,將引發(fā)一個NoSystemMenuException例外。
    注意,每一個Windows API菜單函數(shù)要求一個菜單句柄以利于操作。因為菜單句柄實際上是一個C++指針,所以在.NET中你要使用IntPtr來操作它。許多函數(shù)還需要一個位掩碼標志來指明新菜單項的動作或形式。幸運的是,你不必象在VC++中那樣,通過某個頭文件的包含來使用一系列的位掩碼標志定義,.NET中已經(jīng)提供了一個現(xiàn)成的公共枚舉類ItemFlags。下面對這個類的幾個重要成員作一說明:
    ·mfString―― 告訴子系統(tǒng)將顯示由菜單項中的“Item”參數(shù)傳遞的字符串。
    ·mfSeparator――此時 "ID" 與 "Item" 參數(shù)被忽略。
    ·MfBarBreak―― 當用于菜單條時,其功能與mfBreak一樣;當用于下拉菜單,子菜單或快捷菜單時,新的一列與舊有的一列由一線垂直線所隔開。
    ·MfBreak――把當前項目放在一個新行(菜單條)或新的一列(下拉菜單,子菜單或快捷菜單)。
    注意:如果指定多個標志,應(yīng)該用位操作運算符|(或)連接。例如:
    //將創(chuàng)建一個菜單項 "Test" ,且該項被選中(checked)
    mySystemMenu.AppendMenu(myID, "Test", ItemFlags.mfString |ItemFlags.mfChecked);
    “Item”參數(shù)指定了新項中要顯示的文本,其ID必須是的數(shù)字――用來標志該菜單項。
    注意:確保新項的ID大于0小于0XF000。因為大于等于0XF000的范圍為系統(tǒng)命令所保留使用。你也可以調(diào)用類SystemMenu的靜態(tài)方法VerifyItemID來核驗是否你的ID正確。
    另外,還有兩個需要解釋的常量:mfByCommand和mfByPosition。
    第一,在缺省情況下,使用mfByCommand。第二,“Pos”的解釋依賴于這些標志:如果你指定mfByCommand,“Pos”參數(shù)就是在新項目插入前項目的ID;如果你指定mfByPosition,“Pos”參數(shù)就是以0索引為開頭的新項的相對位置;如果是-1并且指定mfByPosition,該項目將被插入到最后。這也正是為什么AppendMenu()可以為InsertMenu()所取代的原因。