 |
如果你得到了窗口句柄hWnd,就可以利用API的GetMenu函数获得菜单的句柄。使用GetSystemMenu可以获得窗口的系统菜单。
下面的例子,你可以将一个菜单添加到VFP的顶级窗体上。
PUBLIC frm
frm = CreateObject("Tform")
frm.Visible = .T.
DEFINE CLASS Tform As Form
PROTECTED hWindow, hMenu, hPopup, hSysPopup
Autocenter = .T.
ShowWindow = 2 && this is important
PROCEDURE Load
THIS.decl
PROCEDURE Init
STORE 0 TO THIS.hWindow, THIS.hMenu,;
THIS.hPopup, THIS.hSysPopup
PROCEDURE Destroy
* DestroyMenu is recursive,
* that is, it will destroy the menu and all its submenus.
= DestroyMenu (THIS.hMenu)
PROCEDURE Activate
IF THIS.hWindow = 0
THIS.InitMenu()
ENDIF
PROCEDURE InitMenu
#DEFINE MF_STRING 0
THIS.hWindow = GetFocus()
THIS.hSysPopup = GetSystemMenu (THIS.hWindow, 0)
THIS.hPopup = CreateMenu()
= AppendMenu (THIS.hPopup, MF_STRING, 1, "Option &1")
= AppendMenu (THIS.hPopup, MF_STRING, 1, "Option &2")
= AppendMenu (THIS.hPopup, MF_STRING, 1, "Option &3")
THIS.hMenu = CreateMenu()
THIS.AddMenuItem (THIS.hMenu, 0, "&Form", THIS.hPopup)
THIS.AddMenuItem (THIS.hMenu, 1, "&System", THIS.hSysPopup)
= SetMenu (THIS.hWindow, THIS.hMenu)
PROCEDURE AddMenuItem (hMenu, lnPosition, lcCaption, lnPopup)
*| typedef struct tagMENUITEMINFO {
*| UINT cbSize; 0:4
*| UINT fMask; 4:4
*| UINT fType; 8:4
*| UINT fState; 12:4
*| UINT wID; 16:4
*| HMENU hSubMenu; 20:4
*| HBITMAP hbmpChecked; 24:4
*| HBITMAP hbmpUnchecked; 28:4
*| ULONG_PTR dwItemData; 32:4
*| LPTSTR dwTypeData; 36:4
*| UINT cch; 40:4
*| HBITMAP hbmpItem; 44:4
*| } MENUITEMINFO, *LPMENUITEMINFO; total = 48 bytes
#DEFINE MENUITEMINFO_SIZE 48
#DEFINE MFT_STRING 0
#DEFINE MIIM_STATE 1
#DEFINE MIIM_ID 2
#DEFINE MIIM_SUBMENU 4
#DEFINE MIIM_TYPE 16
#DEFINE MFS_ENABLED 0
LOCAL lcMask, lcItemInfo, loCaption
loCaption = CreateObject ("PChar", lcCaption)
lcMask = MIIM_STATE + MIIM_ID + MIIM_TYPE + MIIM_SUBMENU
* fill MENUITEMINFO structure
lcItemInfo =;
num2dword(MENUITEMINFO_SIZE) +;
num2dword(lcMask) +;
num2dword(MFT_STRING) +;
num2dword(MFS_ENABLED) +;
num2dword(lnPosition) +;
num2dword(lnPopup) +;
num2dword(0) +;
num2dword(0) +;
num2dword(0) +;
num2dword(loCaption.GetAddr()) +;
num2dword(Len(lcCaption)) +;
num2dword(0)
= InsertMenuItem (hMenu, lnPosition, 1, @lcItemInfo)
RETURN
PROCEDURE decl
DECLARE INTEGER GetFocus IN user32
DECLARE INTEGER CreateMenu IN user32
DECLARE INTEGER CreatePopupMenu IN user32
DECLARE INTEGER DestroyMenu IN user32 INTEGER hMenu
DECLARE INTEGER SetMenu IN user32 INTEGER hWnd, INTEGER hMenu
DECLARE INTEGER GetSystemMenu IN user32 INTEGER hWnd, INTEGER bRevert
DECLARE INTEGER AppendMenu IN user32;
INTEGER hMenu, INTEGER uFlags,;
INTEGER uIDNewItem, STRING @lpNewItem
DECLARE INTEGER InsertMenuItem IN user32;
INTEGER hMenu, INTEGER uItem,;
INTEGER fByPosition, STRING @lpmii
ENDDEFINE
DEFINE CLASS PChar As Custom
PROTECTED hMem
PROCEDURE Init (lcString)
THIS.hMem = 0
THIS.setValue (lcString)
PROCEDURE Destroy
THIS.ReleaseString
FUNCTION getAddr && returns a pointer to the string
RETURN THIS.hMem
PROCEDURE setValue (lcString) && assigns new string value
#DEFINE GMEM_FIXED 0
THIS.ReleaseString
DECLARE INTEGER GlobalAlloc IN kernel32 INTEGER, INTEGER
DECLARE RtlMoveMemory IN kernel32 As Str2Heap;
INTEGER, STRING @, INTEGER
LOCAL lnSize
lcString = lcString + Chr(0)
lnSize = Len(lcString)
THIS.hMem = GlobalAlloc (GMEM_FIXED, lnSize)
IF THIS.hMem <> 0
= Str2Heap (THIS.hMem, @lcString, lnSize)
ENDIF
PROCEDURE ReleaseString && releases allocated memory
IF THIS.hMem <> 0
DECLARE INTEGER GlobalFree IN kernel32 INTEGER
= GlobalFree (THIS.hMem)
THIS.hMem = 0
ENDIF
ENDDEFINE
FUNCTION num2dword (lnValue)
#DEFINE m0 256
#DEFINE m1 65536
#DEFINE m2 16777216
LOCAL b0, b1, b2, b3
b3 = Int(lnValue/m2)
b2 = Int((lnValue - b3*m2)/m1)
b1 = Int((lnValue - b3*m2 - b2*m1)/m0)
b0 = Mod(lnValue, m0)
RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3)
此问题由李海回答。
附加关键字:编程, 源程序, programming, source code, FoxPro/Visual FoxPro, Foxbase, dBase, xbase, FoxPro, VFP, Visual FoxPro, 窗体与菜单, form, window, tform。
|