Friday, August 29, 2014

Difference between Owner and Parent in Delphi

Difference between Owner and Parent in Delphi

Parent is the Window control where the control is displayed. Owner is the component responsible for making sure it's destroyed. Parent refers to the component that another component is contained in, such as TForm, TGroupBox or a TPanel. If one control (parent) contains others, the contained controls are child controls of the parent.

Example of Owner and Parent

Whenever we try add a button on a panel in a form, we try to make an invisible connection between the components. When a component is dropped on a form at design time, the owner is the form and the parent is the container on which it is dropped.

As we add the button on the panel, the panel automatically is set as the parent of the button while the form becomes the owner.  

Another example, drop a group box on a form. Its owner and parent are both the form. Drop a check box on the group box. Its owner is the form and its parent is the group box.

Parent is required to make a control visible

For a component to be visible, it must have a parent to display itself within. Controls that appear on the screen need to know where to paint themselves, hence the parent property. It specifies the visual container for the control. This property must be specified before a control can be displayed. When you want to create a TButton at run-time, it is important that we remember to assign a parent - the control that contains the button. 

The Parent component on the other end determines how the child (i.e. contained component is to be displayed). All the properties like left, top etc are relative to the parent component.

Owner is Readonly while Parent can be changed

Owner property is a read only property and cannot be modified, however parent for a control can be assigned and chagned easily at runtime. The Owner is being set while invoking the create constructor and becomes a read-only property so can't be changed later on.

Allocating and Freeing the memory

The Owner component is responsible for freeing the allocated memory of the owned components. Form is the owner of all the components residing inside it. So whenever the form is destroyed, all the components memory is freed automatically. This is the purpose of ownership.

HasParent Property

Not all components have the Parent. Many forms do not have a Parent. For example, forms that appear directly on the Windows desktop have Parent set to nil. A component's HasParent method returns a boolean value indicating whether or not the component has been assigned a parent.

Parent Property

We use the Parent property to get or set the parent of a control. If we try to create a new control, then we need to set the parent property of the control to make it visible. For example, 

Button1.Parent := Panel1;

Above code has set Panel1 as the parent of Button1.

Difference between Components and Controls in Delphi

Difference between Components and Controls in Delphi

Controls are the visible elements on the Delphi Forms to which you can focus and interact. All the controls are components and vice versa is not true. So we can say that Controls are the subset of Components in Delphi.

TComponent is the common ancestor of all component objects in Delphi. TControl is the abstract base class for all visual components. Everything that goes into the component palette is a Component. Everything that goes into the component and is something that the user of the program can control by using mouse or keyboard is a Control.

For example: TTimer component is a component that you can place on a form, but it is not visible to the end-user. So TTimer is only the component but not a control in Delphi. Other examples like TTimer are TXMLDocument, TDatabase, TQuery, TTable, TDataSet, TDataSource etc. These all components play a vital role but never appear in front of the end user.

A TEdit or TButton is visible and can be controlled by the user (you can add events to TEdit and TButton and with those events a user can actually focus/select/click on the TEdit and TButton components). So both TEdit and TButton are the components as well as controls in Delphi. 

A control takes up more resources than a component because a control needs extra info about how to draw itself.

Thursday, August 21, 2014

How to create and extract ZIP files in Delphi XE6?

How to create and extract ZIP files in Delphi XE6?

Delphi provides System.Zip unit for creating ZIP files. System.Zip unit contains a simple ZIP extractor and creator class named TZIPFile. TZIPFile class mainly has three methods which are used to create and extract zip files:

ZipDirectoryContents: Creates the zipped file
IsValid: Validates the zip file
ExtractZipFile: Extracts the zip file

Following is the code snippet in Delphi to create a zip file.

uses System.Zip;

TZIPFile.ZipDirectoryContents('C:\FolderToZip', 'C:\ZippedFolder.zip');

Following is the code snippet in Delphi to extract a zip files. 

uses System.Zip;

ZipFile := 'ZippedFolder.zip'; //This is my zip file
if TZipFile.IsValid(ZipFile) then //Validate zip file
begin
  TZipFile.ExtractZipFile(ZipFile, 'C:\DestinationDirectory'); //Extract the zip file
end
else
begin
  ShowMessage('Zip File is not valid');
end;

Friday, August 1, 2014

How to create XML document in Delphi XE4 using IXMLDOCUMENT and IXMLNODE?

How to create XML document in Delphi XE4 using IXMLDOCUMENT and IXMLNODE?

Following is the self explanatory code in Delphi XE4 to create XML document using IXMLDOCUMENT and IXMLNODE interfaces. You should have XMLIntf and XmlDoc units in your uses section. Following CreateXMLinDelphi Delphi procedure creates an XML named MyXML in D drive.

procedure CreateXMLinDelphi;
var
  XML : IXMLDOCUMENT;
  RootNode, CurNode : IXMLNODE;
begin
  XML := NewXMLDocument;
  XML.Encoding := 'UTF-8';
  XML.Options := [doNodeAutoIndent];
  RootNode := XML.AddChild('ParentNode');
  CurNode := RootNode.AddChild('ChildNode1');
  CurNode.Text := 'ChildNode Text 1';
  CurNode := RootNode.AddChild('ChildNode2');
  CurNode.Text := 'ChildNode Text 2';
  XML.SaveToFile('D:\MyXML.xml');
  ShowMessage('XML created successfully');
end;

The above code generates following XML document:

<?xml version="1.0" encoding="UTF-8"?>
<ParentNode>
  <ChildNode1>ChildNode Text 1</ChildNode1>
  <ChildNode2>ChildNode Text 2</ChildNode2>
</ParentNode>

How to create an XTR file from XML in Delphi XE4 using XML Mapper?

How to create an XTR file from XML in Delphi XE4 using XML Mapper?


By using Delphi XE4 RAD Studio, you can create an XTR file from the given XML file using XML Mapper. XML Mapper Tool is provided in RAD Studio XE4 under Tools -> XML Mapper.

Following are the steps to create an XTR file from XML in Delphi XE4 using XML Mapper:

1. Open the XML Mapper Tools from RAD Studio. 


Now load an XML. In my case I am loading following simple XML:

<?xml version="1.0" encoding="UTF-8"?>
<Parent>
  <Child1>ABC</Child1>
  <Child2>XYZ</Child2>
</Parent>

All the nodes will appear on the left section of XML Mapper.

2. Right click on left section and select "Select All Children" option. Transformation will be created on the middle section.

3. Right click on left section again and select "Create Datapacket from XML". You will see the generated datapacket on the right section of the XML Mapper.

4. Hit "Create and Test Transformation" button in the middle section of XML Mapper.

5. Right click on the right section and select "Clear". A popup will appear asking you "Save changes to Transformation to Datapacket?".

6. Click Yes and save that XTR file.

I got following XTR file corresponding to the above XML file:

<XmlTransformation Version="1.0"><Transform Direction="ToCds" DataEncoding="UTF-8"><SelectEach dest="DATAPACKET\ROWDATA\ROW" from="\Parent"><Select dest="@Child1" from="\Child1"/><Select dest="@Child2" from="\Child2"/></SelectEach></Transform><XmlSchema RootName="Parent"><![CDATA[<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="Parent" type="ParentType"/>
  <complexType xmlns="http://www.w3.org/2001/XMLSchema" name="ParentType">
    <sequence>
      <element name="Child1" type="Child1Type"/>
      <element name="Child2" type="Child2Type"/>
    </sequence>
  </complexType>
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="Child1" type="Child1Type"/>
  <simpleType xmlns="http://www.w3.org/2001/XMLSchema" name="Child1Type">
    <restriction base="xs:string"/>
  </simpleType>
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="Child2" type="Child2Type"/>
  <simpleType xmlns="http://www.w3.org/2001/XMLSchema" name="Child2Type">
    <restriction base="xs:string"/>
  </simpleType>
</xs:schema>]]></XmlSchema><CdsSkeleton/><XslTransform/><Skeleton><![CDATA[<?xml version="1.0"?><DATAPACKET Version="2.0"><METADATA><FIELDS><FIELD attrname="Child1" fieldtype="string" WIDTH="3"/><FIELD attrname="Child2" fieldtype="string" WIDTH="3"/></FIELDS><PARAMS/></METADATA><ROWDATA/><METADATA><FIELDS><FIELD attrname="Child1" fieldtype="string" WIDTH="3"/><FIELD attrname="Child2" fieldtype="string" WIDTH="3"/></FIELDS><PARAMS/></METADATA><ROWDATA/></DATAPACKET>
]]></Skeleton></XmlTransformation>

Friday, July 4, 2014

EOleException error raised with message catastrophic failure or access is denied in Delphi

EOleException error raised with message catastrophic failure or access is denied in Delphi

While calling DLLs from my application using safecall, I was getting EOleException error raised with message catastrophic failure. When I switched to stdcall, I started getting EOleException error raised with message access is denied for some calls. So, I thought to dive deep into the root cause of the error and tried to understand what exactly EOleException is in Delphi?

As per documentation:

EOleException is the exception class for OLE automation errors that occur in methods or properties of an object.

EOleException is the exception class for errors specific to the OLE IDispatch interface.

EOleException is raised when an error occurs in the middle of a method call from IDispatch. EOleException is generated when a server receives a failure return value from a property or method that was called with the IDispatch interface Invoke method.

When an error occurs, objects invoked through IDispatch can return essential information about the exception, including the source of the error, error code, description, help file, and ID number for context-sensitive help. EOleException captures this information, and the error description and ID number (if available) are included in a message generated by the constructor; the other information is stored in the Source and HelpFile properties defined for EOleException and the ErrorCode property inherited from EOleSysError.

Solution:

1. Try catching the error

try
  ....
  ....
except 
  on e: EOleException do
  begin
    ....
    .... 
  end;  
end;

2. Ignore the error

To stop Delphi from breaking, you will need to configure Delphi to ignore the exception by telling it that the application will handle the exception. Go to Tools > Debugger Options, on the "Language Exceptions" tab add "EOleException". Ensure that it is ticked, which tells the Delphi environment to ignore the exception (and let the code run).

Wednesday, June 25, 2014

WPF Page Hosted Windows Applications and XAML Browser Applications (XBAPs)

WPF Page Hosted Windows Applications and XAML Browser Applications (XBAPs)

In WPF, you can also make page based applications. These page based applications are of two types:

1. Pages Hosted in Windows Application
2. Stand-alone XAML Browser Application(XBAPs)

Lets try to understand these WPF Page based applications:

1. Pages Hosted in Windows Application

In this approach, you create your windows application and host some of the pages in that Windows application using NavigationWindow or Frame. This approach is generally used in WPF applications to integrate some kind of wizard in your application, to show some help contents and documentation.

Hosting Pages in Navigation Window

System.Windows.Controls.Page class is used as top level container instead of Windows. 

<Page...>
...
...
</Page>

But actually, there is one more top level container known as NavigationWindow (derives from Windows class) in which Page container is hosted. The NavigationWindow looks like an ordinary window aside from the backward and forward buttons that appear in the bar at the top. Page class is derived directly from FrameworkElement class. You can add a page to any WPF project. Just choose Project --> Add Page in visual studio.

Hosting Pages in other Window

You have to use Frame class to host your page inside other windows. You can use several frames in your window. You have to use the Source property of the Frame class to point to the page which you want to host.

<Window...>
  ....
  ....
  <Frame Source="Page2.xaml"></Frame>
  ....
  ....
</Window>

Hosting Pages in other Pages

You can also host your page into another page. Again you have to use Frames for this task. Just keep a frame container in other page where you want to host your page.

Ways to move from one page to another:

1. Forward and Back Button:

Set Page.ShowNavigationUI property set to true to show the forward and back button. By default, the property is set to true. There is also one more property called NavigationUIVisibility property which you can use to hide/show the Navigation buttons. By default its value is Automatic. But you can set it to Hidden or Visible as per your need.

2. Hyperlinks

Hyperlinks include NaviageUri property using which you can jump from one page to another.

Example: 

Navigating to other page: 

<Textblock>Click <Hyperlink NavigateUri="Page2.xaml">here</Hyperlink></TextBlock>

Fragment Navigation: Navigating to other page and at specific control on that: 

<Textblock>Click <Hyperlink NavigateUri="Page2.xaml#myTextBox">here</Hyperlink></TextBlock>

You will land on Page2.xaml and scroll up to the myTextBox control. But myTextBox control will not have any focus.

Navigating to websites:

<Textblock>Click <Hyperlink NavigateUri="http://theprofessionalspoint.blogspot.com">here</Hyperlink></TextBlock>

2. Stand-alone XAML Browser Application(XBAPs)

Page Based Applications run directly on IE or Firefox and you don't have to install this application. Just point your browser to correct location. This model is called XBAP. Client system must have .NET framework installed to run the XBAP application. The XBAP applications have limited permissions like XBAP applications cannot write files, cannot interact with system resources and registry, cannot connect to databases etc. But you can give permissions to XBAP applications when required.

To create XBAP application, you have to choose WPF Browser Application template in Visual Studio. After that if you see csproj file, you will find these four elements which point that it is a XBAP application:

<HostInBrowser>True</HostInBrowser>
<Install>False</Install>
<ApplicationExtension>.xbap</ApplicationExtension>
<TargetZone>Internet</TargetZone>

Related Article: To know the difference between Windows and Page Controls, visit my previous post.