Skip to content

Instantly share code, notes, and snippets.

@CarsonSlovoka
Created November 15, 2022 03:15
Show Gist options
  • Select an option

  • Save CarsonSlovoka/4752ddc18064000d05d19f93ad24f02c to your computer and use it in GitHub Desktop.

Select an option

Save CarsonSlovoka/4752ddc18064000d05d19f93ad24f02c to your computer and use it in GitHub Desktop.
create popup menu
package main
import (
"github.com/CarsonSlovoka/go-pkg/v2/w32"
"log"
"syscall"
"unsafe"
)
func ExampleUser32DLL_CreatePopupMenu() {
user32dll := w32.NewUser32DLL()
gdi32dll := w32.NewGdi32DLL()
kernel32dll := w32.NewKernel32DLL()
var (
hIcon w32.HICON
iInfo w32.ICONINFO
)
{
hIcon, _ = user32dll.LoadIcon(0, w32.MakeIntResource(w32.IDI_QUESTION))
/*
hIcon = w32.HICON(user32dll.MustLoadImage(
0,
"testdata/img/golang.ico",
w32.IMAGE_ICON,
0, 0,
w32.LR_LOADFROMFILE|w32.LR_DEFAULTSIZE|w32.LR_SHARED,
))
*/
if !user32dll.GetIconInfo(hIcon, &iInfo) {
return
}
// Remember to release when you are not using the HBITMAP.
defer func() {
_ = gdi32dll.DeleteObject(w32.HGDIOBJ(iInfo.HbmColor))
_ = gdi32dll.DeleteObject(w32.HGDIOBJ(iInfo.HbmMask))
}()
}
// Create Menu
var hMenu w32.HMENU
{
hMenu = user32dll.CreatePopupMenu()
_, _ = user32dll.AppendMenu(hMenu, w32.MF_STRING, 1023, "Open")
var menuItemInfo w32.MENUITEMINFO
pMsg, _ := syscall.UTF16PtrFromString("Hello")
menuItemInfo = w32.MENUITEMINFO{
CbSize: uint32(unsafe.Sizeof(menuItemInfo)),
FMask: w32.MIIM_BITMAP |
w32.MIIM_ID |
w32.MIIM_STRING,
WID: 1024,
DwTypeData: pMsg,
HbmpItem: iInfo.HbmColor,
}
_, _ = user32dll.SetMenuItemInfo(hMenu, 1024, false, &menuItemInfo)
_, _ = user32dll.AppendMenu(hMenu, w32.MF_STRING, 1025, "Exit program")
defer func() {
if ok, errno := user32dll.DestroyMenu(hMenu); !ok {
log.Printf("%s\n", errno)
}
}()
}
ch := make(chan w32.HWND)
go func(chanWin chan<- w32.HWND) {
// define WNDPROC
wndProcFuncPtr := syscall.NewCallback(w32.WNDPROC(func(hwnd w32.HWND, uMsg w32.UINT, wParam w32.WPARAM, lParam w32.LPARAM) w32.LRESULT {
switch uMsg {
case w32.WM_DESTROY:
log.Println("WM_DESTROY")
user32dll.PostQuitMessage(0)
return 0
case w32.WM_RBUTTONDOWN:
log.Println("WM_RBUTTONDOWN")
// Show the menu
curHwnd := user32dll.GetForegroundWindow()
user32dll.SetForegroundWindow(curHwnd)
var pos w32.POINT
if ok, errno := user32dll.GetCursorPos(&pos); !ok {
fmt.Printf("%s", errno)
}
_, _ = user32dll.TrackPopupMenu(hMenu, w32.TPM_LEFTALIGN, pos.X, pos.Y, 0, curHwnd, nil)
_, _ = user32dll.PostMessage(curHwnd, w32.WM_NULL, 0, 0)
case w32.WM_COMMAND:
id := w32.LOWORD(uint32(wParam))
switch id {
case 1023:
log.Println("open")
case 1024:
log.Println("hello")
case 1025:
log.Println("1025")
_, _ = user32dll.PostMessage(hwnd, w32.WM_DESTROY, 0, 0)
}
}
return user32dll.DefWindowProc(hwnd, uMsg, wParam, lParam)
}))
const (
wndClassName = "classCreatePopupMenu"
wndWindowName = "windowCreatePopupMenu"
)
// Register
pUTF16ClassName, _ := syscall.UTF16PtrFromString(wndClassName)
hInstance := w32.HINSTANCE(kernel32dll.GetModuleHandle(""))
if atom, errno := user32dll.RegisterClass(&w32.WNDCLASS{
Style: w32.CS_HREDRAW | w32.CS_HREDRAW,
HbrBackground: w32.COLOR_WINDOW,
LpfnWndProc: wndProcFuncPtr,
HInstance: hInstance,
HIcon: hIcon,
LpszClassName: pUTF16ClassName,
}); atom == 0 {
fmt.Printf("%s", errno)
chanWin <- 0
return
}
// Create window
hwnd, errno := user32dll.CreateWindowEx(0,
wndClassName,
wndWindowName,
w32.WS_OVERLAPPEDWINDOW,
// Size and position
w32.CW_USEDEFAULT, w32.CW_USEDEFAULT, w32.CW_USEDEFAULT, w32.CW_USEDEFAULT,
0, // Parent window
0, // Menu
hInstance,
0, // Additional application data
)
if hwnd == 0 {
fmt.Printf("%s\n", errno)
if ok, errno2 := user32dll.UnregisterClass(wndClassName, hInstance); !ok {
fmt.Printf("Error UnregisterClass: %s", errno2)
}
chanWin <- hwnd
return
}
// Make sure it can be unregistered when exiting.
defer func() {
if ok, errno2 := user32dll.UnregisterClass(wndClassName, hInstance); !ok {
log.Printf("Error UnregisterClass: %s", errno2)
} else {
log.Println("OK UnregisterClass")
}
close(chanWin)
}()
chanWin <- hwnd
var msg w32.MSG
for {
if status, _ := user32dll.GetMessage(&msg, 0, 0, 0); status <= 0 {
break
}
user32dll.TranslateMessage(&msg)
user32dll.DispatchMessage(&msg)
}
}(ch)
hwnd := <-ch
user32dll.ShowWindow(hwnd, w32.SW_SHOW)
// wait user close the window
<-ch
// Output:
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment