Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Delphi Cookbook

You're reading from   Delphi Cookbook Recipes to master Delphi for IoT integrations, cross-platform, mobile and server-side development

Arrow left icon
Product type Paperback
Published in Jul 2018
Publisher
ISBN-13 9781788621304
Length 668 pages
Edition 3rd Edition
Languages
Tools
Arrow right icon
Authors (2):
Arrow left icon
Daniele Teti Daniele Teti
Author Profile Icon Daniele Teti
Daniele Teti
Daniele Spinetti Daniele Spinetti
Author Profile Icon Daniele Spinetti
Daniele Spinetti
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

Preface 1. Delphi Basics FREE CHAPTER 2. Becoming a Delphi Language Ninja 3. Knowing Your Friends – The Delphi RTL 4. Going Cross-Platform with FireMonkey 5. The Thousand Faces of Multithreading 6. Putting Delphi on the Server 7. Linux Development 8. Riding the Mobile Revolution with FireMonkey 9. Using specific platform features 10. Delphi and IoT 11. Other Books You May Enjoy

Creating a stack of embedded forms

Every modern browser has a tabbed interface. Also, many other kinds of multiple-view software have this kind of interface. Why? Because it's very useful. While you are reading one page, you can rapidly check another page and still come back to the first one at the same point you left some seconds ago. You don't have to redo a search or use a lot of mouse clicks to just go back to that particular point. You simply switch from one window to another window and come back to the first. I have seen too many business applications that are composed of a bunch of dialog windows. Every form is called with the TForm.ShowModal method. So, the user has to navigate into your application one form at time. This is simpler to handle for the programmer, but it's less user friendly for your customers. However, giving a switchable interface to your customer is not that difficult. In this recipe, we'll see a complete example of how to do it.

Getting ready

This recipe is a bit more complex than the previous recipes. So, I'll not explain all the code but only the fundamental parts. You can find the complete code in the book's code repository (Chapter1/RECIPE06).

Let's say we want to create a tabbed interface for our software that is used to manage product orders, sales, and invoices. All the forms must be usable at the same time, without us having to close the previous one. Before we begin, the following screenshot is what we want to create:

Figure 1.12: The main form containing seven embedded child forms

How it works...

The project is composed of a bunch of forms. The main form has TTabControl, which allows us to switch between the active forms. All embedded forms inherit from EmbeddableForm. The most important one is the Show method shown here:

procedure TEmbeddableForm.Show(AParent: TPanel); 
begin 
  Parent := AParent; 
  BorderStyle := bsNone; 
  BorderIcons := []; 
  Align := alClient; 
  Show; 
end; 
Note that all the forms apart from the main form have been removed from the Auto-Create Form list (you can access the list by going to Project | Options | Forms).

All the other forms descend from EmbeddableForm and are added to TTabControl on the main form, with a line of code similar to the following one:

procedure TMainForm.MenuOrdersClick(Sender: TObject); 
begin 
  AddForm(TForm1.Create(self)); 
end; 

The AddForm method is in charge of adding an actual instance of a form into the tabs, keeping a reference to it. The following code shows how it is done:

// Add a form to the stack 
procedure TMainForm.AddForm(AEmbeddableForm: TEmbeddableForm); 
begin 
  AEmbeddableForm.Show(Panel1); 
  // each tab show the caption of the containing form and    
  // hold the reference to it 
  TabControl1.Tabs.AddObject(
AEmbeddableForm.Caption, AEmbeddableForm); ResizeTabsWidth; ShowForm(AEmbeddableForm); end;

Other methods are in charge of bringing an already created form to the front when a user clicks on the Related tab, and then to close a form when the Related tab is removed (check out the ShowForm and WMEmbeddedFormClose methods).

There is a bit of code, but the concepts are simple:

  • When we need to create a new form, we add it in the TabControl1.Tabs property. The caption of the form is the caption of the tab, and the object is the form itself. This is what the AddForm method does with the following line:
TabControl1.Tabs.AddObject(AEmbeddableForm.Caption, AEmbeddableForm); 
  • When a user clicks on a tab, we have to find the associated form by cycling through the TabControl1.Tabs.Objects list and bringing it to the front.
  • When a form asks to be closed (sending a WM_EMBEDDED_CLOSE message), we have to set the ParentWantClose property and then call the Close method of the correspondent form.
  • If the user wants to close a form by closing the corresponding tab (in the recipe code, there is TPopMenu connected to TabControl, which is used to close a form with a right-click), we have to call the Close method on the corresponding form.
  • Every form frees itself in the OnClose event handler. This is done once for
    all the forms in the TEmbeddableForm.CloseForm event handler, using the caFree action.

There's more...

Embedding a form into another TWinControl is not difficult and allows us to create flexible GUIs without using TPageControl and Frames. For the end user, this multi-tabbed GUI is probably more familiar because all modern browsers use it, and your user may already know how to use a browser with different pages or screens open. From a developer's point of view, the multi-tabbed interface allows for much better programming patterns and practices. This technique can also be used for other scenarios where you have to embed one screen into another.

More flexible (and complex) solutions can be done involving the use of Observers, but in simple cases, this recipe's solution, based on Windows Messaging, is enough.

More information about the Observer design pattern can be found at http://sourcemaking.com/design_patterns/observer/delphi.

Other interesting solutions that don't rely on Windows Messaging and so are also cross-platform include the following:

Code in this recipe can be used with every component that uses TStringList to show items (TListBox, TComboBox, and so on) and can be adapted easily for other scenarios.

In the recipe code, you'll also find a nice way to show status messages generated by the embedded forms and a centralized way to show application hints in the status bar.

You have been reading a chapter from
Delphi Cookbook - Third Edition
Published in: Jul 2018
Publisher:
ISBN-13: 9781788621304
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image