Implementation of normal windows in Delphi

Source: Internet
Author: User

From http://blog.csdn.net/cathyeagle

1 Introduction
Windows applications written using the VCL class library provided by DelphiProgram, There is a feature that is significantly different from the standard Windows window-the system menu of the main window is different from the system menu on the taskbar. Generally, the system menu of the main window has six menu items, and the system menu of the taskbar has only three menu items. In actual use, we find that the program developed with VCL has the following advantages:

1) not beautiful enough. This is positive. If it is not consistent with the standard, it will naturally look malformed.
2) There is no animation effect when the main window is minimized.
3) The window cannot be normally tiled with other windows.
4) the taskbar System menu has the highest priority. If a modal window exists, the entire program can be minimized, which is contrary to the design of the modal window.

The problem of minimizing the animation effect in the main window has been solved by using the showwinnoanimate function in forms. PAS in Versions later than Delphi 5.0, but the remaining issues have always existed. Although this does not affect applications in most cases, it is indeed unacceptable in the pursuit of professional results. Since C ++ builder and Delphi use the same class library, the above problems also exist in Windows applications written using C ++ builder.
In the previousArticleI have discussed this issue. The description at that time seems to be a clever method, I also found that method by accident. The task in this article is to explain the principle of doing so by analyzing the VCL class library, and then give a three-lineCodeTo completely solve the problem of this "abnormal window" in Delphi.

2 Principle
2.1 application creation process
The following is a typical application's Delphi project file. We noticed that there was a reference to the initialize method of the Application object at the beginning, and our analysis started from here:

Program project1;

Uses
Forms,
Unit1 in 'unit1. pa' {form1 };

{$ R *. Res}

Begin
Application. initialize;
Application. createform (tform1, form1 );
Application. Run;
End.

The hidden window is created by the Application object. Where does the application object come from? In the code editing window of Delphi, press Ctrl and click application. The application object is one of the global objects defined in the forms. Pas unit. This is not enough. We want to know where the application object is created, because we must successfully create an instance of the tapplication class before we can reference it.
Think about the code that will be executed before application. initialize? By the way, it is the code in the initialization code segment. After carefully debugging the VCL source code, you can know that many units in VCL have initialization code segments. When you start the Delphi Program, the code of initialization code segments in each unit is first executed in the order of uses, after all initialization actions are completed, the initialize method of the application is executed to initialize the application. Therefore, it is clear that the Application object is created in the initialization code segment of a unit.
Search the VCL source code directory with the keyword "tapplication. Create". We found the code for creating the application object in the controls. Pas unit. In the initialization code segment of the controls. Pas Unit, there is a call to the initcontrols process, and the implementation of initcontrols is as follows:

Unit controls;
...
Initialization
...
Initcontrols;

Procedure initcontrols;
Begin
...
Mouse: = tmouse. Create;
Screen: = tscreen. Create (NiL );
Application: = tapplication. Create (NiL );
...
End;

Well, our analysis completes the first step. To solve the problem of abnormal windows, we must do one thing before initializing the application object, therefore, it is very important to understand the initialization process of the application.

2.2 islibrary Variables
Islibrary variables are one of the global flag variables defined in the system. Pas unit. If the islibrary value is true, it indicates that the program module is a dynamic link library, and vice versa, it is an executable program. In the VCL class library, different actions are performed based on different values of the variable. That is, this variable plays a key role in solving the problem of abnormal window in Delphi.
As mentioned above, for convenience, an invisible window is created during application object initialization (that is, the window named "tapplication" as the class name seen by tools such as spy ++ ), but it is precisely because of this invisible window that the program developed with Delphi presents many malformed features. Well, if we can remove this invisible window (also remove the taskbar System menu) and replace it with our application main window, isn't all the problems solved?
This is simple, but the VCLSource codeMajor surgery? If that's not the case, isn't it? Of course, the answer is no. Otherwise, there will be no such article. What I want to talk about here is that in the next analysis, we will see that the so-called "programming path, saving your mind", tapplication design is unintentional, this leaves an interface for us to solve this problem. Without source code analysis, you may need to go around the circle. In fact, we can see that there are not many and just a lot of things that are left for us by the design of genius.
Open the create constructor of the tapplication class and we will find such a line of code.

Constructor tapplication. Create (aowner: tcomponent );
Begin
...
If not islibrary then createhandle;
...
End;

If the program module is not a dynamic link library, execute createhandle, and the work done by createhandle in the help is as follows: "If there is no application window, create an "Application Window", which is the invisible window mentioned above, that is, the culprit. In the tapplication class, use the fhandle variable to save the window handle. Here, different actions are completed based on the islibrary value, because the message loop is generally not required in the dynamic link library, but the application object must be used to develop a dynamic link library using VCL, so we have the design here. Well, we only need to cheat the application object and assign the islibrary value to true before it is created. Then, we can filter out the createhandle execution and remove this annoying window.
The code assigned to islibrary should obviously be placed in the initialization code segment of a certain unit, and because the code in the initialization code segment is executed in the order of included units, to ensure that the islibrary is assigned true before the application object is created, we must place the unit containing the assignment code in the project file before the forms unit, as shown below (assume that the unit is named unitdllexe. PAS ):

Program template;

Uses
Unitdllexe in 'unitdllexe. pa ',
Forms,
Formmain in 'formmain. pa' {mainform },
...

The following is a list of unitdllexe. Pas code:

Unit unitdllexe;

Interface

Implementation

Initialization
Islibrary: = true;
// Tell applciation object, which is a dynamic link library and does not need to create a hidden window.
End.

Now, compile and run the program. We can see that the system menu on the taskbar disappears because no hidden window is created, and is replaced with the system menu in the main window, the main window can also be arranged and tiled normally with other windows Windows. However, the problem is that Windows cannot be minimized. What's going on? Keep track of the old method.

2.3 minimize the Main Window
Minimization is a system command. In the end, it is necessary to call the API function defwindowproc to minimize the window. Therefore, we have found the wmsyscommand function in tcustomform to respond to the wm_syscommand message, specifically, it is clearly written to redirect the minimal message to the application. wndproc:

Procedure tcustomform. wmsyscommand (VAR message: twmsyscommand );
Begin
With message do
Begin
If (condition type and $ fff0 = SC _minimize) and (application. mainform = self) then
Application. wndproc (tmessage (Message ))
...
End;
End;

In application. wndproc, the minimize method of application is called when the response is minimized, so the crux of the problem must be in the minimize process.

Procedure tapplication. wndproc (VAR message: tmessage );
...
Begin
...
With message do
Case MSG
Wm_syscommand:
Case wparam and $ fff0
SC _minimize: Minimize;
SC _restore: Restore;
Else
Default;
...
End;

Finally, find tapplication. Minimize and you will understand everything. The call to the defwindowproc function has no effect. Why? As we had previously spoofed the application object, filtered out the createhandle call, and did not create the window required for the application object to respond to the message, so the fhandle handle of the Application object was 0. Of course, the call was unsuccessful. If you can direct fhandle to the main application window, the problem can be solved.

Procedure tapplication. Minimize;
Begin
...
Defwindowproc (fhandle, wm_syscommand, SC _minimize, 0 );
// Here, the fhandle value is 0.
...
End;

3. Implementation
Borland's talented people did not care about the design. Once again, we found a solution to the problem. From the previous analysis, we know that no hidden window is created in the dynamic link library developed with VCL to receive Windows messages (createhandle is not executed ), however, to display a window in the dynamic link library, another parent window is required. How can this problem be solved? The VCL designer designs the fhandle variable that saves invisible window handles as Writable, so we can actually assign a value to fhandle to provide a parent window for the Child window to be displayed. For example, to display a form in a dynamic link library plug-in, we usually pass in the Application object handle in the executable file of the main module through a function of the dynamic link library and assign it to the application of the dynamic link library. handle, similar:

Procedure setapplicationhandle (mainappwnd: hwnd)
Begin
Application. Handle: = mainappwnd;
End;

Okay, since aplication. handle is actually a window handle used internally to respond to messages, and the invisible window that should have been created is removed by us. Then we only need to provide a window handle, can it be used to replace the handle of the previously redundant hidden window? Where can I find such a window? The main window of the application is the top choice, so the following code is available.

Program template;

Uses
Unitdllexe in 'unitdllexe. pa ',
Forms,
Formmain in 'formmain. pa' {mainform };

{$ R *. Res}

Begin
Application. initialize;
Application. createform (tformmain, formmain );
Application. Handle: = formmain. Handle;
Application. Run;
End.

As a result, all problems are solved. You do not need to modify the VCL source code or modify the original program. You only need to add two lines of code to the project file and add unitdllexe. in pas, there are three lines of code in total to make your application window as normal as any standard Windows window.

1) the taskbar and window title bar have the same system menu.
2) When the main window is minimized, there will be an animated effect.
3) The window can be normally arranged and tiled with other windows.
4) When a modal window exists, its parent window cannot be operated.

The above implementation code is used in all versions of Delphi.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.