建立右键菜单

~RButton::   ; 右键启动
;ahk_class类名   以后就在这下面新建一行class , 由WinGetClass, Class名字, A 获得
Global Win_Explorer_Class1 := "AutoHotkeyGUI" ;要操作的class

WinGetClass, ClassCurrentWindow, A ; ;获取当前操作软件的ahk_class
If ( ClassCurrentWindow = Win_Explorer_Class1 ) or ( ClassCurrentWindow = Win_Explorer_Class2 ) ; 如果你现在操作的软件class等于你上面一行设置的class
	Goto Label_MenuContext_Explorer 
Return 
Label_MenuContext_Explorer: 
Global MenuContext_RightClickAgain := "-> MenuContext: Right Click Again instead of regular click <-" 
Global MenuContext_NoClicked_AddedItem := "-> MenuContext: Added items have not been clicked <-"
Global MenuContext_Separator := "-> MenuContext: Separator <-" 
Global MenuContext_Item := "-> MenuContext: Standard Item <-"
Global MenuContext_Submenu := "-> MenuContext: Popup Submenu <-"
;下面是添加右菜单
InsertItemsAtPosition := 2  ; 新添加的右菜单从第几行开始。
ArrayToAddItems := { } ; Object as array of items to add into the context menu
ArrayToAddItems.Push( Fct_MenuContext_Separator() )    ; 添加下划线
ArrayToAddItems.Push( Fct_MenuContext_Item( "第1个" ) ) ; 添加第一个
ArrayToAddItems.Push( Fct_MenuContext_Separator() )     ; 添加下划线
ArrayToAddItems.Push( Fct_MenuContext_Item( "第2个" ) )  ; 添加第二个
ArrayToAddItems.Push( Fct_MenuContext_Separator() )     ; 添加下划线
ArrayToAddItems.Push( Fct_MenuContext_Submenu( "第3个"   ; 这个有二级菜单
	,[ "第一个子菜单" 		; 1st Item
	, MenuContext_Separator 	; 下划线
	, "第二个子菜单"
	, MenuContext_Separator   ; 下划线
	, "第三个子菜单"
	, MenuContext_Separator   ; 下划线
	, "第四个子菜单" ] ) )   
TargetProgram_Classes := [ Win_Explorer_Class1, Win_Explorer_Class2 ]
; 下面是判断你点击了哪个菜单
ClickedItem := Fct_Get_ClickedItem_MenuContext_AddedItems( TargetProgram_Classes, InsertItemsAtPosition, ArrayToAddItems* )
If ( ClickedItem = MenuContext_RightClickAgain )
	Goto Label_MenuContext_Explorer ; When User do right click again, We must rebuild the items 
Else If ( ClickedItem = "第1个" ) {   ; 当你点击了第1个 
	MsgBox 你点击了第1个!
Return
}
Else If ( ClickedItem = "第2个" )   ; 当你点击了第2个
{
	MsgBox 你点击了第2个!
	Return
	}
Else If ( ClickedItem = "第一个子菜单" )   ; 当你点击了第一个子菜单
{
	MsgBox 你点击了第一个子菜单!
	Return
	}
Else If ( ClickedItem = "第二个子菜单" )   ; 当你点击了第二个子菜单
{
	MsgBox 你点击了第二个子菜单!
	Return
	}
Else If ( ClickedItem = "第三个子菜单" )   ; 当你点击了第三个子菜单
{
	MsgBox 你点击了第三个子菜单!
	Return
	}
Else If ( ClickedItem = "第四个子菜单" )   ; 当你点击了第四个子菜单
{
	MsgBox 你点击了第四个子菜单!
	Return
	}					
Else If ( SubStr( ClickedItem, 1, 2 ) =  "->")  ; 当点击了不是你创建的菜单,忽略掉
	Return
Else If ( ClickedItem = False )
Return 



Fct_MenuContext_Separator() {
	Return { Type: MenuContext_Separator }
}

Fct_MenuContext_Item( Name ) {
	Return { Type: MenuContext_Item, Name: Name }
}

Fct_MenuContext_Submenu( Name, ArraySubitems ) {
	Return { Type: MenuContext_SubMenu, Name: Name, Items: ArraySubitems }
}


; Writed by  Nico.Godvician  /  Code Opensource - CC: BY-NC-SA 2.0  –> Copy thsee lines
; Pubished:  2019/09/21 –> https://www.autohotkey.com/boards/viewtopic.php?f=76&t=38579&p=291014#p290862
; Function that add the items to the context menu, and return the clicked item
;*********************************************************************************************************
Fct_Get_ClickedItem_MenuContext_AddedItems( TargetProgram_Classes, InsertItemsAt_Position, ArrayOf_Items* ) 
;**********************************************************************************************************
{
	; Get handle of the target program:
	For each, ProgramClass in TargetProgram_Classes 
	{
		; Handle of active window:
		If Program_Handle := WinActive( "ahk_class " ProgramClass ) ; Handle return false if class it's not active
			Break ; Program is active, then OK
	} ; Or not if the loop ( for each ) is finished
	
	; Check we are really in the right active program:
	If not Program_Handle ; False or Handle
		Return "-> Not into the right program <-"	
	
	; Class #32768 is for all standard windows context menu:
	Global MenuContext_AhkClass := "ahk_class #32768" 
	
	; Wait context menu appears:
	WinWait, %MenuContext_AhkClass% ;
	
	; Context menu opened –> Get handle:
	MN_GETHMENU := 0x1E1 ; Shell Constant: "Menu_GetHandleMenu"
	SendMessage, MN_GETHMENU, False, False 
	MenuContext_Handle := ErrorLevel ; Return Handle in ErrorLevel
	
	
	;***************************
	; 	Section: Add Items:
	;***************************
	
	; Constants for menus in User32.dll:
	Static MF_SEPARATOR := 0x800
	Static MF_STRING := 0x0
	Static MF_POPUP := 0x10
	Static MF_BYPOSITION := 0x400 
	
	; Add each new item into the context menu:
	For each, ItemToAdd in ArrayToAdd_Items :=  ArrayOf_Items
	{
		; Save absolut position of this Item in the menu: 
		ItemToAdd.Position := InsertItemsAt_Position-1 + A_Index-1 ; Zero based
		
		; Add Separator:
		If ( ItemToAdd.Type == MenuContext_Separator ) 
		{
			; Insert Separator: –> https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-InsertMenuA
			DllCall( "User32\InsertMenu"
					,"UPtr", MenuContext_Handle
					,"UInt", ItemToAdd.Position ; At the specified position
					,"UInt", MF_SEPARATOR + MF_BYPOSITION
					,"UPtr", False
					,"UInt", False )
		}
		
		; Add Classic Item:
		Else If ( ItemToAdd.Type == MenuContext_Item )
		{
			; Insert text of item: –> https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-InsertMenuA
			DllCall( "User32\InsertMenu" 
					,"UPtr", MenuContext_Handle
					,"UInt", ItemToAdd.Position ; At the specified position
					,"UInt", MF_STRING + MF_BYPOSITION
					,"UPtr", False 
					,"Str", ItemToAdd.Name ) ; Insert Value ( text )
		}
		
		; Add Submenu and its Subitems:
		Else If ( ItemToAdd.Type == MenuContext_Submenu )
		{
			AddSubmenu := ItemToAdd ; Renames to clarify
			; Create Submenu, and return handle:
			AddSubmenu.Handle := DllCall( "User32\CreatePopupMenu" ) 
			
			; Insert Submenu into the context menu: –> https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-InsertMenuA
			DllCall( "User32\InsertMenu"
					,"UPtr", MenuContext_Handle
					,"UInt", AddSubmenu.Position  ; At the specified position
					,"UInt", MF_STRING + MF_BYPOSITION + MF_POPUP
					,"UPtr", AddSubmenu.Handle
					,"Str", AddSubmenu.Name )
			
			; Now add each Item and Separator into this Submenu:
			For each, ItemOfSubmenu in AddSubmenu.Items 
			{
				; AppendMenu –> https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-AppendMenuA
				
				; In case of Separator:
				If ( ItemOfSubmenu == MenuContext_Separator ) 
					DllCall( "User32\AppendMenu"
							,"UPtr", AddSubmenu.Handle
							,"UInt", MF_SEPARATOR
							,"UPtr", False, "UInt", False )
				
				Else  ; In case of Subintem: insert Value as text:
					DllCall( "User32\AppendMenu"
							,"UPtr", AddSubmenu.Handle
							,"UInt", MF_STRING
							,"UPtr", False
							,"Str", ItemOfSubmenu )
			}
		}
		Continue ; Continue to add next item...
	}
	; End for each add items
	
	
	;***************************
	; 	Section: Wait Click:
	;***************************
	
	Label_Wait_New_Click: ; When User clicks on Separator: wait new click
	
	; Wait User do a regular or right click:
	While not GetKeyState( "LButton" ) and not GetKeyState( "RButton" ) 
	{
		; Fix error if 2 right clicks are very too close: menu disappears sometimes for some apps:
		If not WinExist( MenuContext_AhkClass ) {
			Send {RButton} 	; Reopen context menu when disappears
			Return MenuContext_RightClickAgain ; Refill the menu 
		}
	}
	
	; Is it a right click on another file ? This means that the menu is closed and reopening...
	If GetKeyState( "RButton" )
		Return MenuContext_RightClickAgain ; Then refill the menu
	;TODO: Fix error when the User right-clicks on context menu, it's filled up again

	; Else Yes: Click into an item, but witch item ?
	
	
	;***********************************
	; 	Section: Get Clicked Item:
	;***********************************
	
	; Get position of mouse into screen:
	CoordMode, Mouse, Screen
	MouseGetPos, MouseScreenX, MouseScreenY  ; Int vars: 4 octets
	
	; POINT –> https://docs.microsoft.com/fr-fr/previous-versions/dd162805(v=vs.85)
	; Create a generic C++ POINT{x,y} with a 'ULongLong' –> 'Int64' 
	; X start at the 1st ULong (right), and Y start at 2nd ULong (32th bit on left):
	MousePointScreen := x := MouseScreenX  | y := ( MouseScreenY << 32 ) 
	
	;Calculate DPI of special screen:  1K, 2K, 4K, 8K, etc...
	WinDPIMultiplicator := A_ScreenDPI / 96  ; 96 is the standard DPI screen: 1K (1600x900)
	
	; Check if clicked item is into the new added items:
	For each, AddedItemInMenu in ArrayOfAdded_Items := ArrayOf_Items 
	{
		; Click on Separator –> Disable:
		If ( AddedItemInMenu.Type == MenuContext_Separator )
		{
			; Get Rectangle of Separator:
			VarSetCapacity( ItemRectangle, 16, 0 ) ; Create Rectangle of 16 octets: 4 corners of Int (4 octets)
			
			; Fill Rectangle: –> https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-GetMenuItemRect
			isFilledRectangle := DLLCall( "User32\GetMenuItemRect"
									,"UPtr", Program_Handle
									,"UPtr", MenuContext_Handle
									,"UInt", AddedItemInMenu.Position ; Absolut position in the context menu
									,"UPtr", &ItemRectangle )
			; Is clicked on separator ?
			If isFilledRectangle 
			and isPointIntoRectangle := DllCall( "User32\PtInRect", "UPtr", &ItemRectangle, "Int64", MousePointScreen )
				Goto Label_Wait_New_Click 
		}
		
		; Click on added Item –> Return Value
		Else If ( AddedItemInMenu.Type == MenuContext_Item ) 					
		{
			VarSetCapacity( ItemRectangle, 16, 0 )
			; https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-GetMenuItemRect
			isFilledRectangle := DLLCall( "User32\GetMenuItemRect"  
									,"UPtr", Program_Handle
									,"UPtr", MenuContext_Handle
									,"UInt", AddedItemInMenu.Position 
									,"UPtr", &ItemRectangle )
			If isFilledRectangle 
			and isPointIntoRectangle := DllCall( "User32\PtInRect", "UPtr", &ItemRectangle, "Int64", MousePointScreen ) 
				Return AddedItemInMenu.Name
		}
		
		; Click on Item of Submenu –> Check each Subitem:
		Else If ( AddedItemInMenu.Type == MenuContext_Submenu )  				
		{
			Loop 3 ; 3 times, because sometimes this function does not work 1 or 2 times:
				For each, ItemInSubmenu in ( ItemIsSubmenu := AddedItemInMenu ).Items 
				{
					ItemPositionInMenu := A_Index
					
					; Get Rectangle for Subitem
					VarSetCapacity( ItemRectangle, 16, 0 ) 
					; https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-GetMenuItemRect
					isFilledRectangle := DLLCall( "User32\GetMenuItemRect"  
											,"UPtr", False ; Indicate Submenu, instead of window
											,"UPtr", ItemIsSubmenu.Handle ; Handle of the Submenu
											,"UInt", ItemPositionInMenu -1 ; Zero based
											,"UPtr", &ItemRectangle )
					
					; Get each corner of Rectangle:
					ItemRectangleX1 := NumGet( &ItemRectangle, 0, "Int" ) ; Int –> 4 octets
					ItemRectangleY1 := NumGet( &ItemRectangle, 4, "Int" )
					ItemRectangleX2 := NumGet( &ItemRectangle, 8, "Int" )
					ItemRectangleY2 := NumGet( &ItemRectangle, 12, "Int" )
					
					; Use DPI multiplicator for special screen (2K, 4K, ...):
					isMouseInto4Corners :=  ( MouseScreenX >= ItemRectangleX1 *WinDPIMultiplicator ) 
									and ( MouseScreenX <= ItemRectangleX2 *WinDPIMultiplicator ) 
									and ( MouseScreenY >= ItemRectangleY1 *WinDPIMultiplicator ) 
									and ( MouseScreenY <= ItemRectangleY2 *WinDPIMultiplicator ) 
					
					;ToolTip % "isFilledRectangle: " isFilledRectangle "`n" "isMouseInto4Corners: " isMouseInto4Corners "`nX: " ItemRectangleX1*WinDPIMultiplicator "<" MouseScreenX ">" ItemRectangleX2*WinDPIMultiplicator "`nY: " ItemRectangleY1*WinDPIMultiplicator "<" MouseScreenY ">" ItemRectangleY2*WinDPIMultiplicator, , , 5
					
					; Check if mouse is into this Rectangle: 
					If isFilledRectangle and isMouseInto4Corners
					{
						; Click on Separator ?
						If ( ItemInSubmenu == MenuContext_Separator ) ; Disable Separator:
							Goto Label_Wait_New_Click ; Wait new click
						
						Else ; Standard text Subitem: 
							Return ItemInSubmenu ; Return value of item
					}
				}
		}
		; End of one item: this is not this item
		Continue ; Then check next item...
	}
	; End: For all the new items, all checked without return
	
	; Then clicked Item is probably on another item of context menu ( like 'Open' ):
	Return MenuContext_NoClicked_AddedItem
}
;End Fct_Get_ClickedItem_MenuContext_AddedItems

给TA捐赠
共{{data.count}}人
人已捐赠
其他

检查时间是否正确并调整

2021-12-2 15:57:02

其他应用

剑灵UE4读取XML坐标2021-9-5(带基本用法)

2021-12-2 15:57:15

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索