• No results found

The Portable Version of DragTree

In document Mastering Delphi 7 (Page 194-199)

Because I use this program in numerous porting demonstrations, I've built a version you can compile as a native VCL application with Delphi and as a CLX application with Kylix. This is different from most other programs in this book, including the previous version of this same example, which can be ported to Delphi by using VisualCLX and also Qt on Windows. Following a different path once in a while can be instructive.

The first thing I had to do was use two different sets of uses statements, using conditional compilation. The unit of the PortableDragTree example begins as follows:

Qt, Libc, QGraphics, QControls, QForms, QDialogs, QStdCtrls, QComCtrls, QMenus, QTypes, QGrids;

{$ENDIF}

{$IFDEF MSWINDOWS}

Windows, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, Menus, Grids;

{$ENDIF}

A similar conditional directive is used in the initial portion of the implementation section, to include the proper resource file for the form (the two resource files are different):

{$IFDEF LINUX}

I've omitted some of the Windows-specific features anyway, so the only difference in code is in the FormCreate method. The program loads the data file from the user's default folder, not the same folder as the executable.

Depending on the operating system, the user's folder is the home directory (and the hidden file has a starting dot) or the specific My Documents area (available with a special API call):

procedure TForm1.FormCreate(Sender: TObject);

var path: string;

begin

{$IFDEF LINUX}

This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks.

filename := GetEnvironmentVariable('HOME') + filename := path + '\TreeText.txt';

{$ENDIF}

TreeView1.LoadFromFile (filename);

end;

Custom Tree Nodes

Delphi 6 added a few features to the TreeView controls, including multiple selection (see the MultiSelect and

MultiSelectStyle properties and the Selections array), improved sorting, and several new events. The key improvement, however, is letting the programmer determine the class of the tree view's node items. Having custom node items implies the ability to attach custom data to the nodes in a simple, object-oriented way. To support this technique, there is a new AddNode method for the TTreeItems class and a new specific event, OnCreateNodesClass. In the handler for this event, you return the class of the object to be created, which must inherit from TTreeNode.

This is a very common technique, so I've built an example to discuss it in detail. The CustomNodes example doesn't focus on a real-world case, but it shows a rather complex situation in which two different custom tree node classes are derived one from the other. The base class adds an ExtraCode property, mapped to virtual methods, and the subclass overrides one of these methods. For the base class, the GetExtraCode function simply returns the value; for the derived class, the value is multiplied to the parent node value. Here are the classes and this second method:

type

TMyNode = class (TTreeNode) private

FExtraCode: Integer;

protected

procedure SetExtraCode(const Value: Integer); virtual;

function GetExtraCode: Integer; virtual;

public

property ExtraCode: Integer read GetExtraCode write SetExtraCode;

end;

TMySubNode = class (TMyNode) protected

function GetExtraCode: Integer; override;

end;

function TMySubNode.GetExtraCode: Integer;

begin

Result := fExtraCode * (Parent as TMyNode).ExtraCode;

end;

With these custom tree node classes available, the program creates a tree of items, using the first type for the first-level nodes and the second class for the other nodes. Because you have only one OnCreateNodeClass event handler, the program uses the class reference stored in a private field of the form (CurrentNodeClass of type TTreeNodeClass):

procedure TForm1.TreeView1CreateNodeClass(Sender: TCustomTreeView;

var NodeClass: TTreeNodeClass);

begin

NodeClass := CurrentNodeClass;

end;

The program sets this class reference before creating nodes of each type—for example, with code like the following:

var

MyNode: TMyNode;

begin

CurrentNodeClass := TMyNode;

MyNode := TreeView1.Items.AddChild (nil, 'item' + IntToStr (nValue)) as TMyNode;

MyNode.ExtraCode := nValue;

Once the entire tree has been created, when the user selects an item, you can cast its type to TMyNode and access the extra properties (but also methods and data):

procedure TForm1.TreeView1Click(Sender: TObject);

var

MyNode: TMyNode;

begin

MyNode := TreeView1.Selected as TMyNode;

Label1.Caption := MyNode.Text + ' [' + MyNode.ClassName + '] = ' + IntToStr (MyNode.ExtraCode);

end;

This is the code used by the CustomNodes example to display the description of the selected node in a label, as you can see in Figure 5.14. Note that when you select an item within the tree, its value is multiplied for that of each parent node. There are certainly easier ways to obtain this effect, but having a tree view with item objects created from different classes of a hierarchy provides an object-oriented structure upon which you can base some very complex code.

Figure 5.14: The CustomNodes example has a tree view with node objects based on different custom classes, thanks to the OnCreateNodes-Class event.

This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks.

What's Next?

In this chapter, we have explored the foundations of the libraries available in Delphi for building user interfaces: the native-Windows VCL and the Qt-based CLX. I've discussed the TControl class, its properties, and its most important derived classes.

We explored some of the basic components available in Delphi, looking at both libraries. These components correspond to the standard Windows controls and some of the common controls, and they are extremely common in applications. You've also seen how to create main menus and pop-up menus and how to add extra graphics to some of these controls.

The next step is to explore in depth the elements of a complete user interface, discussing action lists and the Action Manager, and building some simple but complete examples. This is the topic of Chapter 6; then, Chapter 7 is devoted to forms.

Chapter 6: Building the User Interface

Overview

In Chapter 5, I discussed the core concepts of the TControl class and its derived classes in the VCL and VisualCLX libraries. Then, I provided a rapid tour of the key controls you can use to build a user interface, including editing components, lists, range selectors, and more. This chapter discusses other controls used to define the overall design of a form, such as the PageControl and TabControl. After these components, I'll introduce toolbars and status bars, including some slightly advanced features. This will give you the foundation material for the rest of the chapter, which covers actions and the Action Manager architecture.

Modern Windows applications usually have multiple ways of giving a command, including menu items, toolbar buttons, shortcut menus, and so on. To separate the actual commands a user can give from their multiple representations in the user interface, Delphi uses the concept of actions. In recent Delphi versions, this architecture has been extended to make the construction of the user interface on top of actions totally visual. You can now also let program users customize this interface easily, as is true in many professional programs. Finally, Delphi 7 adds to the visual controls supporting the Action Manager architecture a better and more modern UI, supporting the XP look and feel. On Windows XP, you can create applications that adapt themselves to the active theme, thanks to a lot of new internal VCL code.

This document was created by an unregistered ChmMagic, please go to http://www.bisenter.com to register it. Thanks.

In document Mastering Delphi 7 (Page 194-199)