0
votes

Is it possible to determine the source of a close request in a Windows application (Delphi)?

Background: I have an option to route close requests to minimizing the window to keep the app running "in Background".

procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
    ...  different checking stuff e.g. unsaved changes
    // Redirect Close to minimize but allow close if requested from minimized state
    if FMinimize and (WindowState <> wsMinimized) then
    begin
        logger.debug('... closing main form redirected to minimize');
        WindowState := wsMinimized;
        CanClose := false;
        exit;
    end;
end;

This works well and allows closing the window by right clicking in the taskbar if already minimized. As icing of the cake I would like to determine if the close request came from right clicking the taskbar icon to close immediately even if the window is not already minimized. Is there a way to determine the source of the close request?

1
I don't think you can out-of-the-box determine the source of the close. You could use a variable set to some enumeration value everywhere a close could be done. You can then check that variable from the OnCloseQuery.fpiette
And what does the program do when I minimize the window? If the answer is "the same" then why don't you disallow closing the window right away? I hate programs not doing what I tell them and am able to distinguish between "close" and "minimize"...AmigoJack
@AmigoJack: This option can be set by users, it is not default behaviour. So the user decides if he wants the program to behave like this. Since many (at least of my) users are used to close windows by clicking the cross icon to put it away and get back to the other application this makes sense, specially in an environment where users switch between two applications. Of course, one could teacht them using ALT TAB and so on, but I prefer adapting to the users way of working.MichaSchumann
@fpiette: Thanks, this I will try, as I mainly want to hook closing by the red cross...MichaSchumann
Are you just minimizing your application on close request so that application taskbar button is still visible (clicking on it restores application) or are you minimizing it to systray where your application creates new systray icon (you could use TTrayIcon component for this)? The later approach would allow you to set some specific variable which you then check in your OnCloseQuery event or simply minimize your application before calling MainForm.CloseSilverWarior

1 Answers

3
votes

There is no difference between closing a window via the X button in its top-right corner, vs the Close window option on the right-click menu of the window's Taskbar button, vs the ALT-F4 keystroke. They all represent the same close command. If any of those options are invoked, the window will receive a WM_SYSCOMMAND(SC_CLOSE) message, which if passed to DefWindowProc() will generate a WM_CLOSE message that will trigger the Form's OnCloseQuery event. So no, there is no way to differentiate the source of the initial WM_SYSCOMMAND message. Only that the user wishes for the window to close.

That being said, you might try having your Form intercept the WM_NCHITTEST and WM_SYSKEYDOWN messages to detect when the user is clicking on the X button or pressing ALT-F4 on the keyboard. You can use those messages to set flags that your OnCloseQuery event can look at. That is about the only way I can think of right now to differentiate between Taskbar vs non-Taskbar closures.