LMD VCL - LMD Packs: Difference between revisions

From LMD
Jump to navigation Jump to search
No edit summary
Line 28: Line 28:
Simply add wininet.lib to your project (file can be found in \lib directory of your C++ Builder / BDS / CRS installation). In recent IDEs you can also add<br>  
Simply add wininet.lib to your project (file can be found in \lib directory of your C++ Builder / BDS / CRS installation). In recent IDEs you can also add<br>  
<code>#pragma link "wininet.lib"</code><br> in your code.
<code>#pragma link "wininet.lib"</code><br> in your code.
==NG Serialization==
===How to serialize collections===
Serializing collections, including custom or standard collections (like TList) requires writing custom converters. For example, lets consider the folowing collection declaration:
<pre class="brush:delphi">
type
  TItem = class
  public
    X: Integer;
    Y: Integer;
  end;
  TItems = class(TObjectList<TItem>);
</pre>
To be able to serialize it, we need to declare a converter class, and '''associate''' this class with our collection using Converter attribute:
<pre class="brush:delphi">
type 
  TItemsConverter = class(TConverter)
  public
    function  GetReadMode: TReadMode; override;
    procedure Write(S: TSerializer; const V); override;
    procedure Read(D: TDeserializer; var V); override;
  end;
  [Converter(TItemsConverter)]
  TItems = class(TObjectList<TItem>);
</pre>
The converter can be implemented like this:
<pre class="brush:delphi">
function TItemsConverter.GetReadMode: TReadMode;
begin
  Result := rmFillRead; // Indicate fill-read mode.
end;
procedure TItemsConverter.Read(D: TDeserializer; var V);
var
  lst: TItems;
begin
  lst := TItems(V); // Since we work in fill-read mode,
                    // V already contains a reference to
                    // TItems instance; we should not
                    // create it here.
  lst.Clear;
  D.BeginArray;
  while D.HasNext do
    lst.Add(D.Value<TItem>);
  D.EndArray;
end;
procedure TItemsConverter.Write(S: TSerializer; const V);
var
  lst: TItems;
  i:  Integer;
begin
  S.BeginArray;
  lst := TItems(V);
  for i := 0 to lst.Count - 1 do
    S.Value(lst[i]);
  S.EndArray;
end;
</pre>
As can be seen, GetReadMode returns rmFillRead, which indicates that de-serializer should use fill-read mode. This means that no new TItems instance is created during de-serialization. This mode is especially usefull for collection like classes, because they usually owned by some other objects. For example, lets look at the following class:
<pre class="brush:delphi">
type 
  TOwner = class
  private
    FItems: TItems;
  public
    constructor Create;
    destructor  Destroy; override;
    property    Items: TItems read FItems;
  end;
constructor TOwner.Create;
begin
  inherited Create;
  FItems := TItems.Create;
end;
destructor TOwner.Destroy;
begin
  FItems.Free;
  inherited;
end;
</pre>
As can be seen, TItems collection is oqned by TOwner class. TOwner expose Items as read-only property, and thus, there no way to replace collection as a whole. Only collection content can be changed.
But, fortunately, TOwner class can be serialized and de-serialized, because TItems collection has fill-read mode converter:
<pre class="brush:delphi">
var
  src, dst: TOwner;
  stream:  TStream;
  s:        TBinarySerializer;
  d:        TBinaryDeserializer;
begin
  stream := TMemoryStream.Create;
  try
    src := TOwner.Create;
    src.Items.Add(TItem.Create);
    src.Items.Add(TItem.Create);
    src.Items.Add(TItem.Create);
    s := TBinarySerializer.Create(stream);
    s.Value(src);
    s.Free;
    stream.Position := 0;
    d  := TBinaryDeserializer.Create(stream);
    dst := d.Value<TOwner>;
    d.Free;
  finally
    stream.Free;
  end;
end;
</pre>
Please use the following link for more information about fill-read mode:
[http://www.lmd.de/downloads/tutorials/serialization/index.html?fill-read_mode.htm Fill-Read Mode]

Revision as of 18:06, 27 May 2015

[edit]

<< Back to Overview page

LMD ShellPack

Using Paste/Copy commands at runtime

Copy:

if assigned(LMDShellList1.selected) then
  LMDDoContextMenuVerb( LMDShellList1, (LMDShellList1.Selected as TLMDShellListItem).ShellItem, 'copy');

Paste:

LMDDoContextMenuVerb( LMDShellList2, LMDShellFolder2.ActiveFolder,'paste');

LMD RichPack

Which MS RichEdit DLL Version can I expect on a specific operating system?

Please check list of different RichEdit versions.

Searching for specific attributes

Q: I was trying out the LMD RTF wrapper (using BCB 6) and wanted to know what would be the best way to search for words or characters with a specific attribute. A:

  • Use FindTextEx
  • Check SelAttributes
    if attrs not ok then FindTextEx again.

LMD WebPack

[Linker Error] Unresolved external "InternetCloseHandle" referenced from

Simply add wininet.lib to your project (file can be found in \lib directory of your C++ Builder / BDS / CRS installation). In recent IDEs you can also add
#pragma link "wininet.lib"
in your code.