FlexGraphics Software, Ltd. FAQ (frequently asked questions)  

 Main | Info | Download | Order | Support | FAQ | About | Russian


Q1: What is this library made for?

A1: Developing this library, we have tried to boost the speed of graphics output in the real time, since it was originally developed for SCADA. The library is poor for the drawing quality images (while it lacks anti-aliasing and other algorithms) and polygraphy.Top

Q2: How to use this library?

A2: For the sake of simplicity of source code and improving the speed it was decided to not support editing in IDE Delphi. Therefore, here is what the library can be used for:
  1. Creating all flex-objects on panel while the program is running (dynamically).
  2. Creating a static document in editor (e.g., FlexEdit) with all necessary data in its objects, loading the document to the panel immediately when the program starts, followed by performing actions over the loaded objects.
In both cases, you can create your own flex-objects for the implementation of necessary functionality in them (like, for instance, in the project "Demo Interactive Plan" door object.) Top

Q3: How are flex-objects stored in the panel?

A3: In the component, a document is stored in the following format:

  Layers: TFlexLayers
    Layer1: TFlexLayer
    Layer2: TFlexLayer
    . . .
  Schemes: TFlexSchemes
    Scheme1: TFlexScheme
      Box1: TFlexBox
      Ellipse1: TFlexEllipse
      Group1: TFlexGroup
        Box2: TFlexBox
        Box3: TFlexBox
      . . .
    Scheme2: TFlexScheme
      Box4: TFlexBox
    . . .

Each item in the Layers and Schemes tree (and even the very roots of Layers and Schemes) are flex-objects (TFlexControl's children.) Every flex-object has a list of flex-properties (the properties stored in the document) stored in TFlexControl.Props. Each flex-property is an instance of the class whose parent is TCustomProp. All children flex-objects are stored in the list TFlexControl.Controls. For example, the layer with the index 2 can be accessed via FlexPanel1.Layers.Controls[2] or even simpler - FlexPanel1.Layers[2].

Each flex-object on the scheme is assigned to the layer TFlexLayer. Objects in the Layers tree and the Schemes list along with the scheme objects TFlexScheme in the TFlexControl.Layer property always contain Nil.

Orders on the scheme are stored in the Z-order: the first object on the scheme is to be drawn first (all other objects will be drawn above it.) However, this order is affected by the belonging to a particular layer: Before drawing a portion of the scheme all objects on it are spit into lists by layers (each list contains objects on current layer) and then, following the layers order objects are drawn from those lists. Thus, if the first object on the scheme belongs to the topmost layer, it will overlap all objects on other layers but will be overlapped by another object that also belongs to the topmost layer. Top

Q4: How do I set object's coordinates?

A4: Flex-objects' coordinates are stored in the coordinate system of the parent object. The TFlexSchemes schemes list coordinates and the TFlexScheme scheme coordinates always contain (0, 0), and such system is called the document coordinates system. The units in this system depend on the value in the constant PixelScaleFactor of the FlexUtils module (see Q5) and by default 1000 units correspond to 1 pixel on the screen at the scale of 100%. Thus, we can say that coordinates of all objects on a scheme (whose parent is the scheme) belong to the document's coordinate system. Now, grouped objects' coordinates are set in relation to the TFlexGroup group object's coordinates on the scheme. Thus, if the Group1 group's coordinates (Left, Top) are (10000, 10000), and the Box2 object's coordinates are (0, 0), Box2's coordinates in the document's coordinate system will be (10000, 10000). You can get the position of any flex-object in the document's coordinate system through the TFlexControl.DocRect property (it is also available for writing.)

The point coodrinates of TFlexControl.Points are stored in the object's coordinate system; thus, the point (0, 0) in the document's coordinate system will correspond with the upper left corner of the rectangle TFlexControl.DocRect.

The conversion of document's coordinates to screen (panel) ones is performed with the reference to current scale TFlexPanel.Scale and to the offset of the document's upper left corner in relation to the preview window TFlexPanel.Origin. To convert a point from the document coordinate system to screen coordinate system, use the panel's method TFlexPanel.TransformPoint. For the reverse conversion, use TFlexPanel.UnTransformPoint.

Since flex-panel can output any portion of a document in any way defined by user, regardless of the current preview window, the Scale and Origin values may mismatch the actual values (for the preview window) while the drawing method TFlexPanel.PaintTo is running, they accept values specified in this method's parameters. Coordinates and sizes of the panel's client area (portion of document visible in it) in the document coordinate system are stored in the TFlexPanel.ClientDocRect property. Top

Q5: What are the "logical units", which measure flex-objects' dimensions? How do they relate to screen dimensions?

A5: One logical unit is 1/1000 of a pixel (one millipixel). With the scale of 100%, 1000 logical units will appear as 1 pixel on the screen. The factor is set by the constant PixelScaleFactor in the module FlexUtils. Such units have been used beginning with version 1.15, since working with larger scales caused major distortions. Top

Q6: How can I use flex-objects after loading documents to flex-panel?

A6: Here are the basic operations available for objects:

  1. Validate flex-object under the mouse pointer in the TFlexPanel.OnMouseMove event. At the same time, the property TFlexPanel.MouseControl stores the object being under the mouse pointer. If the object is a group, the property TFlexPanel.MouseSubControl stores a specific object being inside the group under the mouse pointer.

  2. Flex-objects can be searched for:
    • In the entire document, using the methods TFlexPanel.FindControl (by name), FindControlByID (by unique identifier), FindControlAtPoint (topmost in specific point).
    • In child flex-objects of the object TFlexControl.FindByID, TFlexControl.FindByName.
    • Search through all objects in sub-tree: functions FirstControl, NextControl.

  3. Access to objects' flex-properties by name. Example:
      Box0.Props['Brush'].Color := clBlue;
      MyEllipse.Props['Width'].Value := 10;

    Frequently used properties are placed in the public section. Example:
      MyEllipse.Props['Width'].Value := 10;

      MyEllipse.Width := 10;

    Any change of a flex-property that affects the appearance of a flex-object (TPropStyleItem, psNonVisual) causes the entire request to redraw the entire flex-object. Thus, when several objects are changed, the redraw calls will be grouped to a single one. Actually, you will not have to "draw" simply change the properties, and it will do the rest automatically.

  4. Flex-objects can be selected using the TFlexPanel.Select, UnSelect, UnselectAll methods or the flex-object's TFlexControl.IsSelected property. Different manipulations can be performed over selected objects (move, copy, delete, group, etc.) through the methods of TFlexPanel. See Q12.

  5. Create new flex-objects. Actually, you can create an entire document in TFlexPanel from scratch by calling constructors of the necessary flex-objects and assigning necessary values to them. See Q12.

  6. Create custom flex-object classes. An example is described in the module ACCtrls.pas, in "Demo Interactive Plan".

Q7: How do I create an object with predefined properties in FlexGraphics library and how do I register it?

A7: To create a new object you should create a TFlexControl inherited class. You should pre-define the following methods:
   - procedure CreateProperties;

    You should register method properties (create TCustomProp inherited classes) that should be saved in Flex-document file.

   - procedure ControlCreate;

    Object properties and initialization is performed. Usually the parent's ControlCreate method is called an then the new properties are initialized. To make the object visible you should set the Visible property to True.

   - procedure ControlDestroy;

    Allocated memory release etc. is performed. ATTENTION: created properties instances SHOULD NOT BE DELETED! They will be deleted when deleting the Props list.

   - procedure Paint(Canvas: TCanvas; var PaintRect: TRect);

    Total object repaint is performed. Object size and placement are defined in PaintRect rectangle. To speed up the output this method can repaint the needed rectangular area only. This area is defined in Owner.PaintRect.

   - function IsPointInside(PaintX, PaintY: integer): boolean;

    If the object shape is not square (or may be other than square) you should define whether the point (PaintX, PaintY) belongs to object or not.

   To integrate an object with FlexEdit you should also override the following methods:
   - class function GetToolInfo(ToolIcon: TBitmap; var Hint: string): boolean;

    If the object is to be added to FlexEdit editor palette the object must override this method and return an icon (24x24 pixels for FlexEdit) and tool tip text.

   - class function CursorInCreate: TCursor;

    Returns mouse cursor that appears in FlexEdit when creating a new object of this class. If the method is not overridden FlexEdit will use the default object creation cursor (cross).

  To make the object able to be loaded from and saved to Flex-files it should be registered by calling the RegisterFlexControl procedure. Usualy this is performed in module initialization section:

  New object creation example can be found in ACCtrls.pas module. Also you can find examples in Tutorial projects package.Top

Q8: Can I add custom properties to objects?

A8: There is a flex-property made specially for storing user data - TFlexControl.UserData. Its content is identical to a section of an ini-file, and its values are stored in the format of "property_name=value". Here is how you can access custom properties:
  with MyControl.UserData do
    Values['Result'] := Values['Value1'] + Values['Value2'];

If the value with the 'Result' name was missing in UserData, it will be created automatically. Here is how the value can be deleted by name:
  with MyControl.UserData do Delete(IndexOfName('Result'));

The class of the UserData flex-property is a child of the TStrListProp class; therefore, you can use this class' method to work with the data.

If you are creating a custom flex-object, you can add flex-properties in the method TFlexControl.CreateProperties (See Q2). Top

Q9: How do I add a flex-property to an object?

A9: To create a custom flex-property, create a child class for the TCustomProp class. Flex properties can be simple or complex. The simple ones can appear as string, list of strings or binary data. Simple properties can contain one value of a specified type (e.g., TIntProp, TStrListProp, etc.), while the complex ones are defined by several values of different types, which are to be defined in the published section of the complex property class (e.g., TBrushProp, TPictureProp, etc.)

The type of the flex-property is setting up in the FPropType field in the class constructor (if it differs from the default ptSimple.) Also, the methods GetPropValue, SetPropValue for obtaining/storing property value in a variable of the Variant type are to be redefined in the class. At the same time, the parameter PropName always contains an empty string for a simple flex-property and the published property name, which value is to be obtained/stored, for a complex property.

To display the value in the editor inspector, you will need to redefine the method GetDisplayValue, plus SetDisplayValue if writing value from inspector string is supported. For editing a complex flex-property, you can define an editor form class in the EditFormClass property or register the editor form for all of this class' flex-properties using the RegisterDefaultPropEditForm procedure. This way, calling of TCustomProp.Edit will create the form and pass the flex-property being edited in the TCustomForm.Tag parameter. Top

Q10: How do I add a flex-property to an object?

A10: An object's flex-are stored in the list TFlexControl.Props, which is created in the object constructor. Once the list is created, the method TFlexControl.CreateProperties is called; this is where the adding of flex-properties takes place. A property is added by simply creating an instance of a necessary class:
  FBrushProp := TBrushProp.Create(Props, 'Brush');

After that, you can customize the property's style using TCustomProp.Style:
  FBrushProp.Style := FBrushProp.Style + [psReadOnly];

The property's style can be customized at any time. Top

Q11: How can I output a flex-document to a TBitmap object?

A11: Any portion of a document can be output through the flex-panel's method TFlexPanel.PaintTo. Here you set the visible area and the scale to use for outputting the image. For instance, to output current scheme entirely at the scale of 100%, you can use the following procedure:

  procedure PaintToBitmap(Flex: TFlexPanel; Bitmap: TBitmap);
    Bitmap.Width := UnscalePixels(Flex.DocWidth);
    Bitmap.Height := UnscalePixels(Flex.DocHeight);
    Flex.PaintTo(Canvas, Rect(0, 0, Bitmap.Width, Bitmap.Height),
      Point(0, 0), 100, Nil, False, False, False, False);


Q12: How can I create flex-objects in programs?

A12: For that purpose, you simply create a flex-object through the Create constructor:
  Box := TFlexBox.Create(FlexPanel1, ActiveScheme, ActiveLayer);

The FlexPanel1 parameter here is mandatory, while the scheme and layer, to which the object being created is to be placed, can be defined later (set the constructor values to Nil). Once the object is created, set that object's position and sizes:
  Box.Left := 10000;
  Box.Top := 20000;
  Box.Width := 200000;
  Box.Height := 100000;

Now you can set other properties; for instance, fill the rectangle with lime color:
  Box.BrushProp.Color := clLime;

You can change these values any time later, which will change the position/size/appearance of the object in the panel component.

For performing operations over a group of objects, you will need to use flex-panel's methods. Example:
  // Create an ellipse
  Ellipse :=
    TFlexEllipse.Create(FlexPanel1, ActiveScheme, ActiveLayer);
  Ellipse.Left := 50000;
  Ellipse.Top := 60000;
  Ellipse.Width := 200000;
  Ellipse.Height := 100000;
  with FlexPanel1 do begin
    // Select the rectangle and the ellipse on the panel
    // Convert them to curves
    // Combine selected objects to a single one
    // Change the fill color to red
    Brush := TBrushProp(Selected[0].Props['Brush']);
    if Assigned(Brush) then Brush.Color := clRed;

The majority of methods for modifying objects are described in the help file, in the flex-panel section TFlexPanel. Top

Q13: How to make a poly-line or a polygon out of line in FlexEdit?

A13: Select the Line tool and draw a line, then draw a poly-line by keeping the Ctrl key pressed. To draw a polygon hold the Ctrl key, point the mouse cursor to the first point of line and adjoin it (the result of this action is that IsSolid property of the object will be set to True). To remove a polygon you should set IsSolid property of the object to False in object inspector.Top

Q14: Why when I set the object property to ShowHint=True the Hint text is not shown?

A14: The document in FlexGraphics library has InDesign property. When creating and editing a document this property is set to True so that the Hints do not come in the way while when viewing a document the InDesign property is set to False.Top

Q15: Why when I specify the Angle property value the text itself is not turned to that angle?

A15: Current version of FlexGraphics library supports text turning (rotation) for TrueType fonts only. Set the TrueType font; also set the AutoSize property to False to make the text rotation.Top

Q16: What is the purpose of Reference object property and how do I use it?

A16: Each document in FlexGraphics library may have inclined sub-documents or Schemes. This property is used for creation of complex references between schemes and interactive plans. If the object refers to another scheme then while InDesign=False the specified scheme will be show upon mouse click (see demo version).Top

Q17: Why the drawing process slows down dramatically when I use gradient fill?

A17: Try to use minimum number of gradient filld objects or use horizontal \ vertical fill - this will speed up the drawing process.Top

January 8, 2022
  - FlexGraphics v1.82 release !!!

What's new:
  - Support for Delphi/CBuilder 11 packages;
  - Minor bug fixes;

October 3, 2020
  - FlexGraphics v1.81 release

What's new:
  - Support for Delphi/CBuilder XE8, 10 - 10.4 packages;

September 17, 2014
  - FlexGraphics v1.78 release

What's new:
  - Support for Delphi/CBuilder XE4 - XE7 packages;

Our partners

Components and tools for developers

Main  | Info  | Download  | Order  | Support  | FAQ  | About  | Russian

Copyright © 2001-2022 by FlexGraphics Software. All rights reserved.
Designed by FlexGraphics Software.