The following is code generated using DeepSeek, which solves the issue of overlapping between the custom menu and the system context menu.
However, when used at the bottom-left or bottom-right corner of the desktop, the custom menu always appears at the top-right or top-left corner of the system menu, leaving the mouse pointer a bit far from the custom menu.
Is there a more concise way to implement this?
Macro Macro51
Trigger !v"" "#32768" /EXPLORER
However, when used at the bottom-left or bottom-right corner of the desktop, the custom menu always appears at the top-right or top-left corner of the system menu, leaving the mouse pointer a bit far from the custom menu.
Is there a more concise way to implement this?
Macro Macro51
Trigger !v"" "#32768" /EXPLORER

int hwnd=TriggerWindow
ARRAY(int) a; win("" "#32768" "explorer" 0 0 0 a); if(a.len>1) ret
SetTimer(0 0 100 &sub._Timer)
;
_s=
;1 open docx
;2 open other
_i=sub.ShowMenuSmart(hwnd _s)
out _i
#sub _Timer v
function u1 u2 timer u3
if !IsWindowVisible(a[0]) && !(RealGetKeyState(1) or RealGetKeyState(2))
,KillTimer 0 timer
,EndMenu
#sub CalcMenuWidth
function# str'menu
;; Estimate menu width (pixels), correctly calculate character display width
if(empty(menu)) ret 0
int maxDisplayWidth=0
str line
int i
foreach line menu
,int displayWidth=0
,int byteLen=line.len
,i=0
,rep
,,if(i>=byteLen) break
,,byte b=line[i]
,,if(b < 0x80) ;; ASCII character
,,,displayWidth=displayWidth+1
,,,i=i+1
,,else if(b >= 0xC0 and b < 0xE0) ;; 2-byte UTF-8 leading byte
,,,displayWidth=displayWidth+2
,,,i=i+2
,,else if(b >= 0xE0 and b < 0xF0) ;; 3-byte UTF-8 leading byte (Chinese, etc.)
,,,displayWidth=displayWidth+2
,,,i=i+3
,,else if(b >= 0xF0 and b < 0xF8) ;; 4-byte UTF-8
,,,displayWidth=displayWidth+2
,,,i=i+4
,,else
,,,;; Other cases, treat as 1
,,,displayWidth=displayWidth+1
,,,i=i+1
,if(displayWidth > maxDisplayWidth) maxDisplayWidth=displayWidth
;; Each unit width is about 8 pixels, plus left/right margin about 40
ret maxDisplayWidth*8+40
#sub NeedAvoidSystemMenu
function# int'hwnd str'menu
;; Check if system menu is too close to left/right screen edges and needs to be avoided
if(!hwnd) ret 0
if(empty(menu)) ret 0
RECT r
if(!GetWindowRect(hwnd &r)) ret 0
int desktop=GetDesktopWindow
int x y w h
if(!GetWinXY(desktop x y w h)) ret 0
int menuWidth=sub.CalcMenuWidth(menu)
if(menuWidth=0) menuWidth=300
;; System menu left edge too left, or right edge too right, and remaining space insufficient for custom menu width
if(r.left < menuWidth or w - r.right < menuWidth) ret 1
ret 0
#sub CalcMenuPos
function# int'hwnd str'menu POINT&p int&tpmFlags
;; Calculate menu popup position to avoid covering the system menu
;; Return 1 success, 0 failure
if(!hwnd) ret 0
if(empty(menu)) ret 0
RECT sysMenuRect
if(!GetWindowRect(hwnd &sysMenuRect)) ret 0
int desktop=GetDesktopWindow
int dx dy dw dh
if(!GetWinXY(desktop dx dy dw dh)) ret 0
;; Estimate menu size
int menuLines=numlines(menu)
int menuHeight=menuLines*22+10
int menuWidth=sub.CalcMenuWidth(menu)
if(menuWidth=0) menuWidth=300
;; Calculate available space
int rightSpace=dw-sysMenuRect.right
int leftSpace=sysMenuRect.left
int bottomSpace=dh-sysMenuRect.bottom
int topSpace=sysMenuRect.top
;; Prefer right side
if(rightSpace >= menuWidth)
,p.x=sysMenuRect.right
,p.y=sysMenuRect.top
,tpmFlags=0 ;; TPM_LEFTALIGN | TPM_TOPALIGN
,ret 1
;; Try left side
if(leftSpace >= menuWidth)
,p.x=sysMenuRect.left
,p.y=sysMenuRect.top
,tpmFlags=8 ;; TPM_RIGHTALIGN | TPM_TOPALIGN
,ret 1
;; Try bottom
if(bottomSpace >= menuHeight)
,p.x=sysMenuRect.left
,p.y=sysMenuRect.bottom
,tpmFlags=0 ;; TPM_LEFTALIGN | TPM_TOPALIGN
,ret 1
;; Try top
if(topSpace >= menuHeight)
,p.x=sysMenuRect.left
,p.y=sysMenuRect.top
,tpmFlags=32 ;; TPM_LEFTALIGN | TPM_BOTTOMALIGN
,ret 1
;; All directions insufficient, choose the direction with relatively more space
if(rightSpace > leftSpace)
,if(rightSpace > bottomSpace and rightSpace > topSpace)
,,p.x=sysMenuRect.right
,,p.y=sysMenuRect.top
,,tpmFlags=0
,,ret 1
,else
,,if(bottomSpace > topSpace)
,,,p.x=sysMenuRect.left
,,,p.y=sysMenuRect.bottom
,,,tpmFlags=0
,,,ret 1
,,else
,,,p.x=sysMenuRect.left
,,,p.y=sysMenuRect.top
,,,tpmFlags=32
,,,ret 1
else
,if(leftSpace > bottomSpace and leftSpace > topSpace)
,,p.x=sysMenuRect.left
,,p.y=sysMenuRect.top
,,tpmFlags=8
,,ret 1
,else
,,if(bottomSpace > topSpace)
,,,p.x=sysMenuRect.left
,,,p.y=sysMenuRect.bottom
,,,tpmFlags=0
,,,ret 1
,,else
,,,p.x=sysMenuRect.left
,,,p.y=sysMenuRect.top
,,,tpmFlags=32
,,,ret 1
#sub ShowMenuSmart
function# int'hwnd str'menu
;; Smart show menu: avoid when system menu near edge, otherwise use default
if(empty(menu)) ret 0
if(sub.NeedAvoidSystemMenu(hwnd menu))
,POINT p
,int tf
,if(sub.CalcMenuPos(hwnd menu p tf))
,,ret ShowMenu(menu 0 p 0 tf)
;; Default display: mouse position, right aligned
ret ShowMenu(menu 0 0 0 8)