System Menu : Add custom and/or remove standard items

Post your working scripts, libraries and tools
User avatar
SKAN
Posts: 661
Joined: 29 Sep 2013, 16:58

System Menu : Add custom and/or remove standard items

19 Dec 2013, 00:15

  • Image

Code: Select all

/*
     __    __  __          __ __       __    __                 _       __                   
    / /_  / /_/ /_____  _ / // /____ _/ /_  / /________________(_)___  / /_ ____  _______
   / __ \/ __/ __/ __ \(_) // // __ '/ __ \/ //_/ ___/ ___/ __/ / __ \/ __// __ \/ __/ _ \
  / / / / /_/ /_/ /_/ / / // // /_/ / / / / ,< (__  ) /__/ / / / /_/ / /__/ /_/ / / / // / 
 /_/ /_/\__/\__/ .___(_) // / \__,_/_/ /_/_/|_/____/\___/_/ /_/ .___/\__(_)____/_/  \__ /  
              /_/     /_//_/                                 /_/                   (___/   
              
  Script  :  System Menu : Add custom and/or remove standard items  
  Author  :  SKAN ( [email protected] ),  Created: 19-Dec-2013 
  Topic   :  http://ahkscript.org/boards/viewtopic.php?p=7630#p7630
  
*/


#SingleInstance, Off
#NoTrayIcon
SetWorkingDir %A_ScriptDir%
Menu, Tray, UseErrorLevel
Menu, Tray, Icon, inetcpl.cpl, 50
Menu, Tray, NoStandard
Menu, Tray, Add, &Show, ShowHideGUI
Menu, Tray, Add, E&xit, GuiClose
Menu, Tray, Default, &Show
Menu, Tray, Click, 1

OnMessage( 0x112, "WM_SYSCOMMAND" )

SysMenuItems=
( LTrim Comments 
  -----------------------------
  "Always On &Top",        1025
  "&Minimize to TNA",      1026
  "&ListVars",           130943 ; 130943 = 0x10000|65407 > Add 0x10000 for new menu column
  "&Help",                65411
  -----------------------------
  "&Window Spy",          65402
  "&Reload",              65400
  "&Edit",                65401
  -----------------------------
  "&Suspend Hotkeys",     65404
  "&Pause",               65403                                  
  -----------------------------
  "E&xit",                65405
)

Gui +LastFound 
hGui1 := WinExist()
hSysMenu := Menu_SetSysMenu( hGui1, SysMenuItems, "Reset" )
Menu_CheckItem( hSysMenu, 1026, False, 1 )
Gui, Show, W400 h300, Demo :: Menu_SetSysMenu()
Return

ShowHideGUI:
  Gui,  Show, % IsVis := DllCall( "IsWindowVisible", UInt,hGui1 )  ?  "Hide" : ""
  Menu, Tray, % IsVis ? "Icon" : "NoIcon"
  TrayTip,,   % IsVis ? "Windows was minimized to TNA`nClick Icon to unhide" : ""  
Return

GuiClose:
 ExitAPP

WM_SYSCOMMAND(  wParam, lParam, Msg, hWnd ) {      ; WM_SYSCOMMAND()         goo.gl/kDL6uM

 hSysMenu := Menu_SetSysMenu( hWnd )               ; Get a Handle to SYSMENU
                                                   
 If wParam in 1025,1026,65403,65404                ; Items that require checkmark toggle
    Menu_CheckItem( hSysMenu, wParam, False, -1 )  ; Toggle Checkmark

 If ( wParam >= 65400 )  {               ; One of AHK commands, so repost it as WM_COMMAND
    DllCall( "PostMessage", UInt,hWnd, UInt,0x111, UInt,wParam, UInt,0 )
    Return 0                                       
 }  

 If ( wParam = 1025 ) {
    WinSet, AlwaysOnTop, Toggle, ahk_id %hWnd%
    Return 0
 }

 SC := wParam & 0xFFF0                             ; Ignore 4 low-order bits of the wParam

 If ( SC = 0xF020 ) ; SC_MINIMIZE
    If Menu_GetState( hSysMenu, 1026, False ) {  
      SetTimer, ShowHideGUI, -1
      Return 0
    }

}


Menu_CheckItem( hMenu, ItemRef=0, ByPos=1, CheckState=1 ) {
Static MF_BYCOMMAND := 0, MF_BYPOSITION := 0x400,   MF_CHECKED := 0x8, MF_UNCHECKED := 0

  Flag    := ByPos ? MF_BYPOSITION : MF_BYCOMMAND,     
  ItemRef := ItemRef - ( ByPos ? 1 : 0 ) 
 
  Flag |= ( !CheckState     ) ? MF_UNCHECKED            ;   GetMenuState()   goo.gl/SjVKK8 
       :  (  CheckState > 0 ) ? MF_CHECKED 
       :  (  DllCall( "GetMenuState", UInt,hMenu, UInt,ItemRef, UInt,Flag ) & MF_CHECKED 
                                                             ? MF_UNCHECKED : MF_CHECKED )

Return DllCall( "CheckMenuItem", UInt,hMenu, UInt,ItemRef, UInt,Flag ) ;     goo.gl/L4FlQy
}


Menu_GetState( hMenu, ItemRef=0, ByPos=1, MF=0x8 ) {
Static MF_BYCOMMAND := 0, MF_BYPOSITION := 0x400, MF_POPUP := 0x10

  Flag    := ByPos ? MF_BYPOSITION : MF_BYCOMMAND     
  ItemRef := ItemRef - ( ByPos ? 1 : 0 ) 

  R := DllCall( "GetMenuState", UInt,hMenu, UInt,ItemRef, UInt,Flag )  ; goo.gl/PdRLR9

Return ( MF=MF_POPUP ? ( R&16 ? R>>8 : 0 ) : MF>0 ? ( R & MF = MF ) : R ) 
}


Menu_SetSysMenu( hWnd, AddItems="", Options="" ) {
Static MF_MENUBARBREAK := 0x20, MF_SEPARATOR := 0x800, MF_STRING := 0  ;     goo.gl/ggTuwF
Static SWP_Flag := 0x33 ; SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE goo.gl/sah2Dm

  InStr( Options, "Reset"  ) ? DllCall( "GetSystemMenu", UInt,hWnd, UInt,True )

  hMenu := DllCall( "GetSystemMenu", UInt,hWnd, UInt,0 )   ; GetSystemMenu() goo.gl/cfW40p
                                                           
  InStr( Options, "-Close" ) ? DllCall( "RemoveMenu", UInt,hMenu, UInt,0xF060, UInt,0 )
  InStr( Options, "-Move"  ) ? DllCall( "RemoveMenu", UInt,hMenu, UInt,0xF010, UInt,0 )   
                                                           ; RemoveMenu()    goo.gl/KzP0Yg
  Loop, Parse, AddItems,`n, `r`t%A_Space%                  
  {
    Item := A_LoopField, F1 := "", F2 := 0

    Loop, Parse, Item, CSV, %A_Space%`t 
      F%A_Index% := A_LoopField
                                                            
    DllCall( "AppendMenu", UInt, hMenu                     ; AppendMenu()    goo.gl/ggTuwF               
                         , UInt, !F2 ? MF_SEPARATOR : F2>>16 ? MF_MENUBARBREAK : MF_STRING 
                         , UInt, F2 & 0xFFFF
                         , UInt, F2 ? &F1 : F2 )                     
  }

  If InStr( Options, "Redraw"  )                           ; SetWindowPos()  goo.gl/sah2Dm
    DllCall( "SetWindowPos", UInt,hWnd, Int,0, Int,0, Int,0, Int,0, Int,0, UInt,SWP_Flag ) 

Return hMenu, DllCall( "SetLastError", UInt,DllCall( "GetMenuItemCount", UInt,hMenu ) )
} 
Menu_SetSysMenu() can be used on third party windows for Disabling Close Button and/or for making the window un-movable

Disable Close Button
Apply: Menu_SetSysMenu( hWnd, "", "-Close Redraw" )
Reset: Menu_SetSysMenu( hWnd, "", "Reset Redraw" )

Set Window Un-Movable
Apply: Menu_SetSysMenu( hWnd, "", "-Move" )
Reset: Menu_SetSysMenu( hWnd, "", "Reset" )

Both of above
Apply: Menu_SetSysMenu( hWnd, "", "-Close -Move Redraw" )
Reset: Menu_SetSysMenu( hWnd, "", "Reset Redraw" )
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: System Menu : Add custom and/or remove standard items

19 Dec 2013, 08:14

what are the advantages/uses/applications of Disabling Close Button and/or for making the window un-movable? :ugeek:
User avatar
Chef
Posts: 50
Joined: 14 Nov 2013, 13:01

Re: System Menu : Add custom and/or remove standard items

19 Dec 2013, 08:36

Useful, thanks for sharing Image
User avatar
budRich
Posts: 81
Joined: 29 Sep 2013, 16:52
Location: Wermland
Contact:

Re: System Menu : Add custom and/or remove standard items

19 Dec 2013, 13:04

Great stuff. Thank you Grand Magus SKAN.
User avatar
SKAN
Posts: 661
Joined: 29 Sep 2013, 16:58

Re: System Menu : Add custom and/or remove standard items

20 Dec 2013, 01:41

Guest10 wrote:what are the advantages/uses/applications of Disabling Close Button and/or for making the window un-movable? :ugeek:
Well, I never had the need for making a window un-movable, but has been requested like a couple of times. As for disabling Close button, it prevents accidental closure of window and yet Alt+F4 will be able close the window. It is convenient for people who rapidly close windows and feel sorry later for having closed the wrong window. About me: I too click rapidly on the close button, BUT before releasing, I take a good look at the window and then release the button. The associated routine only fires when Left-Mouse-button is up and is the default behavior for any button you see in Windows. So, in cases where you have already clicked on a button but yet to release the mouse button and want to cancel it: Move the mouse cursor away from the button and then release it or press simply press <Esc> to cancel the mouse click.
Grezzo
Posts: 1
Joined: 17 Feb 2014, 04:59

Re: System Menu : Add custom and/or remove standard items

17 Feb 2014, 05:05

Hi SKAN,

Sorry to hijack this thread, but my question is related to this script.

I'm trying to make a script that adds custom menus to an existing menu of a 3rd party application.

I have successfully added the menus using DLL calls, but I'm not sure how to detect clicks on the menu because all the OnMessage() listeners that I have tried don't work on 3rd party windows. They only seem to work on AHK GUI windows.

I have had the idea of monitoring clicks in the RECT of my custom menu items, but I'm wondering if you have found a better way in this script? Unfortunately I'm struggling to understand exactly how your script works...

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 28 guests