A side effect introduced by the Delphi message mechanism

xiaoxiao2021-03-06  78

Delphi introduces a hidden form Application when handling the process, and the distribution of messages. Such a mechanism is beautifully processed by the issue of the distribution and disposal of the message. But recently I found that this mechanism has also introduced a side effect and will affect the interface interaction behavior in some cases.

The demand I encountered is to implement a single instance in the program, and when the second instance is started, first set the previous instance to the forehead, then exit. It should be a typical example, but such a simple demand is affected by this side effect.

My implementation is like this: When the second instance is started, send a message to the previous instance, ask it to place itself, then exit. As for the first instance of the handle, you can use FindWindows, you can also use named filemapping, in short, the first form is connected to the commands presented before.

How to set this form to the forefront? As we all know, setForegroundWindow does not really set a form to the forefront. In contrast, it will make this designated form flash in the task bar, but it does not cover this form. The top of the z-Order. Very educated, but I don't like it, because this is not what I want.

So I used such a way to put the form I want to directly to the forefront:

Setwindowpos (HFORM, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE OR SWP_NOSIZE); SetWindowPos (HFORM, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE OR SWP_NOSIZE);

Forcibly drag the form to the top of the z-Order, then remove its topmost property, so you can. It is a bit not polite, but if the polite is useful, what should I do?

Ok, what is said earlier, it seems that there is not much relationship with our title, but the rest of the trouble is here.

I found that when the first instance is minimized, the second instance wakes it, placing its main window to the forehead, and then the "minimize" button of the form is invalid! At this time, the form can be operated, and you can maximize it, but it can no longer be minimized!

This is a very depressed problem, a form that cannot be minimized is very unfriendly, I can accept a non-courtesy form, but I don't want to accept such unfrigery guys.

I found the process of problem causes this:

In the process, the WM_SYSCOMMAND message of the main form is passed to the Application class. When cmdtype is SC_MINIMIZE, Application will call the minimize method:

procedure TApplication.Minimize; begin if not IsIconic (FHandle) then begin NormalizeTopMosts; SetActiveWindow (FHandle); if (MainForm <> nil) and (ShowMainForm or MainForm.Visible) and IsWindowEnabled (MainForm.Handle) then begin SetWindowPos (FHandle, MainForm .Handle, MainForm.Left, MainForm.Top, MainForm.Width, 0, SWP_SHOWWINDOW); DefWindowProc (FHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0); end else ShowWinNoAnimate (FHandle, SW_MINIMIZE); if Assigned (FOnMinimize) then FOnMinimize (Self) End; end; Note this isiconic (Fhaandle), it is the problem of the cause of the iceberg. Isiconic is an API used to detect if the form is in a minimized state. I found that after the second instance places the main window body of the previous instance, this form minimizes this method, each time ISICONIC (FHANDLE) is TRUE. In other words, Application has always considered that they are minimized.

So the problem is more clear: When we enable the main form to the forefront, Application does not restore the original state. So the main form in the minimize method does not minimize commands.

No wonder that there will be no such problem in the program developed by VC! Because this factor does not exist.

So we only need to force the main form for arsenation, first restore the Application:

IF ISICONIC (Application.Handle) THENBEGIN DEFWINDOWPROC (Application.Handle, WM_SYSCOMMAND, SC_RESTORE, 0); END;

This is fine.

Welcome to the author's personal homepage: http://www.mrspace.net/

转载请注明原文地址:https://www.9cbs.com/read-108766.html

New Post(0)