How do I disable the application Close button

Tags: #<Tag:0x00007f224d89d688>

I am writing an email monitoring program that needs to run all the time. If the user goes to File -> Exit then it should close. But I don’t want the user to click on the right-hand “x” button to close it. It’s too easy to close it by accident that way.

How do I disable the close button, or reprogram it to minimise the app instead? I am using the CapeSoft WinEvent5 library if that will help.

AFAIK you cannot disable it.

Everything posts an Event:CloseWindow. In that embed if you CYCLE the close does not happen.

So create a local variable CloseAllowed. In Event:CloseWindow IF ~CloseAllowed THEN CYCLE.

In Accepted of Exit ITEM set CloseAllowed=true

That would be for a Window, for an APPLICATION Frame it’s EVENT:CloseDown.

You will also want to ALRT(EscKey) so they cannot press, I think ESC closes a frame.

Edit: Donn figured out that ?Exit ITEM must have STD(STD:Close) removed for this to work.

1 Like

How do I enable and disable the minimize, maximize, and close buttons in my caption bar? - The Old New Thing (microsoft.com)

To disable the Close button in the caption dynamically, you enable and disable the SC_CLOSE menu item in your system menu.

void DisableCloseButton(HWND hwnd)
    {
     EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
                    MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
    }
    void EnableCloseButton(HWND hwnd)
    {
     EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
                    MF_BYCOMMAND | MF_ENABLED);
    }
1 Like

As Ray Chen says of you hide Close you may frustrate users since it works in every other program. It makes them feel trapped and uncomfortable

In my first post having Close do nothing will also frustrate or confuse. Instead give them a Message when Close button is pressed:

IF ~CloseAllowed THEN
     IF Message('if you close this you''re emails will not be blah blah blah', |
        'Close?',,'Monitor Email|Stop Email Monitoring' .... ) = 1 THEN CYCLE.

I prefer to not disable controls and leave a puzzle what is needed to enable. I would rather let them click on them then display a message ('You need to enter a yadda yadda…

1 Like

This worked, until I tried File -> Exit. I had to remove the STD property and then write

    CloseAllowed = TRUE    
    post(EVENT:CloseDown)

Without this small change the ?Exit code wasn’t executed.

I will put a warning message on the Close event when it is disabled.

1 Like

Good catch … STD(STD:Close) has caused many WTF “why’s my embed code not running” delays

The Defaults.clw Windows used STD:Close on all the Close buttons. I asked to have it removed. Not sure if SV did it but I edited my Defaults.clw

1 Like

I use the strategy of requiring a “canclose” variable.
As in the attached demo app.

(Of course, the variable is normally set by a condition within the program, not by a checkbox as in the example.)

CannotClose.zip (6.8 KB)

Here’s the Clarion code:

 MAP 
    CloseButtonDisable(BOOL DisableClose=True) !Disables Close button (False Enable) on the Current Window

    MODULE('Win32')
      GetSystemMenu(LONG hWnd, BOOL bRevert=False),LONG,PASCAL,DLL(1)   !Returns hMenu 
      EnableMenuItem(LONG hMenu, LONG uIDEnableItem, LONG uEnable ),LONG,PROC,PASCAL,DLL(1)  !Returns Prior State
    END
 END


CloseButtonDisable  PROCEDURE(BOOL DisableClose=True) !Disables Close button (False Enable) on the Current Window
hSysMenu LONG,AUTO
uEnable  LONG,AUTO
cbSC_CLOSE EQUATE(0F060h)
!MF_BYCOMMAND EQUATE(0) Indicates uIDEnableItem gives the identifier of the menu item i.e. cbSC_CLOSE
!MF_ENABLED   EQUATE(0)
!MF_DISABLED  EQUATE(2)   2+1 to Disable and make visually Gray
!MF_GRAYED    EQUATE(1)
  CODE
  hSysMenu=GetSystemMenu(0{PROP:Handle},False)
  IF hSysMenu THEN
     IF DisableClose THEN   ! uEnable = 0 + CHOOSE(~DisableClose, 0, 2+1)
        uEnable = 0 + 2+1   ! Disable = 0 + 2 + 1 =  MF_BYCOMMAND | MF_DISABLED | MF_GRAYED
     ELSE
        uEnable = 0 + 0     ! Enable  = 0 + 0     =  MF_BYCOMMAND | MF_ENABLED
     END
     EnableMenuItem(hSysMenu, cbSC_CLOSE, uEnable)
  END
  RETURN

3 Likes

Thanks everyone for the suggestions, code, etc.

I put a warning message on the close window event, which shows up if you click on the close button in the top right corner. The File->Exit menu item allows the program to quit as expected. The blue message on the toolbar tells the rest of the story.

Thanks everyone for pitching in. I always appreciate it and I have learnt a lot more about events and menus too :slightly_smiling_face:

You could add a Minimize button to the Message to save them the extra step of reading and following your instructions. If they click the Min button set 0{PROP:Iconize}=True

Maybe button text of 'Minimize|Keep Open'. I’d put Minimize first since that’s what you want them to do. I really go to this extra work to make it easy for them to do what I want them to do. And give them button names that are easy to understand, so they don’t have to read the message too well, versus Yes/No buttons require reading and understanding.

I would also add a caption to the Message(, 'eMail Timer') because its good to have a caption. Sometimes the Message can show on the taskbar so blank is bad, mainly shows when underlying window is hide.

2 Likes

All of what Carl said plus add system {prop:icon}

2 Likes

It took me a minute … you mean add the program icon to the Message? That would look nice and visually link it. Could also use the frame icon 0{PROP:Icon}.

IF Message('Please use File->Exit to quit |or minimize the window.', |
           'eMail Timer', 0{PROP:Icon} ,'Minimize |Keep Open')=1 THEN 0{PROP:Iconize}=1.