[CB] place the form from the main form

Source: Internet
Author: User
Almost all formal C ++ builder programs have subordinate forms in addition to the main form, sometimes dialog boxes and sometimes modeless windows. VCL makes it easy to create and display subordinate forms. However, not all programs are suitable for non-modal forms. Some programs need to display different content in a main form. This article discusses how to "intercept" a subordinate form in a main form. A subordinate form looks like a part of the main form, and the user does not even know that a slave form is being displayed. Figure A shows a main form, and its customer area is a slave form.

Figure A main form with a subordinate form in the customer Zone

Understanding child/parent contact
The basic idea of this type of program is to make all subordinate forms work as sub-forms of the main form. This design is common in other frameworks (such as owl or MFC, but it is not common in VCL programs. VCL does not allow you to simply specify attributes so that a form belongs to another form. To do this, you have to make a little effort. You have to tell Microsoft Windows that the subordinate form is the sub-object of the main form. In C ++ Builder programming, it is generally considered that the form is a window and the component is a sub-object. In fact, from the perspective of windows, both the form and component are windows. Any window can be
(Form and component) is specified as the sub-object of another window, as long as you temporarily jump out of the VCL circle.

Better mouse clip"
One advantage of attaching a form to a main form is that you can design a subform like designing any other subordinate form, that is, you create a new form, add a component on it and write the code for this form. This makes it easy to design your child forms, and you can concentrate the code of all sub-forms in one place.

Programming examples
First, the background of some programs is given. The program name is parenting. There is a main form. There is a tool bar and a status bar at the top and bottom of the main form. Besides the main form, there are two sub-forms, one is ttableform, which displays animal in a grid. DBF data table. An animal table is a table of database samples in C ++ builder. The other sub-form tchartform uses tchart to display the animal table. (If the C ++ builder you purchased is a Standard Edition, there is no database component.) You can click the menu item or tool button to choose whether to display the form or graphical form, the activity form is destroyed and the selected form is displayed. The child form is displayed in the customer area below the tool bar of the main form and above the status bar, and is always filled with the customer area as the size of the main form changes.

Reload createparams ()
As mentioned above, to allow the main form to control the subordinate form, you need to set the main form as the "parent" of the form, which can be done by reloading the createparams () method. Createparams () is called when VCL creates a window to contact the form. The createparams () statement is as follows:
Void _ fastcall createparams (tcreateparams & Params );
The unique parameter of createparams () is a reference to a tcreateparams struct. In VCL, tcreateparams is defined as follows:

Struct tcreateparams
{
Char * Caption;
Int style;
Int exstyle;
Int X;
Int y;
Int width;
Int height;
Hwnd wndparent;
Void * Param;
Tagwndclassa windowclass;
Char winclassname [64];
};

This structure contains all the information required for Windows to create a window (if you have used APIs for Windows Programming, you will be aware of the ing of tcreateparams members to the Windows createstruct structure ). When you overload createparams (), first call the createparams () method of the base class, and then modify the individual member variables of the tcreateparams structure. An overloaded createparams () method looks roughly as follows:

Void _ fastcall tchartform: createparams (tcreateparams & Params)
{
Tform: createparams (Params );
Params. Style = ws_child | ws_clipsiblings;
Params. wndparent = mainform-> handle;
Params. x = 0;
Params. Y = 0;
Params. width = mainform-> clientrect. Right;
Params. Height = mainform-> clientrect. bottom;
}

The key of the program is to set the style and wndparent members of the tcreateparams struct, ws_child and ws_clipsiblings window styles, and ws_child specifies the window as the Child Window of the other window. According to the definition, a subwindow does not have a title stick. The title stick during design will be removed when Windows creates a form at runtime. Ws_clipsiblings ensures that different subwindows in the main window do not interfere with each other when drawing the form. Obviously, a child window must have a parent object. by specifying the parent window handle to the wndparent Member of the tcreateparams struct, the parent object is specified, as shown in the previous code, the wndparent member is set as the handle attribute of the main form. Since the attributes of the specified parent object are relatively straightforward, I am not going into this topic for more details.

Set Properties of child forms
In addition to the Code in the createparams () method, you also need to set some subform attributes. Most attributes can retain the default values, but the autoscroll attribute should be set to false. Of course, the premise is that your form should be designed as a form style that does not need to be rolled. Because the size and position of the subwindow are set in createparams (), the position attribute can be set to podefault. The caption and bordericon attributes are ignored and therefore do not need to be specified. Make sure that borderstyle is set to bssizeable, and borderwidth is set to 0. If these two attributes are set to other values, the child form and the main form will be inconsistent.

Other elements of the form
In many cases, apart from subordinate forms, the main form also contains other components, such as toolbar and status bar, in this case, when setting the X, Y, width, and height members of the tcreateparams struct, you must consider the toolbar and status bar. The child form should be coordinated with the toolbar at the top and the baseline status bar. Therefore, the code of the member who sets the tcreateparams struct should be:

Params. x = 0;
Params. Y = mainform-> toolbar-> height + 1;
Params. width = mainform-> clientrect. Right;
Params. Height = (mainform-> statusbar-> top-1)-Params. Y;

Note that Y is set to add 1 to the bottom of the toolbar, and the width of the child form is set to the width of the main form customer area. The height is calculated based on the top of the child form and status bar, it is basically the main form customer area between the bottom of the toolbar and the bottom of the status bar. These are all requirements for the subordinate form to "Reside" in the main form. You may have other features that you want to implement in the subform. I will leave these features to the end.

Set the main form
You must also set the main form to control its child form that is "hosted. First, remove the child forms from the automatically created forms list and create them as needed. If it is not removed from the list, it is automatically displayed when your application starts. You also need a variable to track the current active sub-forms, declare the following variable in the public area of the main form, tform * activechild; activechild is public, because the sub-forms need to access this variable. I will immediately demonstrate how to use this variable. Now let's write the code that shows the sub-form. First read the following program line and I will explain it.

Void _ fastcall tmainform: chart1click (tobject * sender)
{
If (activechild)
Delete activechild;

Tchartform * form = new tchartform (this );
Activechild = form;
Form-> show ();
Chart1-> checked = true;
Table1-> checked = false;
}

This method is the onclick processing handle of the menu item of the main form. I guess it is correct. This is the display of the tchartform subform. First, check whether the activechild variable is not 0. If there is an exciting activity subform, activechild will not be 0. If activechild is not 0, delete the pointer associated with this variable to destroy the active child form. Otherwise, the program stacks the child forms one by one. Create an instance of the tchartform class and assign the new operation to the activechild variable. In this way, activechild always contains a pointer pointing to the current child form. Finally, call the sow () method to display the child form. The last two lines of code ensure that a selected tag is displayed for the menu items displayed in the form or image. To complete the activechild variable discussion, I have to take you back to the child form unit for a while. Each subform contains the event handle of the following onclose event:

Void _ fastcall tchartform: formclose (tobject * sender,
Tcloseaction & Action)
{
Mainform-> activechild = 0;
Mainform-> chart1-> checked = false;
Action = cafree;
}

Note: When the form is destroyed, activechild of the main form is set to 0, and the menu items associated with the child form are set to unselected. The action parameter is set to cafree to notify VCL to release the memory associated with this form. You may wonder why the formclose handle contains the last two rows. The answer is that each subform has a close button to close the form. If you use the close button to close the form, you need to release the memory and uncheck menu items.

Additional features
The example program has at least one feature that has not yet been discussed, that is, if the child form is larger than the main form, you need to re-adjust the size of the main form to accommodate the child form. These statements are placed in the createparams () method of the subform. I have previously demonstrated a simple createparams () example, but I have not placed a statement to adjust the size of the main form. List B contains the complete createparams () method. The only difference from the previous display is that it contains the following statement:

If (width> mainform-> clientwidth)
Mainform-> clientwidth = width;
If (height> (mainform-> statusbar-> top-mainform-> toolbar-> height ))
Mainform-> clientheight = height +
Mainform-> toolbar-> height +
Mainform-> statusbar-> height;

These statements check whether the width of the sub-form is greater than the clientwidth attribute of the main form. If yes, the clientwidth of the main form is set to the width of the sub-form. The remaining lines do the same thing, but only target the customer Zone Height of the main form. The result of these statements is that the main form is always adjusted to fully accommodate the displayed subforms. The example program also takes into account the hour-long adjustment of the main form. If the size of the Main Window changes, the size of the child form must also change to the customer area filled with the main form. The following statement demonstrates the onresize event handle of the main form:

Void _ fastcall tmainform: formresize (tobject * sender)
{
If (activechild)

{
Activechild-> width = clientrect. Right;
Activechild-> Height = (mainform-> statusbar-> top-1 )-
Activechild-> top;
}

}

These statements are rather straightforward and do not need to be explained one by one. Note: Check the activechild variable to make sure that it is not 0 (that is, pointing to a subform). Obviously, if no subform is activated, you do not need to do anything in onresize. Other statements are the variants of the statements seen in createparams (). They simply calculate the new size of the child form and set the corresponding width and height attributes.

Conclusion
List A contains the code of the main form of the example program. List B shows the source code of the tchartform unit. The header file does not provide any meaningful statements or ttableform unit statements, because it is similar to the chatform unit. You can download the example program at www.reisdorph.com. It provides a clear method to replace the child form with the primary form. It is also an alternative to programs that can only display data to users in the form of a non-modal form, using a child form allows you to use the Form Designer to design your slave window and place the code for manipulating the child form in one place.

List A: mainu. cpp
# Include <VCL. h>
# Pragma hdrstop

# Include/"mainu. h /"
# Include/"chartu. h /"
# Include/"tableu. h /"

# Pragma resource/"*. DFM /"
Tmainform * mainform;

_ Fastcall tmainform: tmainform (tcomponent * owner)
: Tform (owner)
{
// Clear 0 to prevent random number inclusion
Activechild = 0;
// Open the data table
Table-> active = true;
}

Void _ fastcall tmainform: table1click (tobject * sender)
{
If (Table1-> checked) return;
If (activechild ){
Delete activechild;
Activechild = 0;
}

Ttableform * form = new ttableform (this );
// Assign the DBGrid: datasource attribute of DBGrid to the data source.
Form-> DBGrid-> datasource = datasource;
// Subform for tracking activity
Active = form;
Form-> show ();
Table1-> checked = true;
Chart1-> checked = false;
}

Void _ fastcall tmainform: chart1click (tobject * sender)
{
If (chart1-> checked) return;
If (activechild ){
Delete activechild;
Activechild = 0;
}

Tchartform * form = new tchartform (this );
Active = form;
Form-> show ();
Chart1-> checked = true;
Table1-> checked = false;
}

Void _ fastcall tmainform: formresize (tobject * sender)
{
If (activechild ){
Activechild-> width = clientrect. Right;
Activechild-> Height = (mainform-> statusbar-> top-1 )-
Activechild-> top;
}
}

List B: chartu. cpp
# Include <VCL. h>
# Pragma hdrstop

# Include/"chartu. h /"
# Include/"mainu. h /"

# Pragma resource/"*. DFM /"
Tchartform * chartform;

_ Fastcall tchartform: tchartform (tcomponent * owner)
: Tform (owner)
{
}

Void _ fastcall tchartform: createparams (tcreateparams & Params)
{
// Call the createparams method of the base class
Tform: createparams (Params );
// Subwindow type
Params. Style = ws_child | ws_clipsiblings;
// Set the parent to the main form
Params. wndparent = mainform-> handle;

Params. x = 0;
If (width> mainform-> clientwidth)
Mainform-> clientwidth = width;
If (height> (mainform-> statusbar-> top-mainform-> toolbar-> height ))
Mainform-> clientheight = height +
Mainform-> toolbar-> height +
Mainform-> statusbar-> height;
Params. Y = mainform-> toolbar-> height + 1;
Params. width = mainform-> clientrect. Right;
Params. Height = (mainform-> statusbar-> top-1)-Params. Y;
}

Void _ fastcall tchartform: formclose (tobject * sender,
Tcloseaction & Action)
{
Mainform-> activechild = 0;
Mainform-> chart1-> checked = false;
Action = cafree;
}

Void _ fastcall tchartform: closebtnclick (tobject * sender)
{
Close ();
}

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.