<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>LMD Innovative Blog &#187; Snippets</title>
	<atom:link href="http://blog.lmd.de/category/snippets/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.lmd.de</link>
	<description>News, Tutorials</description>
	<lastBuildDate>Mon, 16 Jan 2012 18:38:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>New Windows 7 API support for Taskbar &#8211; Part 1</title>
		<link>http://blog.lmd.de/2009/12/new-windows-7-api-for-taskbar-part-1/</link>
		<comments>http://blog.lmd.de/2009/12/new-windows-7-api-for-taskbar-part-1/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 17:16:53 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[taskbar]]></category>
		<category><![CDATA[windows 7]]></category>

		<guid isPermaLink="false">http://blog.lmd.de/?p=87</guid>
		<description><![CDATA[The latest OS release from Microsoft introduces to us a lot of new features that (can) make life of developers easier and improve usability of own applications. This post is about small part of new Windows API that allows to customize taskbar button of your application. Pictures and source code are telling more than 1000 [...]]]></description>
			<content:encoded><![CDATA[<p>The latest OS release from Microsoft introduces to us a lot of new features that (can) make life of developers easier and improve usability of own applications. This post is about small part of new Windows API that allows to customize taskbar button of your application.<br />
<span id="more-87"></span><br />
Pictures and source code are telling more than 1000 words, hence we start immediately with practical examples:<br />
Here is picture of what we will get after compiling <a href="http://blog.lmd.de/uN">sample project</a> &#8211; we will create project that has buttons on it&#8217;s taskbar thumbnail, that allow to control progressbar and another part is reflect progressbar state on application taskbar button:</p>
<p><div id="attachment_90" class="wp-caption alignnone" style="width: 546px"><a rel="lightbox[screenshot1.png]" href="http://blog.lmd.de/La" title="windows7-part1-1"><img class="size-full wp-image-90 cboxModal" title="windows7-part1-1" src="http://blog.lmd.de/La" alt="Sample project screenshot. Windows 7" width="536" height="249" /></a><p class="wp-caption-text">Sample project screenshot. Windows 7</p></div><strong>NB #1</strong> To compile code from this post you should have updated units from Delphi 2010 or unit from LMD Tools 2010 &#8211; LMDWindows7Utils.pas</p>
<p><strong>NB #2</strong> All manipulatations with taskbar buttons must be done after button will be created, to catch this moment we should subscribe to WM_TASKBARBUTTONCREATED event, that must firstly registered by RegisterWindowMessage(&#8216;TaskbarButtonCreated&#8217;); &#8211; I reccomend you to add this registration to initialization section of unit with your form:</p>
<pre class="brush:delphi">//.....//
initialization
  WM_TASKBARBUTTONCREATED := RegisterWindowMessage('TaskbarButtonCreated');
end.</pre>
<p><strong>NB #3</strong> You must be sure that Application.MainFormOnTaskbar is True; or drop on form TLMDFormVista for delphi 6-2005 versions</p>
<p>Now, when we registered message we can handle it in WndProc method to setup taskbar button:</p>
<pre class="brush:delphi">type
  TForm8 = class(TForm)
    Timer1: TTimer;
    ImageList1: TImageList;
    ProgressBar1: TProgressBar;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    FTick: Int64;
    FButtons: array[0..2] of TThumbButton;
    FNormalIcon: Cardinal;
    FPauseIcon: Cardinal;
    FTaskBar: ITaskbarList3;
  protected
    procedure WndProc(var Message: TMessage); override;
    { Private declarations }
  public
    { Public declarations }
  end;
//...//
procedure TForm8.WndProc(var Message: TMessage);
begin
  inherited;
  // Is tasbar button created?
  if Message.Msg = WM_TASKBARBUTTONCREATED then
  begin
    // Create instance of ITaskbarList3
    CoCreateInstance(CLSID_TaskbarList, nil, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, FTaskBar);
    // Init
    FTaskBar.HrInit;
    // This method set progress state of tasbar button.
    // Button has next states: error, paused, normal and indetermintate
    FTaskBar.SetProgressState(Handle, TBPF_NORMAL);
    FNormalIcon := LoadIcon(0, IDI_ASTERISK);
    FPauseIcon := LoadIcon(0, IDI_WARNING);
    // Set overlay icon for taskbar button - "!" - asterix
    FTaskBar.SetOverlayIcon(Handle, FNormalIcon, 'In progress');

    // Buttons setup
    // Set imagelist handle that contains glyphs for our buttons
    FTaskBar.ThumbBarSetImageList(Handle, ImageList1.Handle);
    // This identificator will be used to determinate what button pressed
    FButtons[0].iId := 40001;
    FButtons[0].dwFlags := THBF_ENABLED;
    FButtons[0].iBitmap := 0;
    StringToWideChar('Reset', FButtons[0].szTip, 260);
    FButtons[0].dwMask := THB_BITMAP or THB_FLAGS or THB_TOOLTIP;

    FButtons[1].iId := 40002;
    FButtons[1].dwFlags := THBF_DISABLED;
    FButtons[1].iBitmap := 1;
    StringToWideChar('Play', FButtons[1].szTip, 260);
    FButtons[1].dwMask := THB_BITMAP or THB_FLAGS or THB_TOOLTIP;

    FButtons[2].iId := 40003;
    FButtons[2].dwFlags := THBF_ENABLED;
    FButtons[2].iBitmap := 2;
    StringToWideChar('Pause', FButtons[2].szTip, 260);
    FButtons[2].dwMask := THB_BITMAP or THB_FLAGS or THB_TOOLTIP;
    // Add buttons to thumbnail
    FTaskBar.ThumbBarAddButtons(Handle, 3, @FButtons[0]);
    FTaskBar.SetThumbnailTooltip(Handle, 'Test');
    Timer1.Enabled := True;
  end;
end;</pre>
<p>To handle buttons click we need to catch WM_COMMAND message, WParamLo field will contains id of clicked button:</p>
<pre class="brush:delphi">procedure TForm8.WndProc(var Message: TMessage);
begin
  //...//
  if Message.Msg = WM_COMMAND then
  begin
    // Handle 'Reset' button
    if Message.WParamLo = 40001 then
    begin
      Timer1.Enabled := True;
      FTaskBar.SetProgressState(Handle, TBPF_NORMAL);
      FTick := 0;
    end;
    // Handle 'Play' button
    if Message.WParamLo = 40002 then
    begin
      // Run timer again
      Timer1.Enabled := True;
      FTaskBar.SetProgressState(Handle, TBPF_NORMAL);
      // Set overlay icon to asterix icon
      FTaskBar.SetOverlayIcon(Handle, FNormalIcon, 'In progress');
      ProgressBar1.State := pbsNormal;
      // Disable 'Play' button
      FButtons[1].dwFlags := THBF_DISABLED;
      // Enable 'Pause' button
      FButtons[2].dwFlags := THBF_ENABLED;
      // Update buttons
      FTaskBar.ThumbBarUpdateButtons(Handle, 3, @FButtons[0])
    end;
    // Handle 'Pause' button. Almost the same as for 'Play'
    if Message.WParamLo = 40003 then
    begin
      Timer1.Enabled := False;
      FTaskBar.SetProgressState(Handle, TBPF_PAUSED);
      FTaskBar.SetOverlayIcon(Handle, FPauseIcon, 'Paused');
      ProgressBar1.State := pbsPaused;
      FButtons[1].dwFlags := THBF_ENABLED;
      FButtons[2].dwFlags := THBF_DISABLED;
      FTaskBar.ThumbBarUpdateButtons(Handle, 3, @FButtons[0])
    end;
  end;
end;</pre>
<p>And finally OnTimer handler code:</p>
<pre class="brush:delphi">procedure TForm8.Timer1Timer(Sender: TObject);
begin
  FTaskBar.SetProgressValue(Handle, FTick, 200);
  ProgressBar1.Position := FTick;
  Inc(FTick);
  // It's all?
  if FTick &gt;= 200 then
  begin
    // Set indeterminate progress mode for tasbar button
    FTaskBar.SetProgressState(Handle, TBPF_INDETERMINATE);
    Timer1.Enabled := False;
  end;
end;</pre>
<p>That&#8217;s all for &#8220;Part 1&#8243; &#8211; I hope that it will be useful for someone.</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.lmd.de/2009/12/new-windows-7-api-for-taskbar-part-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The OnUserRule and OnTextChangedAt events of the TLMDMaskEdit control</title>
		<link>http://blog.lmd.de/2009/11/the-onuserrule-and-ontextchangedat-events-of-the-tlmdmaskedit-control/</link>
		<comments>http://blog.lmd.de/2009/11/the-onuserrule-and-ontextchangedat-events-of-the-tlmdmaskedit-control/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 21:10:37 +0000</pubDate>
		<dc:creator>vbocharov</dc:creator>
				<category><![CDATA[LMD-Tools]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[edit controls]]></category>
		<category><![CDATA[lmdtools]]></category>

		<guid isPermaLink="false">http://blog.lmd.de/?p=70</guid>
		<description><![CDATA[Once again, many thanks to Roddy Pratt for the subject of this post. The OnUserRule event serves to check if entered symbol is correct for a given place when MaskType = meMask and there is an &#8220;r&#8221; letter in the mask. For example, if Mask = &#8216;rr&#8217;, following OnUserRule handler allows to enter &#8220;aa&#8221;, &#8220;ab&#8221;, [...]]]></description>
			<content:encoded><![CDATA[<p>Once again, many thanks to Roddy Pratt for the subject of this post.<br />
The <strong>OnUserRule</strong> event serves to check if entered symbol is correct for a given place when MaskType = <em>meMask</em> and there is an &#8220;r&#8221; letter in the mask. For example, if Mask = &#8216;rr&#8217;, following <strong>OnUserRule</strong> handler allows to enter &#8220;aa&#8221;, &#8220;ab&#8221;, &#8220;ba&#8221;, &#8220;bb&#8221; strings only:</p>
<pre class="brush:delphi;gutter:false">procedure TForm1.LMDMaskEdit1UserRule(Sender: TObject; var Ok: Boolean;
   c: WideChar; at: Integer);
begin
  ok := ( c = 'a' ) or ( c = 'b' );
end;</pre>
<p>While implementing some kind of tricky user rule, it is very easy to yield to temptation of changing text with <strong>OnUserRule</strong> event.<br />
This is what should never be done unless you have some free hours to debug unexpected behavior of your construction.</p>
<p><span id="more-70"></span></p>
<p>So, the message of this post is: do not use the <strong>OnUserRule</strong> event  for changing the Text while it is being checked.<br />
You should use the <strong>OnTextChangedAt</strong> for this purposes.</p>
<p>Here is an example of how to modify text while user is entering characters: LMDMaskEdit control with a custom rule ( Mask = &#8216;rr&#8217; ) that allows entry of  2-digit numbers between 00 and 23 (including bounds). If a number is greater than 23 is entered, then the units digit is automatically set to 3.</p>
<pre class="brush:delphi;gutter:false">procedure TForm1.LMDMaskEdit1UserRule(Sender: TObject; var Ok: Boolean;
   c: WideChar; at: Integer);
begin
  case at of
    1: ok := ( Pos(AnsiChar(c), '012' ) &gt; 0);
    2: ok := ( (Pos(AnsiChar(LMDMaskEdit1.Text[1]), '012' )
         &gt; 0) ) and
        ( (Pos(AnsiChar(c), '0123456789' ) &gt; 0) ) ;
  end;
end;

procedure TForm1.LMDMaskEdit1TextChangedAt(sender: TObject; At: Integer);
begin
  if (at = 2) and (Pos(LMDMaskEdit1.BlankChar,
    LMDMaskEdit1.Text) = 0) then
    if strtoint(LMDMaskEdit1.Text) &gt; 23 then
      LMDMaskEdit1.Text := '23';
end;</pre>
<p>Note that LMDMaskEdit1.TextChangedAt can be simplified in this example if<br />
BlankChar = &#8217;0&#8242;:</p>
<pre class="brush:delphi;gutter:false">procedure TForm1.LMDMaskEdit1TextChangedAt(sender: TObject; At: Integer);
begin
  if (at = 2)  then
    if strtoint(LMDMaskEdit1.Text) &gt; 23 then
      LMDMaskEdit1.Text := '23';
end;</pre>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.lmd.de/2009/11/the-onuserrule-and-ontextchangedat-events-of-the-tlmdmaskedit-control/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New look for LMD Calendar</title>
		<link>http://blog.lmd.de/2009/10/new-look-for-lmd-calendar/</link>
		<comments>http://blog.lmd.de/2009/10/new-look-for-lmd-calendar/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 21:00:07 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[LMD VCL]]></category>
		<category><![CDATA[LMD-Tools]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[lmdtools]]></category>
		<category><![CDATA[newlook]]></category>

		<guid isPermaLink="false">http://blog.lmd.de/?p=28</guid>
		<description><![CDATA[Do you think that TLMDCalendar looks a little bit outdated? What about this: Yes &#8211; it&#8217;s still well known TLMDCalendar, and here is the DFM snippet of it: object LMDCalendar1: TLMDCalendar Left = 48 Top = 87 Width = 234 Height = 225 BackFX.AlphaBlend.FillObject.Style = sfGradient BackFX.AlphaBlend.FillObject.AlphaLevel = 255 BackFX.FlipHorizontal = True BackFX.Buffered = True Bevel.BorderColor = [...]]]></description>
			<content:encoded><![CDATA[<p>Do you think that TLMDCalendar looks a little bit outdated? What about this:</p>
<div id="attachment_35" class="wp-caption alignnone" style="width: 255px"><img class="size-full wp-image-35" title="LMDCalendar" src="http://blog.lmd.de/wp-content/uploads//LMDCalendar.png" alt="Improved look of TLMDCalendar" width="245" height="238" /><p class="wp-caption-text">Improved look of TLMDCalendar</p></div>
<p>Yes &#8211; it&#8217;s still well known TLMDCalendar, and here is the DFM snippet of it:</p>
<pre class="brush:Dfm;collapse: true">object LMDCalendar1: TLMDCalendar
  Left = 48
  Top = 87
  Width = 234
  Height = 225
  BackFX.AlphaBlend.FillObject.Style = sfGradient
  BackFX.AlphaBlend.FillObject.AlphaLevel = 255
  BackFX.FlipHorizontal = True
  BackFX.Buffered = True
  Bevel.BorderColor = clGradientActiveCaption
  Bevel.Mode = bmStandard
  Bevel.StandardStyle = lsNone
  CellStyle.Font.Charset = DEFAULT_CHARSET
  CellStyle.Font.Color = 5392449
  CellStyle.Font.Height = -11
  CellStyle.Font.Name = 'Tahoma'
  CellStyle.Font.Style = [fsBold]
  CellStyle.Font3D.LightColor = clSilver
  CellStyle.Font3D.ShadowColor = clGradientActiveCaption
  CellStyle.Font3D.Style = tdSunken
  CellStyle.Bevel.StyleInner = bvShadow
  CellStyle.Bevel.StyleOuter = bvShadow
  CellStyle.Bevel.Mode = bmCustom
  CellStyle.FillObject.Style = sfBrush
  CellStyle.FillObject.AlphaLevel = 255
  CellStyle.FillObject.Brush.Color = 13814989
  Date = 40115.000000000000000000
  Day = 29
  DayCaptionCellStyle.Font.Charset = DEFAULT_CHARSET
  DayCaptionCellStyle.Font.Color = clGray
  DayCaptionCellStyle.Font.Height = -11
  DayCaptionCellStyle.Font.Name = 'Tahoma'
  DayCaptionCellStyle.Font.Style = [fsBold]
  DayCaptionCellStyle.Bevel.StyleOuter = bvLowered
  DayCaptionCellStyle.Bevel.Mode = bmStandard
  DayCaptionCellStyle.Bevel.StandardStyle = lsNone
  DayCaptionCellStyle.FillObject.Style = sfBrush
  DayCaptionCellStyle.FillObject.AlphaLevel = 255
  DayCaptionCellStyle.FillObject.Brush.Color = cl3DLight
  FillObject.AlphaLevel = 255
  FillObject.Brush.Color = clMoneyGreen
  GridPen.Color = clSilver
  GridPen.Style = psClear
  GridPen.Width = 0
  Header.Style.Font.Charset = DEFAULT_CHARSET
  Header.Style.Font.Color = 5392449
  Header.Style.Font.Height = -11
  Header.Style.Font.Name = 'Tahoma'
  Header.Style.Font.Style = [fsBold]
  Header.Style.Font3D.Style = tdSunken
  Header.Style.Bevel.EdgeStyle = etBump
  Header.Style.Bevel.Mode = bmStandard
  Header.Style.Bevel.StandardStyle = lsRaised
  Header.Style.FillObject.Style = sfGradient
  Header.Style.FillObject.Gradient.Color = 16119285
  Header.Style.FillObject.Gradient.ColorCount = 32
  Header.Style.FillObject.Gradient.EndColor = 12697020
  Header.Style.FillObject.AlphaLevel = 255
  Header.Elements = [heMonthName, heMonthBtns, heYear]
  Header.ButtonStyle = ubsOfficeTransp
  Header.ButtonFont.Charset = DEFAULT_CHARSET
  Header.ButtonFont.Color = clWindowText
  Header.ButtonFont.Height = -11
  Header.ButtonFont.Name = 'Tahoma'
  Header.ButtonFont.Style = []
  Header.MinHeight = 22
  Header.MonthName.Alignment = taCenter
  Header.MonthName.Order = 0
  Header.YearValue.Alignment = taCenter
  Header.YearValue.Order = 0
  Header.MonthUp.Alignment = taRightJustify
  Header.MonthUp.Order = 15
  Header.MonthDn.Alignment = taLeftJustify
  Header.MonthDn.Order = -15
  Header.YearUp.Alignment = taRightJustify
  Header.YearUp.Order = 20
  Header.YearDn.Alignment = taLeftJustify
  Header.YearDn.Order = -20
  Header.MonthCombo.Alignment = taLeftJustify
  Header.MonthCombo.Order = 0
  Header.YearCombo.Alignment = taLeftJustify
  Header.YearCombo.Order = 0
  Header.Today.Alignment = taLeftJustify
  Header.Today.Order = 0
  MarkedCellStyle.Font.Charset = DEFAULT_CHARSET
  MarkedCellStyle.Font.Color = clWindowText
  MarkedCellStyle.Font.Height = -11
  MarkedCellStyle.Font.Name = 'Tahoma'
  MarkedCellStyle.Font.Style = []
  MarkedCellStyle.Bevel.Mode = bmCustom
  MarkedCellStyle.FillObject.Style = sfBrush
  MarkedCellStyle.FillObject.AlphaLevel = 255
  MarkedCellStyle.FillObject.Brush.Color = clActiveCaption
  Marked2CellStyle.Font.Charset = DEFAULT_CHARSET
  Marked2CellStyle.Font.Color = clWindowText
  Marked2CellStyle.Font.Height = -11
  Marked2CellStyle.Font.Name = 'Tahoma'
  Marked2CellStyle.Font.Style = []
  Marked2CellStyle.Bevel.Mode = bmCustom
  Marked2CellStyle.FillObject.AlphaLevel = 255
  Month = 10
  SelectedCellStyle.Font.Charset = DEFAULT_CHARSET
  SelectedCellStyle.Font.Color = clWhite
  SelectedCellStyle.Font.Height = -11
  SelectedCellStyle.Font.Name = 'Tahoma'
  SelectedCellStyle.Font.Style = [fsBold]
  SelectedCellStyle.Font3D.ShadowColor = clBlack
  SelectedCellStyle.Font3D.Style = tdShadow
  SelectedCellStyle.Bevel.StyleInner = bvLowered
  SelectedCellStyle.Bevel.StyleOuter = bvNormal
  SelectedCellStyle.Bevel.BorderColor = clGray
  SelectedCellStyle.Bevel.BorderWidth = 1
  SelectedCellStyle.Bevel.LightColor = 15647132
  SelectedCellStyle.Bevel.Mode = bmCustom
  SelectedCellStyle.Bevel.ShadowColor = 15647132
  SelectedCellStyle.FillObject.Style = sfGradient
  SelectedCellStyle.FillObject.Gradient.ColorCount = 100
  SelectedCellStyle.FillObject.Gradient.TwoColors = False
  SelectedCellStyle.FillObject.Gradient.ColorList = (
    15905663
    15568171
    14315781
    14315781)
  SelectedCellStyle.FillObject.AlphaLevel = 255
  SelectedCellStyle.FillObject.Brush.Color = clSkyBlue
  ShowDayHint = True
  SpecialDates = &lt;
    item
      Style.Font.Charset = DEFAULT_CHARSET
      Style.Font.Color = clWhite
      Style.Font.Height = -11
      Style.Font.Name = 'Tahoma'
      Style.Font.Style = [fsBold]
      Style.Font3D.ShadowColor = clBlack
      Style.Font3D.Style = tdShadow
      Style.Bevel.StyleInner = bvLowered
      Style.Bevel.StyleOuter = bvLowered
      Style.Bevel.LightColor = 9597787
      Style.Bevel.Mode = bmCustom
      Style.Bevel.ShadowColor = 6509379
      Style.FillObject.Style = sfBrush
      Style.FillObject.AlphaLevel = 255
      Style.FillObject.Brush.Color = 11045750
      Caption = '345345'
      Index = 0
      DisplayName = 'TLMDSpecialDates'
      FDates = (
        40100.681377314820000000
        '557y6')
    end&gt;
  StartDay = 2
  StartWithActualDate = True
  TabOrder = 1
  Year = 2009
end</pre>
<p>Just copy it to clipboard and insert on your form.</p>
<p>PS. If you have access to SVN you can add the follwoing 2 strings into the OnCreate event of Form (they paint the non active days of previous or next month):</p>
<pre class="brush:delphi;gutter:false">  LMDCalendar1.InactiveCellStyle := LMDCalendar1.CellStyle;
  LMDCalendar1.InactiveCellStyle.Font.Color := RGB(155, 157, 162);</pre>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.lmd.de/2009/10/new-look-for-lmd-calendar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Download a specific file from a ZIP using TLMDWebHTTPGet</title>
		<link>http://blog.lmd.de/2009/10/using-tlmdwebhttpget-to-downloading-specified-file-from-zip/</link>
		<comments>http://blog.lmd.de/2009/10/using-tlmdwebhttpget-to-downloading-specified-file-from-zip/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 00:12:53 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[LMD Packs]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[WebPack]]></category>
		<category><![CDATA[zip]]></category>

		<guid isPermaLink="false">http://blog.lmd.de/?p=8</guid>
		<description><![CDATA[From the most recent version of LMD WebPack on the TLMDWebHTTPGet control is able to resume file downloads from a specified position. 2 new properties were added: RangeStart and RangeEnd. Thus a programmer can setwith RangeStart position from which downloading should be started, whereby RangeEnd specifies end position. Another property is Resume: If set to [...]]]></description>
			<content:encoded><![CDATA[<p>From the most recent version of LMD WebPack on the TLMDWebHTTPGet control is able to resume file downloads from a specified position. 2 new properties were added: RangeStart and RangeEnd. Thus a programmer can setwith RangeStart position from which downloading should be started, whereby RangeEnd specifies end position. Another property is Resume: If set to true, the component will search in TLMDWebHTTPGet.DownloadDir for a file named with TLMDWebHTTPGet.DestinationName and fills RangeStart property automatically with the found file size.</p>
<p><span id="more-8"></span></p>
<p>So how can a programmer use described features? Possibilities are endless:</p>
<ol>
<li>Download a filelist and get a specified file from zip file only</li>
<li>Multi-threaded file downloads</li>
<li>Allow end-users to pause/resume downloads of large files</li>
</ol>
<p>Here is simple code to implement first example (downloading a specified file from zip):</p>
<pre class="brush:delphi">  LMDWebHTTPGet1.URL := 'http://www.lmd.de/downloads/lmd2010vcl/setupse10d14.zip';
  // "end of central directory" size.
  // Minus shows that we read it from end of file
  LMDWebHTTPGet1.RangeEnd := -17;
  // Downloads last 17 bytes of file
  if LMDWebHTTPGet1.Process(False, False) then
  begin
    LEndOfCentralRecord.LoadFromStream(LMDWebHTTPGet1.Data);
    // Fills RangeStart by "Central Directory" structure begin offset
    LMDWebHTTPGet1.RangeStart := LEndOfCentralRecord.OffsetOfCentralDirectory;
    LMDWebHTTPGet1.RangeEnd := LMDWeHTTPGet1.RangeStart + LEndOfCentralRecord.SizeOfCentralDirectory;
    // Downloads "Central Directory" structure
    if LMDWebHTTPGet1.Process(False, False) then
    begin
      LCentralDirectory.LoadFromStream(LMDWebHTTPGet1.Data);
      // Fills RangeStart by offset of compressed file in ZIP
      LMDWebHTTPGet1.RangeStart := LCentralDirectory.Files['readme.txt'].FileOffset;
      // Compressed size
      LMDWebHTTPGet1.RangeEnd := LMDWebHTTPGet1.RangeStart + LCentralDirectory.Files['readme.txt'].CompressedSize;
      // Downloads compressed file "readme.txt"
      if LMDWebHTTPGet1.Process(False, False) then
      begin
        // Processing of compressed file
      end;
    end;
  end;</pre>
<p>LEndOfCentralRecord, LCentralDirectory are placeholders that schematically shows corresponding zip format structures &#8211; &#8220;Central directory structure&#8221; and &#8220;End of central directory record&#8221;. The full specification is described <a href="http://blog.lmd.de/xT" target="_blank">here</a>.</p>
<p>Besides that WebPack includes a demo project in <code>demos\lmdweb\LMDWebHTTPGetResume</code> folder.</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.lmd.de/2009/10/using-tlmdwebhttpget-to-downloading-specified-file-from-zip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

