【PB案例學習筆記】-28制作一個右鍵菜單

寫在前面

這是PB案例學習筆記系列文章的第28篇,該系列文章適合具有一定PB基礎的讀者。

通過一個個由淺入深的編程實戰案例學習,提高編程技巧,以保證小伙伴們能應付公司的各種開發需求。

文章中設計到的源碼,小凡都上傳到了gitee代碼倉庫https://gitee.com/xiezhr/pb-project-example.git

gitee代碼倉庫

需要源代碼的小伙伴們可以自行下載查看,后續文章涉及到的案例代碼也都會提交到這個倉庫【pb-project-example

如果對小伙伴有所幫助,希望能給一個小星星?支持一下小凡。

一、小目標

基本上所有的應用程序在點擊鼠標右鍵之后都會彈出一個菜單,本案例我們將使用PB實現這個功能。通過鼠標右鍵,彈出一個命令菜單,

菜單上包含“剪切”、“復制”、“粘貼”、“加粗”等操作標識。這在日常開發中是一個非常常見的功能,一定要學會哈。

最終效果如下所示

右鍵菜單

二、實現思路

我們將通過引用user32.dll中的GetMenuGetSubMenuTrackPopupMenuGetSystemMetrics等窗體操作函數和LoadImageA

SetMenuItemBitmaps等圖形顯示函數來實現相關功能。具體函數功能如下

GetMenu函數

用于獲取與特定窗口關聯的菜單句柄

函數原型:

HMENU GetMenu(HWND hWnd);

參數說明:

hWnd: 一個窗口句柄,指定了要查詢其菜單的窗口。

返回值:

成功時,返回窗口的菜單句柄(HMENU)。如果沒有菜單關聯到該窗口,則返回NULL。

GetSubMenu函數

用于從主菜單中獲取指定位置的子菜單

函數原型:

HMENU GetSubMenu(HMENU hMenu, int nPos);

參數說明:

  • hMenu: 主菜單的句柄,即之前通過GetMenu或其他方式獲得的菜單句柄。
  • nPos: 一個整數,表示要獲取的子菜單在其父菜單中的位置索引,其中0通常是第一個子菜單(頂級菜單項)。

返回值

成功時,返回指定位置的子菜單句柄(HMENU)。如果索引無效或沒有子菜單,則返回NULL。

TrackPopupMenu函數

用于在一個指定的位置顯示一個彈出式菜單,并跟蹤用戶的選擇。

函數原型:

BOOL TrackPopupMenu(HMENU hMenu,UINT uFlags,int x,int y,int nReserved,HWND hWnd,CONST RECT* prcRect
);

參數說明:

  • hMenu: 要顯示的彈出菜單的句柄。
  • uFlags: 控制菜單顯示方式的標志,如TPM_LEFTALIGNTPM_RIGHTBUTTON等。
  • x, y: 菜單左上角的屏幕坐標,相對于屏幕原點或指定窗口客戶區。
  • nReserved: 在舊版本中保留,應設為0。
  • hWnd: 與菜單顯示相關的窗口句柄,用于消息處理。
  • prcRect(舊版)/lptpm(新版,包含x, y, flags, rect等更詳細信息的結構體): 用于指定額外的顯示參數或限制區域。

返回值:

如果用戶選擇了菜單項并成功處理,返回非零值;否則,返回0。通常需要檢查GetLastError來確定失敗原因。

GetSystemMetrics函數

用于獲取有關當前系統的各種度量信息和配置設置。這些信息涵蓋了顯示器分辨率、顏色深度、鼠標和鍵盤狀態、操作系統版本特性等多個方面。

函數原型:

int GetSystemMetrics(int nIndex);

參數說明:

nIndex: 一個整型參數,作為索引值,指定了想要獲取的系統度量信息類型。不同的索引值對應不同的系統配置或狀態信息。

返回值:

函數根據nIndex所指定的索引值,返回相應的系統度量信息值。返回值類型通常是整數。

LoadImageA函數

用于加載光標、圖標、位圖或圖元文件資源。

函數原型:

HANDLE LoadImageA(HINSTANCE hinst,LPCSTR lpszName,UINT uType,int cxDesired,int cyDesired,UINT fuLoad
);

參數說明:

  • hinst: 一個模塊實例句柄,通常為NULL以加載系統資源,或指定的DLL句柄來加載該DLL中的資源。
  • lpszName: 指向資源名稱(文件名或資源ID,如圖標ID)的指針,可以是字符串或整數資源ID(需要轉換為LPCTSTR)。
  • uType: 指定要加載的圖像類型,可以是IMAGE_BITMAP, IMAGE_ICON, IMAGE_CURSOR, 或 IMAGE_ENHMETAFILE
  • cxDesired, cyDesired: 指定希望加載圖像的寬度和高度(以像素為單位)。如果為0,則使用圖像的實際大小。
  • fuLoad: 加載標志,如LR_CREATEDIBSECTION, LR_LOADFROMFILE, LR_DEFAULTSIZE等,用于控制加載行為。

返回值:

成功時返回圖像句柄(HBITMAP, HCURSOR, HICON, 或 HENHMETAFILE),失敗則返回NULL。

SetMenuItemBitmaps函數

用于設置菜單項的位圖圖像的API,可以為菜單項的正常狀態和選中(或按下)狀態指定不同的位圖

函數原型:

BOOL SetMenuItemBitmaps(HMENU hMenu,UINT uPosition,UINT uFlags,HBITMAP hBitmapUnchecked,HBITMAP hBitmapChecked
);

參數說明:

  • hMenu: 要修改的菜單的句柄。
  • uPosition: 要設置位圖的菜單項的位置索引,從0開始計數。
  • uFlags: 指定要設置哪一組位圖的標志,可以是MF_BYCOMMAND(基于菜單項的ID查找)或MF_BYPOSITION(直接使用位置索引)。
  • hBitmapUnchecked: 未選中狀態下菜單項的位圖句柄。
  • hBitmapChecked: 選中或按下狀態下菜單項的位圖句柄。

返回值:

函數執行成功返回非零值,失敗返回0。可以通過GetLastError獲取詳細的錯誤信息

三、創建程序基本框架

① 新建examplework工作區

② 新建exampleapp應用

③ 新建w_main窗口,將其Title設置為"右鍵菜單"

由于文章篇幅原因,以上步驟不再贅述,如果忘記了的小伙伴可以翻一翻該系列第一篇文章復習一下

④ 新建w_popmenu窗口

⑤ 在w_mian窗口中布局控件

新建一個MultiLineEdit控件和一個CommandButton控件,名稱分別為mle_1cb_1,調整控件布局,

并將cb_1Text設置為"關閉"

控件布局

⑥ 設置w_popmenu窗口屬性

w_popmenu窗口縮小成一個小方塊,并在MenuName屬性欄中添加菜單m_popmenu

⑦ 保存w_popmenu窗口

w_popmenu窗口

⑧ 新建m_popmenu菜單如下圖所示

新建菜單

四、編寫代碼

① 在w_main窗口中定義實例變量,代碼如下

ulong il_popmenu_window_hwnd

② 在w_main窗口中定義外部函數

FUNCTION ulong GetMenu(ulong hwnd) LIBRARY "user32.dll"FUNCTION ulong GetSubMenu(ulong hMenu,ulong nPos) LIBRARY "user32.dll"FUNCTION ulong TrackPopupMenu(ulong hMenu,ulong wFlags,ulong x,ulong y,ulong nReserved,ulong hwnd,ref Rect lprc) LIBRARY "user32.dll"

③ 在w_main窗口的Open中添加如下代碼

open(w_popmenu)il_popmenu_window_hwnd = handle(w_popmenu)

④ 在w_main窗口的close事件中添加如下代碼

close(w_popmenu)

⑤ 在mle_1控件的rbuttondown事件中輸入如下代碼

ulong hmenu,hsubmenu,hwnd
integer li_x,li_yRECT l_rect
l_rect.left = 0
l_rect.top = 0
l_rect.right = 0
l_rect.bottom = 0hmenu = getmenu(il_popmenu_window_hwnd)
hsubmenu = getsubmenu(hmenu, 0)li_x = (xpos + parent.x) / 5
li_y = (ypos + parent.y) / 5TrackPopupMenu(hsubMenu, 2, li_x, li_y, 0, il_popmenu_window_hwnd, l_rect)

⑥ 在cb_1按鈕的clicked中添加如下代碼

close(parent)return 0

⑦ 在w_popmenu窗口中定義實例變量

//Win32
CONSTANT Integer IMAGE_BITMAP	   = 0
CONSTANT Integer LR_LOADFROMFILE = 16
CONSTANT Integer SM_CXMENUCHECK  = 71
CONSTANT Integer SM_CYMENUCHECK	= 72
CONSTANT Integer MF_BITMAP			= 4
CONSTANT Integer MF_BYPOSITION	= 1024

⑧ 在w_popmenu窗口中定義外部函數

FUNCTION ulong LoadImageA(ulong hintance, string filename,uint utype,int x,int y,uint fload)  LIBRARY "USER32.DLL"FUNCTION boolean SetMenuItemBitmaps(ulong hmenu,uint upos,uint flags,ulong handle_bm1,ulong handle_bm2)  LIBRARY "USER32.DLL"FUNCTION int GetSystemMetrics(  int nIndex ) LIBRARY "USER32.DLL"FUNCTION int GetSubMenu(ulong hMenu,int pos) LIBRARY "USER32.DLL"FUNCTION ulong GetMenu(ulong hWindow) LIBRARY "USER32.DLL"

⑨ 在w_popmenu窗口的open事件中添加如下代碼并準備圖片

準備圖片

**注:**圖片資源會一起推送到gitee倉庫,需要圖片資源的小伙伴克隆倉庫即可獲取

long		ll_MainHandle
long		ll_SubMenuHandle
long		ll_X
long		ll_Y
long		ll_Bitmapcut
long		ll_Bitmapcopy
long		ll_Bitmappaste
long		ll_Bitmapitl
long 		ll_bitmapcnt
long		ll_bitmapunderlinethis.visible = falsell_MainHandle = GetMenu(Handle(this))ll_SubMenuHandle = GetSubMenu(ll_MainHandle,0)ll_x = GetSystemMetrics(SM_CXMENUCHECK) 
ll_y = GetSystemMetrics(SM_CYMENUCHECK) ll_Bitmapcut = LoadImageA(0,'cut.bmp',  IMAGE_BITMAP ,ll_x,ll_y,LR_LOADFROMFILE)
ll_Bitmapcopy = LoadImageA(0,'copy.bmp',  IMAGE_BITMAP ,ll_x,ll_y,LR_LOADFROMFILE)
ll_Bitmappaste = LoadImageA(0,'paste.bmp',  IMAGE_BITMAP ,ll_x,ll_y,LR_LOADFROMFILE)
ll_Bitmapitl = LoadImageA(0,'itl.bmp',  IMAGE_BITMAP ,ll_x,ll_y,LR_LOADFROMFILE)
ll_Bitmapcnt = LoadImageA(0,'big.bmp',  IMAGE_BITMAP ,ll_x,ll_y,LR_LOADFROMFILE)
ll_bitmapunderline = LoadImageA(0,'ul.bmp',  IMAGE_BITMAP ,ll_x,ll_y,LR_LOADFROMFILE)SetMenuItemBitmaps(ll_SubMenuHandle,0,MF_BYPOSITION,ll_Bitmapcut,ll_Bitmapcut)
SetMenuItemBitmaps(ll_SubMenuHandle,1,MF_BYPOSITION,ll_Bitmapcopy,ll_Bitmapcopy)
SetMenuItemBitmaps(ll_SubMenuHandle,2,MF_BYPOSITION,ll_Bitmappaste,ll_Bitmappaste)
SetMenuItemBitmaps(ll_SubMenuHandle,4,MF_BYPOSITION,ll_Bitmapitl,ll_Bitmapitl)
SetMenuItemBitmaps(ll_SubMenuHandle,5,MF_BYPOSITION,ll_Bitmapcnt,ll_Bitmapcnt)
SetMenuItemBitmaps(ll_SubMenuHandle,6,MF_BYPOSITION,ll_Bitmapunderline,ll_Bitmapunderline)

⑩ 在開發界面左邊的SystemTree窗口中雙擊exampleapp應用對象,并在其open事件中添加如下代碼

open(w_main)

五、運行程序

經過一波代碼編寫之后,我們來驗證下結果

右鍵菜單

本期內容到這兒就結束了★,°:.☆( ̄▽ ̄)/$:.°★ 。 希望對您有所幫助

我們下期再見 ヾ(?ω?`)o (●’?’●)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/39177.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/39177.shtml
英文地址,請注明出處:http://en.pswp.cn/web/39177.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

任天堂稱未來第一方游戲不會使用生成式AI

雖然EA、育碧、暴雪、Embracer等西方游戲廠商都大力支持生成式AI技術,但日本老牌游戲公司任天堂并不會追隨這一步伐。任天堂已經確認該公司未來的第一方游戲不會使用生成式AI技術。 在公司最近的投資人問答會上,任天堂描繪了公司未來游戲愿景。在談到AI技…

安徽農業大學學報

《安徽農業大學學報》是安徽農業大學主辦,國內外公開發行的綜合性農業科學類學術期刊,主要刊登茶葉科學、動植物遺傳育種、作物栽培、植物保護、林學、動物科學與動物醫學、水產科學、生物學、土壤學、農業生態與環境科學、園藝學、食品科學、農業機械工…

Oracle PL / SQL變量值

常量 要聲明常量,請在類型說明符之前放入關鍵字CONSTANT。 常量必須在其聲明中初始化。 每次輸入塊或子程序時,都會初始化常量。 以下代碼顯示如何定義REAL類型的常量,并為常量指定一個不可更改的值5。 DECLARE n_real CONSTANT RE…

51單片機第27步_單片機工作在睡眠模式

重點學習51單片機工作在睡眠模式。 1、進入“睡眠模式”的方法 通過將PCON寄存器中的PDWN置1,則CPU會進入“睡眠模式”。在“睡眠模式”中,晶振將停止工作,因此,定時器和串口都將停止工作,只有外部中斷繼續工作。如果單片機電源…

LeetCode——第 404 場周賽

周賽 三角形的最大高度 給你兩個整數 red 和 blue,分別表示紅色球和藍色球的數量。你需要使用這些球來組成一個三角形,滿足第 1 行有 1 個球,第 2 行有 2 個球,第 3 行有 3 個球,依此類推。 每一行的球必須是 相同 …

Go語言--自定義函數

定義格式 函數構成代碼執行的邏輯結構。在 Go語言中,兩數的基本組成為:關鍵字 func、函數名、參數列表、返回值、所數體和返回語句。 函數定義說明: func:函數由關鍵字func開始聲明FuncName:函數名稱,根據約定,數名首字母小寫即為private…

淺談 Linux 中的 core dump 分析方法

文章目錄 一、什么是 core dump二、發生 core dump 的原因1. 空指針或非法指針引起 core dump2. 數組越界或指針越界引起的 core dump3. 數據競爭導致 core dump4. 代碼不規范 三、core dump 分析方法1. 啟用 core dump2. 觸發 core dump2-1. 因空指針解引用而崩潰2-2. 通過 SI…

圖形編輯器基于Paper.js教程06:鼠標畫圓與橢圓

繪制橢圓與圓形:利用Paper.js進行交互式圖形設計 在Web應用中實現交互式圖形繪制功能,對于提高用戶體驗至關重要,尤其是在設計和藝術相關的應用中。Paper.js是一款強大的JavaScript庫,專門用于處理矢量圖形,它提供了一…

智能語音門鎖:置入NV170D語音芯片ic 打造便捷生活新體驗

一、智能門鎖語音芯片開發背景 隨著科技的飛速發展,傳統門鎖的局限性日益凸顯,無法滿足現代人對高效、安全生活的需求。在這樣的時代背景下,智能門鎖應運而生,它不僅繼承了傳統門鎖的基本功能,更通過融入先進的科技元素…

商標的近似分辯,商標起名稱時注意!

曾有過網友發來商標名稱,普推知商標老楊說有近似,然后網友起過新名稱還是存有近似,或者加字,后面加的通用詞,與先有商標名稱也是近似。 “良信健康”這個名稱健康是行業通用詞,加成健康后變成四個字&#x…

出現 images and labels...0 found, xx missing, 0 empty, 0 corrupt 解決方法

目錄 1. 問題所示2. 原理分析3. 解決方法1. 問題所示 訓練VOC的數據的時候出現如下問題: val: Scanning /home/l228/huoyanhao/yolov5/datasets/VOC/images/VOCdevkit/VOC2007/2007_val images and labels...0 found, 2510 missing, 0 empty, 0 corrupt: 100%|███████…

HTTP協議深入

1.了解web和網絡基礎 有客戶端和服務端雙方參與交互 客戶端發送請求:request 服務端根據請求給出響應:response 請求通過URL來指定要獲取都得資源 響應內容可以是HTML網頁,或者用json表示的數據或者其他二進制文件內容 Web使用一種名為HTTP的協議作為規范&…

jEasyUI 添加分頁組件

jEasyUI 添加分頁組件 jEasyUI(jQuery EasyUI)是一個基于jQuery的用戶界面插件集合,它為用戶提供了一系列的UI組件,如菜單、窗口、數據網格等,以簡化Web頁面的開發。分頁組件是jEasyUI中的一個重要部分,它允許用戶在處理大量數據時,將數據分頁顯示,提高用戶體驗和數據…

AI與大模型工程師證書研修班報名啦!

人工智能大模型是指擁有超大規模參數(通常在十億個以上)、超強計算資源的機器學習模型,能夠處理海量數據,完成各種復雜任務,如自然語言處理、圖像識別等。計算機硬件性能不斷提升,深度學習算法快速優化&…

ESP32CAM物聯網教學03

ESP32CAM物聯網教學03 物聯網小車 小智突發奇想:要是我在點燈物聯APP中多增加幾個按鈕,控制小車的行駛方向,不就可以做成遙控小車了嗎? 點燈物聯控制小車的行駛方向 我們可以重新編輯點燈物聯APP中的設備控件界面,如…

自定義控件之動畫篇(六)——聯合動畫的代碼及xml實現

在Android中,聯合動畫(即組合多種類型的動畫)可以通過編寫Java/Kotlin代碼或XML資源文件來實現。這里我們將分別展示如何通過這兩種方式來實現一個簡單的自定義控件動畫,該動畫將包含平移和縮放效果。 1. XML 資源文件實現 首先…

AI學習指南機器學習篇-梯度提升樹模型應用與Python實踐

AI學習指南機器學習篇-梯度提升樹模型應用與Python實踐 機器學習領域中的梯度提升樹(Gradient Boosting Tree)模型是一種非常強大且廣泛應用的模型,它在各種數據類型和問題類型上都表現出色。在本篇博客中,我們將介紹如何使用Pyt…

開關電源中強制連續FCCM模式與輕載高效PSM,PFM模式優缺點對比筆記

文章目錄 前言一、連續FCCM模式優點:缺點: 二,輕載高效PSM,PFM優點:缺點: 總結 前言 今天我們來學習下開關電源中,強制連續FCCM模式與輕載高效PSM,PFM模式優缺點對比 一、連續FCCM模式 優點: …

mac中如何恢復因為破解腳本導致的IDEA無法啟動的問題

問題 為了在mac中安裝免費的2024版idea,導致下載了一個腳本,使用這個腳本后,但是發現idea還沒有破解,相反導致idea無法啟動,每次點擊,都會彈出“cannot start IDE…” 問題排查 在訪達中點擊mac的應用程…

docker -run hello-world超時

主要原因就是嘗試拉取庫的時候沒有從阿里云鏡像里拉&#xff0c;所以設置一下就好了 這里使用的是ubuntu系統&#xff08;命令行下逐行敲就行了&#xff09; sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": [&quo…