Difference between revisions of "LMD VCL - LMD Packs"

From LMD
Jump to: navigation, search
(4 intermediate revisions by 2 users not shown)
Line 3: Line 3:
 
==LMD ShellPack==
 
==LMD ShellPack==
 
===Using Paste/Copy commands at runtime===
 
===Using Paste/Copy commands at runtime===
 
+
Copy:
 +
<syntaxhighlight lang="delphi">
 +
if assigned(LMDShellList1.selected) then
 +
  LMDDoContextMenuVerb( LMDShellList1, (LMDShellList1.Selected as TLMDShellListItem).ShellItem, 'copy');
 +
</syntaxhighlight>
 +
Paste:
 +
<syntaxhighlight lang="delphi">
 +
LMDDoContextMenuVerb( LMDShellList2, LMDShellFolder2.ActiveFolder,'paste');
 +
</syntaxhighlight>
  
 
==LMD RichPack==
 
==LMD RichPack==
Line 19: Line 27:
 
===[Linker Error] Unresolved external "InternetCloseHandle" referenced from===
 
===[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<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.
+
<syntaxhighlight lang="cpp">
 
+
#pragma link "wininet.lib"
==NG Serialization==
+
</syntaxhighlight> in your code.
===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 13:10, 18 August 2017

[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.