Detect if red/white cross in upper right corner is clicked

Hi all,

When the user closes a window I want to detect he is is closing it by clicking on the red/white cross in upper right corner. Explicitly that button and not the close button or something like CTRL-F4 or ALT-F4.

Any idea how I can do that?

FWIW, dirty but it works , we setkeycode(CtrlAltF12) , under the ‘Close’ button ,

Then trap event:Closewindow and check for ‘CtrlAltF12’ , ie

IF KEYCODE() <> CtrlAltF12 THEN CYCLE End
SETKEYCODE(0)
… let CloseWindowEvent proceed

See previous suggestions…

Set a local variable on your Close button and check it before closing the window. e.g. example from AI…

! Local Data
ClosedByCode  BYTE(0)

! Inside your ACCEPT Loop / Event Handling:
CASE EVENT()
OF EVENT:CloseWindow
  IF ClosedByCode = FALSE
    ! The user clicked the Red X, pressed Alt+F4, or used the System Menu
    ! Put your warning or cancellation logic here
    IF Message('Do you really want to quit?', 'Confirm', ICON:Question, BUTTON:Yes+BUTTON:No, BUTTON:No) = BUTTON:No
      CYCLE  ! This CYCLE prevents the window from closing
    END
  END
  BREAK
  
OF EVENT:Accepted
  OF ?SaveAndCloseButton
    ClosedByCode = TRUE
    POST(EVENT:CloseWindow)
END

Copilot response to distinguishing the click on the close button vs other ways of initiating the close

bool g_XButtonClicked = false;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_NCLBUTTONDOWN:
        // HTCLOSE means the cursor is specifically over the Close ('X') button
        if (wParam == HTCLOSE)
        {
            g_XButtonClicked = true; 
        }
        break;

    case WM_SYSCOMMAND:
        // Filter out system command artifacts (masking last 4 bits as per Win32 specs)
        if ((wParam & 0xFFF0) == SC_CLOSE)
        {
            if (g_XButtonClicked)
            {
                // Triggered strictly by clicking the upper right 'X' Close button
                OutputDebugString(L"Closed via 'X' Button Click\n");
                g_XButtonClicked = false; // Reset the flag
            }
            else if (lParam == 0)
            {
                // Triggered via Alt+F4 or Taskbar "Close Window"
                OutputDebugString(L"Closed via Alt+F4 or Taskbar\n");
            }
            else
            {
                // Triggered by selecting "Close" from the top-left system menu
                OutputDebugString(L"Closed via System Menu\n");
            }
        }
        break;

    case WM_CLOSE:
        // Fall back to normal closure processing here
        DestroyWindow(hwnd);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Trying to think of something simple…

Event:Close window is the place to check. If they clicked on the Red X then I would think KeyCode() = MouseLeft so that’s something to check.

Any Close button you have could also be clicked, so as @ted suggested in that embed you must SetKeyCode(0).

That leaves the System Menu on the upper left that can be dropped and Click on Close so also MouseLeft and triggers this logic.

You could look at the values of MouseX() and Y() when you click on the Red X to see if they have useful values detecting upper right.

Remember pressing Esc usually also closes the Window.

I would advise against preventing using the Red X as that is common Windows UI behavior. When you prevent that you tend to confuse and frustrate users.

Your are right but I don’t want to disable that button, I just want to detect. This particular window is a browser window that shows an embed Power BI report:

That report has a blue filter settings overlay. To close that overlay there is a white cross. Some users click on the red/white cross instead of the white cross. That is the reason I want to explicitly detect clicking on that button.
(BTW I must admit it is a bit poor design)

Looks like subclassing to me, correct? Not much experience with that, but I have done that in the past I think. Going to dig in my memory.

Hi Koen, and disable the red cross?

Can maybe, but it is not my intention to change behaviour. I agree with Carl Barnes that interfering with common Windows UI behaviour isn’t good. So that is just want to show a message when that on button is clicked as in this particular window it might be not intentional. Clicking on the close button elsewhere on the window I consider to be intended and doesn’t need a question “Are you sure?”

Not necessarily will eliminate the button, but maybe it can help. If you remove the Title Bar, the button will not show. Now, the problem is the user may not have a way to move around the window if needed. A workaround for that may be this template

Move a clarion window from clicking on a region - code / Snippets - ClarionHub

Remember to give the user a proper way to close the window.

Hope this helps or maybe give you new ideas.

Mark Goldberg put me on the right track. The solution is using a subclassing procedure. Based on the code Mark provided I created a subclass procedure in Clarion. It works for me as desired.

See attached example how it works:
XButton.zip (10,5 KB)