WIN 下的超動態菜單(二)用法

来源:http://www.cnblogs.com/tomview/archive/2016/05/25/5521431.html
-Advertisement-
Play Games

WIN 下的超動態菜單(一)簡介 WIN 下的超動態菜單(二)用法 作者:黃山松,發表於博客園:http://www.cnblogs.com/tomview/ auto_dynamenu 是一個動態生成WINDOWS菜單的c++封裝庫,設計思路是要儘量簡化動態菜單的生成代碼,在程式界面任何地方想要顯... ...


WIN 下的超動態菜單(一)簡介

WIN 下的超動態菜單(二)用法

作者:黃山松,發表於博客園:http://www.cnblogs.com/tomview/

        auto_dynamenu 是一個動態生成WINDOWS菜單的c++封裝庫,設計思路是要儘量簡化動態菜單的生成代碼,在程式界面任何地方想要顯示菜單(特別是右鍵菜單)的時候,可以方便生成菜單,特別可以根據程式當時的內部數據,內部狀態來生成不同的動態菜單。

        auto_dynamenu 只封裝了一個靜態的介面函數,這樣處理的目的是把類的實現代碼可以放在頭文件的類的聲明裡面,這樣使用的時候只要包含頭文件就可以直接調用了,不需要把實現文件加入工程,簡化操作。

類的介面函數定義

/**************************************************************************************************\
* static int           :    返回值,表明選擇了哪個菜單項或者被更新的 nDefaultValue
* dynamenu             :    
* HWND hWnd            :    當前視窗句柄
* LPPOINT pPoint       :    顯示菜單的位置,通常為0即可,自動確定顯示的菜單位置
* char* pszMenu        :    表明動態菜單內容的菜單字元串
* int nDefaultMode     :    自動更新菜單選擇標記的模式,0 無,1 等於模式,2 位模式
* int nDefaultValue    :    預設值,根據這個值,按照 nDefaultMode 來顯示菜單項的選擇標記
\**************************************************************************************************/
class auto_dynamenu
{
public:
static int dynamenu(HWND hWnd, LPPOINT pPoint, char* pszMenu, int nDefaultMode, int nDefaultValue);
};

參數:pszMenu

        介面用一個格式化的字元串 pszMenu 來表示動態菜單,具體格式規則如下:

(1)每個菜單項為一個以 \n 結束的字元串

(2)菜單項的字元串通常以等號 = 分割為兩部分,等號前面為要顯示的菜單內容,等號後面為選擇這個菜單後的取值

(3)菜單項的字元串裡面如果沒有等號,表明選擇菜單返回的時候,返回的是菜單項字元串

(3)每個菜單項字元串前面可以加如下的修飾符:

[a] *(星號):表示這個菜單項前面有點的選擇標記

[b] ^:表示這個菜單項前面有對勾的選擇標記

[c] #:表示這個菜單項是灰色的

[d] -(減號):表明這個菜單項和下一個菜單項之間分為不同的列(多列的菜單)

[e] `(鍵盤左上角的按鍵):表示一個沒有意義的占位符

[f] ~:表明是一個菜單分割線

(4)可以用單獨一行的 ~ 表示一個菜單分割橫線,“~\n”

(5)菜單項字元串等號前面部分的豎線字元”|“ 把菜單分割為父菜單和子菜單

(6)把不同的菜單項的字元串連接為一個完整的字元串就可以描述這個整個菜單了

例如:

char szMenu[] = 
        "選項1=20\n"                       //選項1對應數值20,選擇這個函數返回20
        "選項2=0x20\n"                     //選擇2對應數值0x20,選擇這個函數返回0x20
        "選項3=0\n"                        //選項3對應數值0,選擇這個函數返回 INT_MAX(因為函數返回0代表沒有選擇菜單項,所以0用INT_MAX返回值表示)
         "~\n"                             //這個代表一個菜單分割橫線
         "錄像|通用格式|avi格式=-1\n"        //多級子菜單,選擇這個返回-1
        "錄像|通用格式|~\n"                //多級子菜單內部的分割橫線
         "錄像|通用格式|mkv格式=-2\n"        //多級子菜單,選擇這個返回-2
        "錄像|~\n"
        "錄像|專用格式|rdv格式=-3\n"        //多級子菜單,選擇這個返回-3
        "~\n"
        "#暫停處理\n"                      //灰色禁用的菜單項,無法選擇,可以用於顯示信息
         "~\n"
        "控制|^開始視頻=10\n"              //顯示選中的視頻開始菜單,選擇返回10
        "控制|結束視頻=11\n"               //顯示沒有選中的菜單,選擇返回11
        "播放當前錄像 1.avi=d:\\1.avi\n"   //返迴文件名字元串指針
        ;

上面的示例菜單字元串顯示出來的菜單如下:

image

參數:hWnd

        雖然菜單的消息不發往任何視窗,但是這個必須指定一個有效的視窗句柄,否則菜單顯示不出來。通常指定對滑鼠右鍵響應要顯示菜單的視窗,或者主視窗。

參數:pPoint

        菜單顯示位置坐標POINT的指針,用於指定菜單的顯示位置,是屏幕坐標。通常可以給0,這時程式自動選擇菜單的顯示位置,通常根據滑鼠當前位置的控制項類型確定,具體如下:

(1)如果是 BUTTON,工具欄上的按鈕,則顯示在這個控制項的下方,左側對齊

(2)如果是TreeView,ListView則顯示在當前滑鼠位置的條目的下方

(3)如果是TabCtrl則顯示在滑鼠當前的Tab頁的頁頭的下方

(4)大小像個按鈕的ActiveX控制項,顯示在下方

(5)其他顯示在滑鼠的當前位置

參數pPoint備註

         在這個參數給0的時候,代碼自動確定菜單顯示位置,但由於作者通常在VC6下編程(參見博文《我是如何把VC6一直用到2016年的》),因此代碼中判斷控制項類型用的 ClassName 沒有包含新版 Visual C 帶的控制項的類,可能需要使用者增加一些代碼中的控制項類名,對不同的控制項確定不同的顯示菜單的位置。具體情況參考文檔《WIN 下超動態菜單(三)代碼》。

參數:nDefaultMode

        預設模式,如果為0,沒有預設模式,菜單項的標記都在菜單字元串中指定。

        如果為1,相等模式,如果某個菜單項的取值等於傳入的nDefaultValue則顯示選中標記。

        如果為2,為與模式,如果某個菜單項的取值與nDefaultValue的位與不為0,則顯示選中標記。

參數:nDefaultValue

        當前的預設值,配合nDefaultValue使用。

返回值:

        程式應該根據返回值來判斷選擇了哪個菜單,根據nDefaultMode不同含義有差別,用法也有差異。

(1)如果nDefaultMode為0

(a)返回值為0的時候,表明沒有選擇任何菜單選項;

(b)返回值為INT_MAX,表明選擇了某個值為0的菜單項;

(c)如果選擇的菜單項字元串裡面有等號,並且等號後面是數字(支持十進位和十六進位寫法),則返回這個數字;

(d)如果選擇的菜單項字元串裡面的等號後面是字元串,則返回這個等號後面的字元串的指針;

(e)如果選擇的菜單項字元串裡面沒有等號,則返回這個菜單項的字元串的指針。

(2)如果 nDefaultMode 為 1 或者 2

        則返回nDefaultValue經過修改後的值,如果沒有選擇任何菜單,返回值等於nDefaultValue。

直接可以這樣寫 :

nDefaultValue = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, pszMenu, nDefaultMode/*1 or 2*/, nDefaultValue);

動態菜單顯示及根據返回值進行處理示例

char szMenu[] = 
        "選項1=20\n"                    //選項1對應數值20,選擇這個函數返回20
        "選項2=0x20\n"                  //選擇2對應數值0x20,選擇這個函數返回20
        "選項3=0\n"                     //選項3對應數值0,選擇這個函數範圍 INT_MAX(因為函數返回0代表沒有選擇菜單項,所以0用INT_MAX返回值表示)
         "~\n"                           //這個代表一個菜單分割橫線
         "錄像|通用格式|avi格式=-1\n"      //多級子菜單,選擇這個返回-1,可以為負值
        "錄像|通用格式|~\n"              //多級子菜單內部的分割橫線
         "錄像|通用格式|mkv格式=-2\n"      //多級子菜單,選擇這個返回-2
        "錄像|~\n"
        "錄像|專用格式|rdv格式=-3\n"      //多級子菜單,選擇這個返回-3
        "~\n"
        "#暫停處理\n"                    //灰色禁用的菜單項,無法選擇,可以用於顯示信息
         "~\n"
        "控制|^開始視頻=10\n"             //顯示選中的視頻開始菜單,選擇返回10
        "控制|結束視頻=11\n"              //顯示沒有選中的菜單,選擇返回11
        "播放當前錄像 1.avi=d:\\1.avi\n"  //返迴文件名字元串指針
        ;

    int index = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 0, 0);
    switch (index)
    {
    case 0:
        //菜單沒有選擇,不做任何處理
        break;
    case 20:
        //選項1
        break;
    case 0x20:
        //選項2
        break;
    case INT_MAX:
        //選項3,這個菜單項的值為0,通常可以避免這樣的情況,就不需要處理這個特殊的值了
        break;
    case -1:
        //avi 錄像
        break;
    case -2:
        //mkv錄像
        break;
    case -3:
        //rdv錄像
        break;
    case 10:
        //開始視頻
        break;
    case 11:
        //停止視頻
        break;
    default:
        {
            char * pfile = (char*)index;
            //選中了最後的文件菜單項,pfile為 “d:\\1.avi” 字元串的指針
        }
        break;
    }

兩點註釋:

        (1)上面的代碼裡面的菜單項的選中標記,都是在菜單字元串裡面手工指定的,這時 nDefaultMode 和 nDefaultValue 指定為0。

        (2)上面代碼中的菜單項是在源代碼中硬編碼的,實際使用的時候可以動態生成,根據程式的狀態來組建菜單字元串,例如:

char szMenu[1024] = {0};
    
    int n = 0;

    if (value == 2)
        n += sprintf(szMenu + n, "^");

    n += sprintf(szMenu + n, "值2=2\n");

    if (value == 4)
        n += sprintf(szMenu + n, "^");

    n += sprintf(szMenu + n, "值4=4\n");

nDefaultMode=1時的示例

(1)模式1為相等模式 ( nDefaultMode = 1 ),當某個菜單項的數值等於輸入的 nDefaultValue 的時候,這個菜單項前面有選中標記

image

    int val = 32;        //nDefaultValue

    char szMenu[] = 
        "整數1=1\n"
        "整數20=20\n"
        "整數32=32\n"
        "整數0x99=0x99\n"
        ;

    //註意上面的菜單字元串裡面沒有選中標記

    //nDeaultMode = 1,當菜單項等於 nDefaultValue的時候顯示選中標記
    
    val = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 1, val);    

    //返回值為當前選中的菜單項對應的值,如果沒有選擇菜單,這個值保持原來的不變

nDefaultMode=2時的示例

        模式2為位模式 ( nDefaultMode = 2 ),當菜單項的數值所對應的位 與nDefaultValue位與的時候不為0,則菜單項前面顯示選中標記。

image

    DWORD flags = 0x82;        //當前的值 nDefaultValue 

    char szMenu[] = 
        "標記1=1\n"
        "標記2=2\n"
        "標記3=4\n"
        "標記4=8\n"
        "標記5=0x10\n"
        "標記6=0x20\n"
        "標記7=0x40\n"
        "標記8=0x80\n"
        ;
    //上面的菜單字元串內沒有選擇標記,程式自動根據 nDefaultValue  把對應的位加上選中標記
    //nDefaultMode = 2

    flags = (DWORD)auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 2, flags);
    //返回值就是flags,如果沒有選擇菜單項,那麼這個值不變

待續

        後續還要發表,《WIN 下的超級動態菜單(三)代碼》。

        可以在下麵的鏈接下載代碼和示常式序:

        http://files.cnblogs.com/files/tomview/dynamenu_20160524.rar


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 顯示結果: ID:1 ParentID: 0 TreeLevel: 0 Name:中國ID:2 ParentID: 1 TreeLevel: 1 Name:江西ID:5 ParentID: 2 TreeLevel: 2 Name:南昌ID:6 ParentID: 5 TreeLevel: 3 Nam ...
  • 直接在vs2013里的App_Data目錄創建資料庫,在伺服器資源管理器中查看時報錯: 未能載入包“Microsoft SQL Server Data Tools” 英文: 以下是右擊表的效果。 解決方案: 1.去https://msdn.microsoft.com/zh-cn/dn864412 下 ...
  • 今天在ASP.NET MVC項目中,實現一個小功能,就是記錄瀏覽者客戶端的一些信息。比如瀏覽者的IP,訪問了哪些頁面,以及瀏覽器相關的信息。在資料庫中創建一張表[VisitData]: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI ...
  • ...
  • 本文是Linux Shell系列教程的第(四)篇,更多shell教程請看:Linux Shell系列教程 與許多的編程語言一樣,Shell中也有註釋符號,今天就為大家來介紹下Shell中的註釋的語法及用法。 Shell中的註釋以“#”號開頭,所有以“#”號開頭的代碼都會被解釋器所忽略。 比如下麵的代 ...
  • 官方文檔給出了兩種Yii2的安裝方式。一種是通過歸檔文件安裝,另一種則是通過composer進行安裝。兩種方式具體有什麼不同呢?我們這裡不討論,安裝完了你自然也就明白了。 相信很多小伙伴想學Yii2,但是大部分都死在了開頭。所謂萬事開頭難,Yii2無疑更好的證實了這一點,還沒開始就先給你一棒槌。 安 ...
  • 利用介面做參數,寫個計算器,能完成+-*/運算 (1)定義一個介面Compute含有一個方法int computer(int n,int m); (2)設計四個類分別實現此介面,完成+-*/運算 (3)設計一個類UseCompute,含有方法:public void useCom(Compute c ...
  • 概述 GenEvent 是事件處理的通用部分的抽象。 通過 GenEvent ,我們給已有的服務 動態 的添加 事件處理。 GenEevent 和 GenServer 的區別 之前已經介紹了 GenServer ,GenServer 和 GenEvent 的主要區別在於: GenServer 是服務 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...