Skip to content

Commit 4f99b87

Browse files
committed
Support rc-defined menus and demo
1 parent deed64a commit 4f99b87

File tree

8 files changed

+101
-21
lines changed

8 files changed

+101
-21
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ https://docs.microsoft.com/zh-cn/windows/win32/controls/window-controls
179179

180180
- [ ] Hot Key
181181
- [ ] Accelerator
182-
- [ ] Menu
182+
- [x] Menu
183183

184184
</details>
185185

examples/basic/main.go

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,33 +31,22 @@ func main() {
3131
log.Panic("main dialog create error", err)
3232
}
3333

34-
// Menu demo
35-
const (
36-
idMenuExit = 60001
37-
idMenuHello = 60002
38-
idMenuToggle = 60003
39-
)
40-
menu := wingui.NewMenu()
41-
fileMenu := wingui.NewPopupMenu()
42-
_ = fileMenu.AppendItem(idMenuExit, "Exit")
43-
_ = menu.AppendSubMenu(fileMenu, "File")
44-
45-
demoMenu := wingui.NewPopupMenu()
46-
_ = demoMenu.AppendItem(idMenuHello, "Hello MessageBox")
47-
_ = demoMenu.AppendItem(idMenuToggle, "Toggle Checked")
48-
_ = menu.AppendSubMenu(demoMenu, "Demo")
49-
34+
// Menu demo (menu loaded from ui.rc resource)
35+
menu := wingui.NewMenuFromResource(IDM_MAINMENU)
5036
_ = dlg.SetMenu(menu)
37+
demoMenu := menu.SubMenu(1)
5138
checked := false
5239
dlg.OnCommand = func(id uint16) {
5340
switch id {
54-
case idMenuExit:
41+
case IDM_FILE_EXIT:
5542
dlg.Close()
56-
case idMenuHello:
43+
case IDM_DEMO_HELLO:
5744
wingui.MessageBox(dlg.Handle(), "Hello from Menu", "Menu", win.MB_OK|win.MB_ICONINFORMATION)
58-
case idMenuToggle:
45+
case IDM_DEMO_TOGGLE:
5946
checked = !checked
60-
demoMenu.CheckItem(idMenuToggle, checked)
47+
if demoMenu != nil {
48+
demoMenu.CheckItem(IDM_DEMO_TOGGLE, checked)
49+
}
6150
}
6251
}
6352
dlg.SetIcon(IDI_ICON1)

examples/basic/resource.h.go

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/basic/ui.syso

210 Bytes
Binary file not shown.

examples/basic/ui/resource.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,8 @@
4646
#define IDC_TREE_EXPAND 40031
4747
#define IDC_TREE_COLLAPSE 40032
4848
#define IDC_TREE_LABEL 40033
49+
50+
#define IDM_MAINMENU 50000
51+
#define IDM_FILE_EXIT 50001
52+
#define IDM_DEMO_HELLO 50002
53+
#define IDM_DEMO_TOGGLE 50003

examples/basic/ui/ui.rc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
2929
IDD_DIALOG DIALOG 0, 0, 365, 188
3030
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_GROUP | WS_POPUP | WS_SYSMENU
3131
CAPTION "Dialog Hello"
32+
MENU IDM_MAINMENU
3233
FONT 8, "Ms Shell Dlg"
3334
{
3435
CONTROL "", IDC_TAB1, WC_TABCONTROL, 0, 197, 57, 160, 105, WS_EX_LEFT
@@ -82,6 +83,20 @@ FONT 8, "Ms Shell Dlg"
8283
LTEXT "Count: 0", IDC_TAB_LABEL_COUNT, 7, 76, 141, 9, SS_LEFT, WS_EX_LEFT
8384
}
8485

86+
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
87+
IDM_MAINMENU MENU
88+
{
89+
POPUP "&File"
90+
{
91+
MENUITEM "E&xit", IDM_FILE_EXIT
92+
}
93+
POPUP "&Demo"
94+
{
95+
MENUITEM "&Hello MessageBox", IDM_DEMO_HELLO
96+
MENUITEM "Toggle &Checked", IDM_DEMO_TOGGLE
97+
}
98+
}
99+
85100
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
86101
IDD_DIALOG_RICH DIALOG 0, 0, 153, 86
87102
STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW | WS_SYSMENU

menu.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,56 @@ import (
88
"github.com/whtiehack/wingui/winapi"
99
)
1010

11+
/*
12+
Manual menu creation example:
13+
14+
const (
15+
idExit = 60001
16+
idHello = 60002
17+
idToggle = 60003
18+
)
19+
20+
menu := wingui.NewMenu()
21+
fileMenu := wingui.NewPopupMenu()
22+
_ = fileMenu.AppendItem(idExit, "Exit")
23+
_ = menu.AppendSubMenu(fileMenu, "File")
24+
25+
demoMenu := wingui.NewPopupMenu()
26+
_ = demoMenu.AppendItem(idHello, "Hello MessageBox")
27+
_ = demoMenu.AppendItem(idToggle, "Toggle Checked")
28+
_ = menu.AppendSubMenu(demoMenu, "Demo")
29+
30+
_ = dlg.SetMenu(menu)
31+
32+
checked := false
33+
dlg.OnCommand = func(id uint16) {
34+
switch id {
35+
case idExit:
36+
dlg.Close()
37+
case idHello:
38+
wingui.MessageBox(dlg.Handle(), "Hello from Menu", "Menu", win.MB_OK|win.MB_ICONINFORMATION)
39+
case idToggle:
40+
checked = !checked
41+
demoMenu.CheckItem(idToggle, checked)
42+
}
43+
}
44+
*/
45+
1146
// Menu wraps a Win32 HMENU.
1247
type Menu struct {
1348
hMenu win.HMENU
1449
count uint32
1550
}
1651

52+
// NewMenuFromResource loads a menu resource by id (from the module hInstance).
53+
func NewMenuFromResource(id uintptr) *Menu {
54+
h := win.LoadMenu(hInstance, win.MAKEINTRESOURCE(id))
55+
if h == 0 {
56+
return nil
57+
}
58+
return &Menu{hMenu: h}
59+
}
60+
1761
// Handle returns the underlying HMENU.
1862
func (m *Menu) Handle() win.HMENU {
1963
if m == nil {
@@ -22,6 +66,18 @@ func (m *Menu) Handle() win.HMENU {
2266
return m.hMenu
2367
}
2468

69+
// SubMenu returns the submenu at the given position (0-based), or nil.
70+
func (m *Menu) SubMenu(pos int32) *Menu {
71+
if m == nil || m.hMenu == 0 {
72+
return nil
73+
}
74+
h := winapi.GetSubMenu(m.hMenu, pos)
75+
if h == 0 {
76+
return nil
77+
}
78+
return &Menu{hMenu: h}
79+
}
80+
2581
// Destroy releases the underlying HMENU.
2682
func (m *Menu) Destroy() bool {
2783
if m == nil || m.hMenu == 0 {

winapi/user32.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ var (
3131
switchToWindow = libuser32.NewProc("SwitchToThisWindow")
3232
sendMessageTimeout = libuser32.NewProc("SendMessageTimeoutW")
3333
trackPopupMenuEx = libuser32.NewProc("TrackPopupMenuEx")
34+
getSubMenu = libuser32.NewProc("GetSubMenu")
3435
)
3536

3637
// FindWindowEx user32 API FindWindowEx
@@ -88,3 +89,9 @@ func TrackPopupMenuEx(hMenu win.HMENU, flags uint32, x, y int32, hWnd win.HWND)
8889
)
8990
return uint32(ret)
9091
}
92+
93+
// GetSubMenu wraps user32!GetSubMenu.
94+
func GetSubMenu(hMenu win.HMENU, pos int32) win.HMENU {
95+
ret, _, _ := getSubMenu.Call(uintptr(hMenu), uintptr(pos))
96+
return win.HMENU(ret)
97+
}

0 commit comments

Comments
 (0)