func defaultWndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) (result uintptr) { defer func() { if len(appSingleton.panickingPublisher.event.handlers) > 0 { var err error if x := recover(); x != nil { if e, ok := x.(error); ok { err = wrapErrorNoPanic(e) } else { err = newErrorNoPanic(fmt.Sprint(x)) } } if err != nil { appSingleton.panickingPublisher.Publish(err) } } }() if msg == notifyIconMessageId { return notifyIconWndProc(hwnd, msg, wParam, lParam) } wi := windowFromHandle(hwnd) if wi == nil { return win.DefWindowProc(hwnd, msg, wParam, lParam) } result = wi.WndProc(hwnd, msg, wParam, lParam) return }
func notifyIconWndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) (result uintptr) { // Retrieve our *NotifyIcon from the message window. ptr := win.GetWindowLongPtr(hwnd, win.GWLP_USERDATA) ni := (*NotifyIcon)(unsafe.Pointer(ptr)) switch lParam { case win.WM_LBUTTONDOWN: ni.publishMouseEvent(&ni.mouseDownPublisher, LeftButton) case win.WM_LBUTTONUP: ni.publishMouseEvent(&ni.mouseUpPublisher, LeftButton) case win.WM_RBUTTONDOWN: ni.publishMouseEvent(&ni.mouseDownPublisher, RightButton) case win.WM_RBUTTONUP: ni.publishMouseEvent(&ni.mouseUpPublisher, RightButton) win.SendMessage(hwnd, msg, wParam, win.WM_CONTEXTMENU) case win.WM_CONTEXTMENU: if ni.contextMenu.Actions().Len() == 0 { break } win.SetForegroundWindow(hwnd) var p win.POINT if !win.GetCursorPos(&p) { lastError("GetCursorPos") } actionId := uint16(win.TrackPopupMenuEx( ni.contextMenu.hMenu, win.TPM_NOANIMATION|win.TPM_RETURNCMD, p.X, p.Y, hwnd, nil)) if actionId != 0 { if action, ok := actionsById[actionId]; ok { action.raiseTriggered() } } return 0 } return win.DefWindowProc(hwnd, msg, wParam, lParam) }
// WndProc is the window procedure of the window. // // When implementing your own WndProc to add or modify behavior, call the // WndProc of the embedded window for messages you don't handle yourself. func (wb *WindowBase) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr { switch msg { case win.WM_ERASEBKGND: if wb.background == nil { break } canvas, err := newCanvasFromHDC(win.HDC(wParam)) if err != nil { break } defer canvas.Dispose() if err := canvas.FillRectangle(wb.background, wb.ClientBounds()); err != nil { break } return 1 case win.WM_LBUTTONDOWN, win.WM_MBUTTONDOWN, win.WM_RBUTTONDOWN: if msg == win.WM_LBUTTONDOWN && wb.origWndProcPtr == 0 { // Only call SetCapture if this is no subclassed control. // (Otherwise e.g. WM_COMMAND(BN_CLICKED) would no longer // be generated for PushButton.) win.SetCapture(wb.hWnd) } wb.publishMouseEvent(&wb.mouseDownPublisher, wParam, lParam) case win.WM_LBUTTONUP, win.WM_MBUTTONUP, win.WM_RBUTTONUP: if msg == win.WM_LBUTTONUP && wb.origWndProcPtr == 0 { // See WM_LBUTTONDOWN for why we require origWndProcPtr == 0 here. if !win.ReleaseCapture() { lastError("ReleaseCapture") } } wb.publishMouseEvent(&wb.mouseUpPublisher, wParam, lParam) case win.WM_MOUSEMOVE: wb.publishMouseEvent(&wb.mouseMovePublisher, wParam, lParam) case win.WM_SETCURSOR: if wb.cursor != nil { win.SetCursor(wb.cursor.handle()) return 0 } case win.WM_CONTEXTMENU: sourceWindow := windowFromHandle(win.HWND(wParam)) if sourceWindow == nil { break } x := win.GET_X_LPARAM(lParam) y := win.GET_Y_LPARAM(lParam) contextMenu := sourceWindow.ContextMenu() var handle win.HWND if widget, ok := sourceWindow.(Widget); ok { handle = ancestor(widget).Handle() } else { handle = sourceWindow.Handle() } if contextMenu != nil { win.TrackPopupMenuEx( contextMenu.hMenu, win.TPM_NOANIMATION, x, y, handle, nil) return 0 } case win.WM_KEYDOWN: wb.handleKeyDown(wParam, lParam) case win.WM_KEYUP: wb.handleKeyUp(wParam, lParam) case win.WM_SIZE, win.WM_SIZING: wb.sizeChangedPublisher.Publish() case win.WM_DESTROY: if wb.origWndProcPtr != 0 { // As we subclass all windows of system classes, we prevented the // clean-up code in the WM_NCDESTROY handlers of some windows from // being called. To fix this, we restore the original window // procedure here. win.SetWindowLongPtr(wb.hWnd, win.GWLP_WNDPROC, wb.origWndProcPtr) } delete(hwnd2WindowBase, hwnd) wb.window.Dispose() wb.hWnd = 0 } if wb.origWndProcPtr != 0 { return win.CallWindowProc(wb.origWndProcPtr, hwnd, msg, wParam, lParam) } return win.DefWindowProc(hwnd, msg, wParam, lParam) }