Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[How To] Disable (Grey-out) the Close Button


  • Please log in to reply
14 replies to this topic
SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

How to Disable ( Grey-out ) the Close Button?
http://www.autohotke...p?p=62506#62506


The Solution is as simple as this:

Removing the menu item "Close" from the (Window's) System menu
"greys out" the Close button!

Compare the snapshots below:-

Posted Image____Posted Image

I present here two functions that will ease the task:


DisableCloseButton() will disable the Close button of the active window.

DisableCloseButton(hWnd="") {
 If hWnd=
    hWnd:=WinExist("A")
 hSysMenu:=DllCall("GetSystemMenu","Int",hWnd,"Int",FALSE)
 nCnt:=DllCall("GetMenuItemCount","Int",hSysMenu)
 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-1,"Uint","0x400")
 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-2,"Uint","0x400")
 DllCall("DrawMenuBar","Int",hWnd)
Return ""
}
[*:1z29pp84] Note: Disabling the Close button helps one to avoid accidental closure of a window.... Nothing more!. ALT+F4 will still close the window![/list]
RedrawSysmenu() will reset the System menu of the active window to default state.
RedrawSysMenu(hWnd="") {
 If hWnd=
    hWnd:=WinExist("A")
 DllCall("GetSystemMenu","Int",hWnd,"Int",TRUE)
 DllCall("DrawMenuBar","Int",hWnd)
Return ""
}

Examples:

Disabling the Close button of an AHK GUI :

Gui, +Resize
Gui, Show, w400 h300, Demo Window
DisableCloseButton()
Return

; Copy & Paste DisableCloseButton() below

Disabling/Enabling the Close button of any Window:

#F2::DisableCloseButton(WinExist("A"))
#F3::RedrawSysmenu(WinExist("A"))
Return

; Copy & Paste DisableCloseButton() and RedrawSysmenu() below

Disabling/Enabling the Close button of all instances of Internet Explorer Windows:

^#F2::
WinGet,WindowID,List,ahk_class IEFrame 
Loop, % WindowID { 
cWindow = % WindowID%A_Index% 
DisableCloseButton(cWindow)
} 
Return

^#F3::
WinGet,WindowID,List,ahk_class IEFrame 
Loop, % WindowID { 
cWindow = % WindowID%A_Index% 
RedrawSysMenu(cWindow)
} 
Return

; Copy & Paste DisableCloseButton() and RedrawSysmenu() below

Credit:

Adapted from a VB example given in
Windows API reference / API-Guide 3.7[/list]
With a little alteration to DisableCloseButton() one can disable the other two buttons, I guess!...

Feedback please!....


kWo4Lk1.png

jaco0646
  • Moderators
  • 3165 posts
  • Last active: Apr 01 2014 01:46 AM
  • Joined: 07 Oct 2006

How to Disable ( Grey-out ) the Close Button?

...

Feedback please!

I'd like to use this tip to stop myself from accidentally closing the Task Manager. I like to keep it running in the tray for the real-time CPU usage graph. This works:
Run, taskmgr.exe,,,PID
WinWait, ahk_pid %PID%
DisableCloseButton(WinExist())
WinMinimize

DisableCloseButton(hWnd) {
 hSysMenu:=DllCall("GetSystemMenu","Int",hWnd,"Int",FALSE)
 nCnt:=DllCall("GetMenuItemCount","Int",hSysMenu)
 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-1,"Uint","0x400")
 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-2,"Uint","0x400")
 DllCall("DrawMenuBar","Int",hWnd)
}
...however, I'd like to not have to flash the window open just to get its handle. Any thoughts?

TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006

I'd like to not have to flash the window open just to get its handle. Any thoughts?


winGet, tmHwnd, ID, Windows Task Manager
msgbox % tmHwnd
:?:

edit:

or
setformat, integerfast, H
msgbox % tmHwnd:=dllCall("FindWindow", str, "#32770", str, "Windows Task Manager")

Posted Image

don't duplicate, iterate!


jaco0646
  • Moderators
  • 3165 posts
  • Last active: Apr 01 2014 01:46 AM
  • Joined: 07 Oct 2006
I forgot to note earlier that to make Task Manager minimize to the tray, go to the Options menu and check Hide When Minimized.

I had also forgotten to detect hidden windows. :oops:
DetectHiddenWindows, On

Run, taskmgr.exe,,Min,PID
WinWait, ahk_pid %PID%
DisableCloseButton(WinExist())

DisableCloseButton(hWnd) {
 hSysMenu:=DllCall("GetSystemMenu","Int",hWnd,"Int",FALSE)
 nCnt:=DllCall("GetMenuItemCount","Int",hSysMenu)
 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-1,"Uint","0x400")
 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-2,"Uint","0x400")
 DllCall("DrawMenuBar","Int",hWnd)
}

This code works about 50% of the time. The other half, the button is not disabled even though the handle is found.

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

Task Manager. I like to keep it running in the tray for the real-time CPU usage graph.


Nice Idea! Here is my version
- without DetectHiddenWindows
- without compromising Ctrl+Alt+Del functionality

#NoTrayIcon
#SingleInstance, Force

If !TaskManID := DllCall("FindWindowA", Str,"#32770", Str,"Windows Task Manager" ) {
    Run, taskmgr.exe,,Hide
    While ! TaskManID := DllCall("FindWindowA", Str,"#32770", Str,"Windows Task Manager" )
     Sleep 20
} Else {
    TaskManID := DllCall("FindWindowA", Str,"#32770", Str,"Windows Task Manager" )
    WinHide, ahk_id %TaskManID%
}
DisableCloseButton( TaskManID )
Return ;                                                  // End of auto-execute section /

[color=red]^!Del[/color]:: ; Ctrl+Alt+Del will toggle Hide/Show state for 'Windows Task Manager'
DllCall( "ShowWindow"
    , UInt, TaskManID := DllCall("FindWindowA", Str,"#32770", Str,"Windows Task Manager" )
    , UInt, !DllCall( "IsWindowVisible", UInt,TaskManID ) )
Return

[color=red]^!x[/color]::ExitApp, % DllCall( "ShowWindow", UInt,TaskManID, UInt,1 )

DisableCloseButton( hWnd ) {
 hSysMenu := DllCall( "GetSystemMenu", UInt,hWnd, Int,0 )
 nCnt := DllCall( "GetMenuItemCount", UInt,hSysMenu )
 DllCall( "RemoveMenu", UInt,hSysMenu, UInt,nCnt-1, UInt,0x400 )
 DllCall( "RemoveMenu", UInt,hSysMenu, UInt,nCnt-2, UInt, 0x400 )
 DllCall( "DrawMenuBar", UInt,hWnd )
}


MasterFocus
  • Moderators
  • 4323 posts
  • Last active: Jan 28 2016 01:38 AM
  • Joined: 08 Apr 2009

Run, taskmgr.exe,,Hide,[color=red]PID[/color]
     WinWait, ahk_pid %[color=red]PID[/color]%

Did you mean TaskManID?

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio França -- git.io -- github.com -- ahk4.net -- sites.google.com -- ahkscript.org

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012.


SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

Did you mean TaskManID?


No.. But I overlooked the fact that WinWait would require DetectHiddenWindows. Code altered..

Thanks.

TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006

DllCall("FindWindow[color=red]A[/color]", Str,"#32770", Str,"Windows Task Manager" )

Hi SKAN is there any difference between FindWindow and FindWindowA other than ANSI?

Also
!DllCall
Does this inverse work for all function calls to dll?

BTW after running the updated version, my taskmanager does not come back if I close it from the tray :?

Posted Image

don't duplicate, iterate!


SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

DllCall("FindWindow[color=red]A[/color]", Str,"#32770", Str,"Windows Task Manager" )

Hi SKAN is there any difference between FindWindow and FindWindowA other than ANSI?


There is no function named FindWindow() exported in user32.dll
AutoHotkey appends the 'A' for you - automatically. Sweet!

Does this inverse work for all function calls to dll?


Yes. You may use triple toggle like !!! Function() if you strictly require a BOOLEAN.

BTW after running the updated version, my taskmanager does not come back if I close it from the tray :?


:D Use SHELLHOOK.

jaco0646
  • Moderators
  • 3165 posts
  • Last active: Apr 01 2014 01:46 AM
  • Joined: 07 Oct 2006
This seems to be 100% reliable after limited testing.
#NoTrayIcon



Run, taskmgr.exe,,Min

While ! TaskManID := DllCall("FindWindowA", Str,"#32770", Str,"Windows Task Manager")

  Sleep 20

DisableCloseButton( TaskManID )



DisableCloseButton( hWnd ) {

 hSysMenu := DllCall( "GetSystemMenu", UInt,hWnd, Int,0 )

 nCnt := DllCall( "GetMenuItemCount", UInt,hSysMenu )

 DllCall( "RemoveMenu", UInt,hSysMenu, UInt,nCnt-1, UInt,0x400 )

 DllCall( "RemoveMenu", UInt,hSysMenu, UInt,nCnt-2, UInt, 0x400 )

 DllCall( "DrawMenuBar", UInt,hWnd )

}
Why does the loop work, when WinWait fails?

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

Why does the loop work, when WinWait fails?


WinWait would require DetectHiddenWindows On, I guess.

jaco0646
  • Moderators
  • 3165 posts
  • Last active: Apr 01 2014 01:46 AM
  • Joined: 07 Oct 2006
Yep, I've remembered that now. Here's my test script. The message box should never show.
;#NoTrayIcon

DetectHiddenWindows, On



Run, taskmgr.exe,,Min,PID

WinWait, ahk_pid %PID%

h1 := WinExist()

h2 := DllCall("FindWindowA", Str,"#32770", Str,"Windows Task Manager")

If (h1 = h2)

 DisableCloseButton(h1)

Else MsgBox,% h1 "`n" h2



DisableCloseButton(hWnd) {

 hSysMenu:=DllCall("GetSystemMenu","Int",hWnd,"Int",FALSE)

 nCnt:=DllCall("GetMenuItemCount","Int",hSysMenu)

 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-1,"Uint","0x400")

 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-2,"Uint","0x400")

 DllCall("DrawMenuBar","Int",hWnd)

}
But intermittently, WinExist() returns a handle and DllCall() returns 0. In these cases, it seems that WinWait has not waited long enough; but then how is WinExist() working :?:

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

The message box should never show.


It never shows.. :roll:

Does the following produce different result?

DetectHiddenWindows, On

Run, taskmgr.exe,,Min,PID
WinWait, ahk_pid %PID%
h1 := WinExist( "Windows Task Manager ahk_class #32770" )
h2 := DllCall("FindWindowA", Str,"#32770", Str,"Windows Task Manager")
If (h1 = h2)
 DisableCloseButton(h1)
Else MsgBox,% h1 "`n" h2


jaco0646
  • Moderators
  • 3165 posts
  • Last active: Apr 01 2014 01:46 AM
  • Joined: 07 Oct 2006
That code is about 90% reliable for me (I ran it 50 times and it failed on 5). Here's the strange thing: I never got a message box, even on the 5 that failed to disable the button. When I don't pass a parameter to WinExist() I get a message box every time it fails (and it fails more often).

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

Does this inverse work for all function calls to dll?

It works for any expression, not just function calls.

AutoHotkey appends the 'A' for you - automatically. Sweet!

If you omit the 'A', the script will also work on the Unicode build of AutoHotkey_L, which appends 'W' instead of 'A'.

You may use triple toggle like !!! Function() if you strictly require a BOOLEAN.

You may also use !!!!!!!!! Function(), but ! Function() will give the same result faster.