<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2portuguesefull.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Malta on Delphi</title>
	
	<link>http://singularsistemas.com.br/blog</link>
	<description>Blog sobre Delphi por Daniel Maltarolli</description>
	<pubDate>Fri, 21 Nov 2008 11:40:15 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/MaltaOnDelphi" type="application/rss+xml" /><feedburner:emailServiceId>1394617</feedburner:emailServiceId><feedburner:feedburnerHostname>http://www.feedburner.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FMaltaOnDelphi" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FMaltaOnDelphi" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/MaltaOnDelphi" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FMaltaOnDelphi" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2FMaltaOnDelphi" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://www.addtoany.com/?linkname=Malta%20on%20Delphi&amp;linkurl=http%3A%2F%2Ffeeds.feedburner.com%2FMaltaOnDelphi&amp;type=feed" src="http://www.addtoany.com/addfr-b.gif">Add to Any Feed Reader</feedburner:feedFlare><item>
		<title>Reordenação de Items em ListBox</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/460671835/</link>
		<comments>http://singularsistemas.com.br/blog/2008/11/reordenacao-de-items-em-listbox/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 10:45:59 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[UI]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=111</guid>
		<description><![CDATA[Eu tenho uma tabela que contém itens ordenados. A coluna &#8220;posicao&#8221; indica a posição relativa de cada item (de 1 a n) e seus valores não podem ser repetidos. Eu precisava de uma forma prática de redefinir a ordenação dos itens. A dificuldade é que a cada vez que um item muda de posição todos [...]]]></description>
			<content:encoded><![CDATA[<p>Eu tenho uma tabela que contém itens ordenados. A coluna &#8220;posicao&#8221; indica a posição relativa de cada item (de 1 a n) e seus valores não podem ser repetidos. Eu precisava de uma forma prática de redefinir a ordenação dos itens. A dificuldade é que a cada vez que um item muda de posição todos os itens posteriores também devem mudar.</p>
<p>A solução foi levar todos os nomes de itens para um TListBox respeitando a ordenação atual e deixar o usuário livremente posicionar os nomes sem se preocupar com o dataset. Quando o usuário estiver satisfeito com a ordem dos itens, clica em OK e o programa atribui de uma só vez todos os valores de &#8220;posicao&#8221; ao dataset conforme os índices dos nomes no ListBox.<span id="more-111"></span></p>
<p><img class="alignright" style="float: right;" src="http://singularsistemas.com.br/blog/wp-content/lbreorder.png" alt="ListBox Reorder Demo" />A idéia foi rapidamente implementada pelo Fábio Costa, que trabalha comigo. A solução inicial usava apenas teclas de atalho e botões para mover o item selecionado para cima e para baixo, para a primeira ou última posição. O problema é que ele começou a tomar gosto pela coisa e danou a ter idéias. Por que não arrastar e soltar um item com o mouse para mudar sua posição? Por que não fazer o mouse dar scroll sozinho no ListBox quando o usuário estiver arrastando para além da primeira ou da última posição do controle?</p>
<p>Assim, a coisa foi evoluindo para uma solução mais e mais sofisticada. Não é que ficou bom?</p>
<p>Várias técnicas foram utilizadas para chegar ao resultado final: <em>TActionList</em> com teclas de atalhos (Ctrl+Home, Ctrl+Up, Ctrl+Down, Ctrl+End) e habilitação condicional, manipulação dos eventos <em>OnStartDrag</em>, <em>OnDragOver</em>, <em>OnDragDrop</em> e <em>OnDragEnd</em>, execução de mensagens do Windows pelo método <em>Perform</em>, scroll de <em>TListBox</em> por código, identificação do item do ListBox dada uma posição (X, Y) de tela, timers com intervalos dinâmicos (1s para começar, 0.2s para continuar a rolagem).</p>
<p>Veja o código de exemplo comentado abaixo, sem a parte de banco de dados. Você também pode fazer o <a href="http://singularsistemas.com.br/blog/wp-content/lbreorder.zip">download</a> do código fonte do projeto de demonstração.</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">unit</span> ListBoxReorder_Form;
&nbsp;
<span style="color: #000000; font-weight: bold;">interface</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">uses</span>
  Windows<span style="color: #000066;">,</span> Messages<span style="color: #000066;">,</span> SysUtils<span style="color: #000066;">,</span> Variants<span style="color: #000066;">,</span> Classes<span style="color: #000066;">,</span> Graphics<span style="color: #000066;">,</span> Controls<span style="color: #000066;">,</span> Forms<span style="color: #000066;">,</span>
  Dialogs<span style="color: #000066;">,</span> ActnList<span style="color: #000066;">,</span> StdCtrls<span style="color: #000066;">,</span> ExtCtrls;
&nbsp;
<span style="color: #000000; font-weight: bold;">type</span>
  TScrollZone <span style="color: #000066;">=</span> <span style="color: #000066;">&#40;</span>szNone<span style="color: #000066;">,</span> szTop<span style="color: #000066;">,</span> szBottom<span style="color: #000066;">&#41;</span>;
&nbsp;
  TMainForm <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #000066;">&#40;</span>TForm<span style="color: #000066;">&#41;</span>
    ActionList<span style="color: #000066;">:</span> TActionList;
    ListBox<span style="color: #000066;">:</span> TListBox;
    ScrollTimer<span style="color: #000066;">:</span> TTimer;
    DownAction<span style="color: #000066;">:</span> TAction;
    DownButton<span style="color: #000066;">:</span> TButton;
    FirstAction<span style="color: #000066;">:</span> TAction;
    FirstButton<span style="color: #000066;">:</span> TButton;
    LastAction<span style="color: #000066;">:</span> TAction;
    LastButton<span style="color: #000066;">:</span> TButton;
    UpAction<span style="color: #000066;">:</span> TAction;
    UpButton<span style="color: #000066;">:</span> TButton;
    <span style="color: #000000; font-weight: bold;">procedure</span> FormCreate<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> FirstActionExecute<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> FirstActionUpdate<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> UpActionExecute<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> UpActionUpdate<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> DownActionExecute<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> DownActionUpdate<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> LastActionExecute<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> LastActionUpdate<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> ListBoxStartDrag<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>; <span style="color: #000000; font-weight: bold;">var</span> DragObject<span style="color: #000066;">:</span> TDragObject<span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> ListBoxDragOver<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">,</span> Source<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>; X<span style="color: #000066;">,</span> Y<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>;
      State<span style="color: #000066;">:</span> TDragState; <span style="color: #000000; font-weight: bold;">var</span> Accept<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Boolean</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> ListBoxDragDrop<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">,</span> Source<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>; X<span style="color: #000066;">,</span> Y<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> ListBoxEndDrag<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">,</span> Target<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>; X<span style="color: #000066;">,</span> Y<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> ScrollTimerExecute<span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">private</span>
    FScrollZone<span style="color: #000066;">:</span> TScrollZone;
    <span style="color: #000000; font-weight: bold;">procedure</span> InitListBox;
    <span style="color: #000000; font-weight: bold;">function</span> IsSelected<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Boolean</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> MoveItem<span style="color: #000066;">&#40;</span>NewIndex<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">function</span> GetScrollZone<span style="color: #000066;">&#40;</span>X<span style="color: #000066;">,</span> Y<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">:</span> TScrollZone;
  <span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">var</span>
  MainForm<span style="color: #000066;">:</span> TMainForm;
&nbsp;
<span style="color: #000000; font-weight: bold;">implementation</span>
&nbsp;
<span style="color: #008000; font-style: italic;">{$R *.dfm}</span>
&nbsp;
<span style="color: #808080; font-style: italic;">{ Inicializa ListBox.Items para demonstração }</span>
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">FormCreate</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  InitListBox;
  ListBox<span style="color: #000066;">.</span><span style="color: #006600;">DragMode</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> dmAutomatic;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Inicializa ListBox.Items com nomes de arquivos da pasta System32 }</span>
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">InitListBox</span>;
<span style="color: #000000; font-weight: bold;">var</span>
  F<span style="color: #000066;">:</span> TSearchRec;
<span style="color: #000000; font-weight: bold;">begin</span>
  ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Items</span><span style="color: #000066;">.</span><span style="color: #006600;">BeginUpdate</span>;
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000066;">FindFirst</span><span style="color: #000066;">&#40;</span><span style="color: #ff0000;">'C:\Windows\System32\*.*'</span><span style="color: #000066;">,</span> faArchive<span style="color: #000066;">,</span> F<span style="color: #000066;">&#41;</span> <span style="color: #000066;">=</span> 0 <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #000000; font-weight: bold;">repeat</span>
      ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Items</span><span style="color: #000066;">.</span><span style="color: #006600;">Add</span><span style="color: #000066;">&#40;</span>F<span style="color: #000066;">.</span><span style="color: #006600;">Name</span><span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">until</span> <span style="color: #000066;">FindNext</span><span style="color: #000066;">&#40;</span>F<span style="color: #000066;">&#41;</span> &lt;&gt; 0;
  <span style="color: #000066;">FindClose</span><span style="color: #000066;">&#40;</span>F<span style="color: #000066;">&#41;</span>;
  ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Items</span><span style="color: #000066;">.</span><span style="color: #006600;">EndUpdate</span>;
  ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> 0;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Indica se algum item do ListBox está selecionado }</span>
<span style="color: #000000; font-weight: bold;">function</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">IsSelected</span><span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Boolean</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> &lt;&gt; <span style="color: #000066;">-</span><span style="color: #0000ff;">1</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Move um item do ListBox para outra posição,
  seleciona a nova posição no ListBox e
  atribui o foco ao ListBox. }</span>
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">MoveItem</span><span style="color: #000066;">&#40;</span>NewIndex<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Items</span><span style="color: #000066;">.</span><span style="color: #000066;">Move</span><span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span><span style="color: #000066;">,</span> NewIndex<span style="color: #000066;">&#41;</span>;
  ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> NewIndex;
  ListBox<span style="color: #000066;">.</span><span style="color: #006600;">SetFocus</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">DownActionExecute</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  MoveItem<span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> <span style="color: #000066;">+</span> <span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">DownActionUpdate</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  DownAction<span style="color: #000066;">.</span><span style="color: #006600;">Enabled</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> IsSelected <span style="color: #000000; font-weight: bold;">and</span>
    <span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> &lt; ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Items</span><span style="color: #000066;">.</span><span style="color: #006600;">Count</span> <span style="color: #000066;">-</span> <span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">FirstActionExecute</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  MoveItem<span style="color: #000066;">&#40;</span>0<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">FirstActionUpdate</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  FirstAction<span style="color: #000066;">.</span><span style="color: #006600;">Enabled</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> IsSelected <span style="color: #000000; font-weight: bold;">and</span> <span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> &gt; 0<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">LastActionExecute</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  MoveItem<span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Items</span><span style="color: #000066;">.</span><span style="color: #006600;">Count</span> <span style="color: #000066;">-</span> <span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">LastActionUpdate</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  LastAction<span style="color: #000066;">.</span><span style="color: #006600;">Enabled</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> IsSelected <span style="color: #000000; font-weight: bold;">and</span>
    <span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> &lt; ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Items</span><span style="color: #000066;">.</span><span style="color: #006600;">Count</span> <span style="color: #000066;">-</span> <span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">UpActionExecute</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  MoveItem<span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> <span style="color: #000066;">-</span> <span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">UpActionUpdate</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  UpAction<span style="color: #000066;">.</span><span style="color: #006600;">Enabled</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> IsSelected <span style="color: #000000; font-weight: bold;">and</span> <span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemIndex</span> &gt; 0<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Inicializa FScrollZone com szNone }</span>
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">ListBoxStartDrag</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>;
  <span style="color: #000000; font-weight: bold;">var</span> DragObject<span style="color: #000066;">:</span> TDragObject<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  FScrollZone <span style="color: #000066;">:</span><span style="color: #000066;">=</span> szNone;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Define se a posição do mouse aponta para um item válido
  do ListBox que permita soltar o item arrastado (Accept).
  Inicia ou cancela o timer de scroll automático. }</span>
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">ListBoxDragOver</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">,</span> Source<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>; X<span style="color: #000066;">,</span> Y<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>;
  State<span style="color: #000066;">:</span> TDragState; <span style="color: #000000; font-weight: bold;">var</span> Accept<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Boolean</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">var</span>
  NewZone<span style="color: #000066;">:</span> TScrollZone;
<span style="color: #000000; font-weight: bold;">begin</span>
  Accept <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000066;">&#40;</span>Source <span style="color: #000066;">=</span> ListBox<span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">and</span>
    <span style="color: #000066;">&#40;</span>ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemAtPos</span><span style="color: #000066;">&#40;</span>Point<span style="color: #000066;">&#40;</span>X<span style="color: #000066;">,</span> Y<span style="color: #000066;">&#41;</span><span style="color: #000066;">,</span> <span style="color: #000000; font-weight: bold;">True</span><span style="color: #000066;">&#41;</span> &lt;&gt; <span style="color: #000066;">-</span><span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
  NewZone <span style="color: #000066;">:</span><span style="color: #000066;">=</span> GetScrollZone<span style="color: #000066;">&#40;</span>X<span style="color: #000066;">,</span> Y<span style="color: #000066;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">if</span> NewZone &lt;&gt; FScrollZone <span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #000000; font-weight: bold;">begin</span>
    FScrollZone <span style="color: #000066;">:</span><span style="color: #000066;">=</span> NewZone;
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000066;">&#40;</span>FScrollZone &lt;&gt; szNone<span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #000000; font-weight: bold;">begin</span>
      ScrollTimer<span style="color: #000066;">.</span><span style="color: #006600;">Interval</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #0000ff;">1000</span>;
      ScrollTimer<span style="color: #000066;">.</span><span style="color: #006600;">Enabled</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">True</span>;
    <span style="color: #000000; font-weight: bold;">end</span>
    <span style="color: #000000; font-weight: bold;">else</span>
      ScrollTimer<span style="color: #000066;">.</span><span style="color: #006600;">Enabled</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">False</span>;
  <span style="color: #000000; font-weight: bold;">end</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Move item selecionado para nova posição }</span>
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">ListBoxDragDrop</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">,</span> Source<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>; X<span style="color: #000066;">,</span> Y<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">var</span>
  NewIndex<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  NewIndex <span style="color: #000066;">:</span><span style="color: #000066;">=</span> ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemAtPos</span><span style="color: #000066;">&#40;</span>Point<span style="color: #000066;">&#40;</span>X<span style="color: #000066;">,</span> Y<span style="color: #000066;">&#41;</span><span style="color: #000066;">,</span> <span style="color: #000000; font-weight: bold;">True</span><span style="color: #000066;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">if</span> NewIndex &lt;&gt; <span style="color: #000066;">-</span><span style="color: #0000ff;">1</span> <span style="color: #000000; font-weight: bold;">then</span>
    MoveItem<span style="color: #000066;">&#40;</span>NewIndex<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Desliga timer de scroll no fim do drag and drop }</span>
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">ListBoxEndDrag</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">,</span> Target<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>; X<span style="color: #000066;">,</span> Y<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  ScrollTimer<span style="color: #000066;">.</span><span style="color: #006600;">Enabled</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">False</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Retorna a szTop se mouse está na área da primeira linha visível do
  ListBox, szBottom se mouse está na área da última linha visível do
  ListBox ou szNone caso contrátrio. }</span>
<span style="color: #000000; font-weight: bold;">function</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">GetScrollZone</span><span style="color: #000066;">&#40;</span>X<span style="color: #000066;">,</span> Y<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span><span style="color: #000066;">:</span> TScrollZone;
<span style="color: #000000; font-weight: bold;">begin</span>
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000066;">&#40;</span>Y &lt; ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemHeight</span><span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">then</span>
    Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> szTop
  <span style="color: #000000; font-weight: bold;">else</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000066;">&#40;</span>Y &gt;<span style="color: #000066;">=</span> ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ClientHeight</span> <span style="color: #000066;">-</span> ListBox<span style="color: #000066;">.</span><span style="color: #006600;">ItemHeight</span><span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">then</span>
      Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> szBottom
    <span style="color: #000000; font-weight: bold;">else</span>
      Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> szNone;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">{ Faz scroll de uma linha para cima ou para baixo conforme a zona
  de scroll definida pela posição do mouse. Redefine intervalo
  do timer para 0.2s após o primeiro scroll. }</span>
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">ScrollTimerExecute</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  ScrollTimer<span style="color: #000066;">.</span><span style="color: #006600;">Interval</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #0000ff;">200</span>;
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000066;">&#40;</span>FScrollZone <span style="color: #000066;">=</span> szTop<span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #000000; font-weight: bold;">begin</span>
    ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Perform</span><span style="color: #000066;">&#40;</span>WM_VSCROLL<span style="color: #000066;">,</span> SB_LINEUP<span style="color: #000066;">,</span> 0<span style="color: #000066;">&#41;</span>;
    ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Perform</span><span style="color: #000066;">&#40;</span>WM_VSCROLL<span style="color: #000066;">,</span> SB_ENDSCROLL<span style="color: #000066;">,</span> 0<span style="color: #000066;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">end</span>
  <span style="color: #000000; font-weight: bold;">else</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000066;">&#40;</span>FScrollZone <span style="color: #000066;">=</span> szBottom<span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #000000; font-weight: bold;">begin</span>
      ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Perform</span><span style="color: #000066;">&#40;</span>WM_VSCROLL<span style="color: #000066;">,</span> SB_LINEDOWN<span style="color: #000066;">,</span> 0<span style="color: #000066;">&#41;</span>;
      ListBox<span style="color: #000066;">.</span><span style="color: #006600;">Perform</span><span style="color: #000066;">&#40;</span>WM_VSCROLL<span style="color: #000066;">,</span> SB_ENDSCROLL<span style="color: #000066;">,</span> 0<span style="color: #000066;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">end</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">end</span><span style="color: #000066;">.</span></pre></div></div>

<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=mhnTn"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=mhnTn" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=R6pyN"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=R6pyN" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=tBuxN"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=tBuxN" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/460671835" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/11/reordenacao-de-items-em-listbox/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/11/reordenacao-de-items-em-listbox/</feedburner:origLink></item>
		<item>
		<title>Teclas Enter e Esc no Delphi</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/458279535/</link>
		<comments>http://singularsistemas.com.br/blog/2008/11/teclas-enter-e-esc-no-delphi/#comments</comments>
		<pubDate>Wed, 19 Nov 2008 11:12:44 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[UI]]></category>

		<category><![CDATA[VCL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=109</guid>
		<description><![CDATA[Se você veio aqui procurando uma dica sobre como aceitar tecla ENTER para mudar de campo, não perca seu tempo porque não vai encontrar (se depois de ler esse artigo você ainda quiser, tenho certeza que o Google vai mostrar um zilhão de técnicas).
As convenções existem por um motivo: estabelecer um entendimento comum entre as [...]]]></description>
			<content:encoded><![CDATA[<p>Se você veio aqui procurando uma dica sobre como aceitar tecla ENTER para mudar de campo, não perca seu tempo porque não vai encontrar (se depois de ler esse artigo você ainda quiser, tenho certeza que o <a href="http://www.google.com.br/search?hl=pt-BR&amp;q=delphi+enter+key&amp;btnG=Pesquisa+Google&amp;meta=">Google</a> vai mostrar um zilhão de técnicas).</p>
<p>As convenções existem por um motivo: estabelecer um entendimento comum entre as partes sobre alguma coisa. Se uma das partes (no caso, a aplicação ou o usuário) ignorar a convenção a coisa não funciona.</p>
<p>A regra é clara: a tecla para pular de um campo é TAB, não ENTER.</p>
<p>Quem estabeleceu a regra não fui eu, foi a indústria ao longo dos anos. A publicação em 1987 pela IBM do manual <a title="Common User Access - A consistent and usable human-computer interface for the SAA environments" rel="nofollow" href="http://www.research.ibm.com/journal/sj/273/ibmsj2703E.pdf">Common User Access (CUA)</a><span class="external text"> foi um marco importante.</span><span class="external text"> A Microsoft seguiu essa cartilha no desenvolvimento da interface de usuário do Windows, até porque ajudou a criá-la durante a fase de cooperação do OS/2 com a IBM. Hoje em dia a Microsoft tem padrões mais atualizados que cobrem </span><span class="external text">novos </span><span class="external text">aspectos do <a title="Windows User Interface " href="http://msdn.microsoft.com/en-us/library/ms632587%28VS.85%29.aspx">Windows XP</a> e do <a title="Windows User Experience Interaction Guidelines" href="http://msdn.microsoft.com/en-us/library/aa511258.aspx">Windows Vista</a>, como acessibilidade, bitmaps de alta definição, cores, transparências, interação com dispositivos USB, etc.</span></p>
<p>Quando os fabricantes de teclados colocam o mesmo conjunto de teclas de suporte, como Home, End, Insert, Delete, Tab, F1 a F12 e Print Screen, também estão respeitando as convenções da indústria.</p>
<p>A tecla ENTER tem um papel bem definido em caixas de diálogo, que é confirmar a aceitação do conteúdo e fechar a janela. Ou seja, equivale a um clique no botão OK. Similarmente a tecla ESC fecha a janela cancelando os dados, equivalendo a um clique no botão Cancelar.</p>
<h4>TButton.Default, OK?</h4>
<p>Por ser uma convenção, a API do Windows suporta nativamente desde a sua primeira versão essas de teclas de atalho em caixas de diálogo. Você não precisa fazer nada para que as combinações TAB e Shift+TAB mudem o foco dos controles. O que muita gente não sabe é que a API também trata nativamente ENTER e ESC.</p>
<p>A biblioteca VCL do Delphi torna tudo muito mais simples. Basta usar as propriedades tipo Boolean <em>Default</em> e <em>Cancel</em> de <em>TButton</em> para aceitar as teclas ENTER e ESC, respectivamente.</p>
<p>Definir <em>TButton.Default = True</em> faz mais que aceitar a tecla ENTER. Desenha um botão diferenciado, com a borda mais destacada, o que indica visualmente ao usuário qual é o botão padrão que será acionado ao se teclar ENTER.</p>
<p>Para o usuário acostumado a usar teclado, é extremamente conveniente (necessário até, eu diria) que a tecla ESC (<em>TButton.Cancel = True</em>) também seja tratada para sair da janela sem salvar nenhum dado.</p>
<h4>Exceções</h4>
<p>Exceções existem, é claro. Uma tela de entrada de dados de grande volume, ainda mais se os usuários nem sempre têm os olhos voltados para o teclado ou se a entrada é basicamente numérica, é uma possível candidata. Sem dúvida é mais fácil digitar com a mesma mão direita o ENTER (o TAB fica à esquerda) e porque as teclas ENTER (as duas!) são sempre maiores e verticais, facilitando o operador &#8220;acertar&#8221; a digitação sem olhar.</p>
<p>Outra justificativa comum é que os usuários estão acostumados a usar um programa antigo para DOS e são habituados a usar ENTER. Na minha opinião não é uma boa desculpa. É a hora de ensinar a convenção que todo mundo usa. Quando esses mesmos usuários navegarem na Internet vão ter que usar TAB para mudar de campo e ENTER para confirmar um formulário de qualquer forma.</p>
<p>Não podemos perder de vista que é a exceção não é a regra. A convenção é nossa amiga. A convenção facilita a vida do usuário e do desenvolvedor.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=igbBn"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=igbBn" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=UTI7N"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=UTI7N" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=8IcyN"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=8IcyN" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/458279535" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/11/teclas-enter-e-esc-no-delphi/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/11/teclas-enter-e-esc-no-delphi/</feedburner:origLink></item>
		<item>
		<title>Modelos de interface SDI, MDI, TDI e NDI</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/456225412/</link>
		<comments>http://singularsistemas.com.br/blog/2008/11/modelos-de-interface-sdi-mdi-tdi-e-ndi/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 17:43:29 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[OOP]]></category>

		<category><![CDATA[UI]]></category>

		<category><![CDATA[VCL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=107</guid>
		<description><![CDATA[Os programadores que viveram a época do modo texto em DOS tinham desafios bem diferentes ao projetar uma interface de usuário. Independente da linguagem utilizada - fosse Clipper, C, Pascal, FoxPro ou qualquer outra - as escolhas eram basicamente o melhor sistema de menu e a melhor combinação de caracteres de linha e cores de [...]]]></description>
			<content:encoded><![CDATA[<p>Os programadores que viveram a época do modo texto em DOS tinham desafios bem diferentes ao projetar uma interface de usuário. Independente da linguagem utilizada - fosse Clipper, C, Pascal, FoxPro ou qualquer outra - as escolhas eram basicamente o melhor sistema de menu e a melhor combinação de caracteres de linha e cores de fundo e texto para diagramar as telas de 80 linhas por 25 colunas.</p>
<p>Na década de 90 os programadores descobriram a interface MDI (&#8221;Multiple Document Interface&#8221;) no Windows. Achavam o máximo aquele monte de janelas superpostas. Como o Delphi tornava muito fácil criar esse tipo de interface, qualquer programinha tinha múltiplas janelas flutuando na área cliente e não faltavam aquelas famigeradas opções de janelas em cascata, lado-a-lado, minimizadas, etc. A gente se sentia até orgulhoso de fazer um sistema com interface semelhante à do Office. Melhor ainda se os ícones fossem os mesmos da Microsoft.</p>
<p>O que nós desenvolvedores ignorávamos então é que os usuários finais não dão a mínima pra nada disso. Os usuários gostam de fazer uma coisa de cada vez, com início, meio e fim. Lidar com várias janelas abertas na mesma aplicação só torna mais confuso o trabalho.</p>
<p>Muitos se assutaram quando o próprio Office, que havia popularizado o modelo MDI, abandonou a estratégia. A Microsoft fez muitas pesquisas de opinião e laboratórios de usabilidade para chegar a conclusão que não valia a pena insistir naquilo. Ficamos perdidos em busca de um novo modelo de interface de usuário.</p>
<p>A alguns anos veio com o FireFox e outros navegadores modernos a inspiração para uma idéia salvadora: apresentar janelas em páginas selecionáveis por abas. Definiu-se um novo modelo, que alguns chamam de TDI (&#8221;Tabbed Document Interface&#8221;), em oposição ao antigo MDI. As janelas abertas (documentos) são fáceis de visualizar e selecionar. Cada aba utiliza grande parte da área cliente, dando ao usuário a confortável sensação que está sempre trabalhando com uma janela &#8220;maximizada&#8221;.</p>
<p>É fácil, no entanto, observar que os usuários finais preferem. O mais simples e direto modelo de interface é o mais eficaz. Muitas vezes os mais complexos modelos de interação acabam reduzidos pela forma com que o usuários utilizam a um modelo simples de uma única janela que ocupa toda área do monitor, conhecido como SDI (&#8221;Single Document Interface&#8221;).</p>
<p>A propósito, qual seria o modelo de interface de um sistema web? Pense no Americanas.com, no Orkut e no site do seu supermercado favorito. Não é TDI, nem MDI, evidentemente. Cada página funciona na mesma área cliente, <em>alternando-se</em> conforme o opção escolhida pelo usuário. O que mais se aproxima é o bom e velho SDI.</p>
<p>Todos esses modelos de interface têm uma coisa em comum: o conceito de documento. Seja um documento de texto, uma planilha eletrônica ou uma página web, todos os documentos são da mesma natureza em uma interface MDI, TDI ou SDI.</p>
<p>Ainda hoje, por falta de opção ou por retrógrada herança da cultura de modo texto dos anos 80 muitos desenvolvedores ainda utilizam uma grande tela vazia (ou pior, um imenso bitmap espalhafatoso com o logo da empresa no fundo), um menu e uma barra de botões no topo da janela e mais nada. Esse modelo é o que se pode chamar NDI: &#8220;No Document Interface&#8221;. A cada opção de menu, abre-se uma caixa de diálogo diferente. Pode não ser bonito ou elegante, mas é funcional. Os clientes entendem.</p>
<p>O fato é que os usuários imediatamente absorvem a metáfora do menu que abre e fecha opções e volta ao estado inicial. Dá até para imaginar um usuário ensinando a outro como usar a aplicação: &#8220;Escolhe essa opção para cadastrar e essa outra para tirar um relatório&#8230;&#8221;.</p>
<h4>Janelas e Documentos</h4>
<p>Trazer o conceito de documentos para um cliente nativo Windows não é fácil. Pelo menos, não é óbvio. Aplicações de negócio têm relatórios, telas de cadastro, consulta e configuração e lidam com grupos de informação diferentes (clientes, produtos e vendas, por exemplo), cada um com uma forma de apresentação própria.</p>
<p>Na busca de um modelo orientado a documentos, seja TDI ou mesmo SDI, torna-se necessário definir um tipo abstrato de objeto <em></em>que possa representar todos os tipos de telas que se deseje apresentar na aplicação, similar ao conceito de documento dos browsers e editores de texto.</p>
<p>O Delphi não traz nada disso pronto, mas oferece inúmeros recursos que possibilitam a sua implementação. A chave é a programação orientada a objetos. Veja bem, eu disse programação, não interface orientada a objetos.</p>
<p>Uma hierarquia de classes de forms é chamada &#8220;herança visual&#8221; na VCL. Podemos usar herança visual para definir um form base que implemente o conceito de documento numa interface TDI ou SDI.</p>
<p>É razoável que todos os forms documento tenham alguma funcionalidade em comum. Todos os &#8220;documentos&#8221; podem ser abertos (abrir datasets, iniciar controles), fechados (fechar datasets, liberar objetos de memória), copiar para clipboard (seja um TEdit ou um TChart) e muitos até impressos. Esses são exemplos de ações comuns. Outras, no entanto, não podem ser abstraídas sem prejuízo de entendimento. Por exemplo, &#8220;Calcular&#8221; não é um bom candidato para uma ação comum, porque não é natural calcular um cadastro, por exemplo.</p>
<p>Há várias formas de implementar funções específicas de um tipo de documento: botões direto na janela, objetos TAction integrados em um TActionList global, menu merge, etc.</p>
<p>Balancear o que deve ser abstraído e o que deve ser especializado é sutil. Isso vale, é bem verdade, para todos os modelos de representação hierárquica e orientada a objetos, de modelos de dados a interfaces de usuário. Felizmente, no caso das interfaces de usuário você sempre tem o recurso de sair da sua mesa e ir perguntar os maiores interessadods, os usuários: &#8220;Para você, o que é melhor?&#8221;.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=ZKwfn"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=ZKwfn" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=vjf8N"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=vjf8N" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=ikKMN"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=ikKMN" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/456225412" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/11/modelos-de-interface-sdi-mdi-tdi-e-ndi/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/11/modelos-de-interface-sdi-mdi-tdi-e-ndi/</feedburner:origLink></item>
		<item>
		<title>MySQL no Delphi 2007</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/441034915/</link>
		<comments>http://singularsistemas.com.br/blog/2008/11/mysql-no-delphi-2007/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 14:57:43 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[CodeGear]]></category>

		<category><![CDATA[dbExpress]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=106</guid>
		<description><![CDATA[Esses dias andei experimentando usar o Delphi 2007 para acessar bancos de dados MySQL, o que me fez lembrar muito da notória frase de Henry Ford no início do século XX: &#8220;Qualquer cliente pode ter um carro de qualquer cor que deseje, desde que seja preta&#8221;.
Descobri que se pode usar componentes dbExpress para acessar qualquer [...]]]></description>
			<content:encoded><![CDATA[<p><img style="float: right; margin-left: 10px; margin-bottom: 8px;" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/74/1910Ford-T.jpg/144px-1910Ford-T.jpg" alt="Any customer can have a car painted any colour that he wants so long as it is black." />Esses dias andei experimentando usar o Delphi 2007 para acessar bancos de dados MySQL, o que me fez lembrar muito da notória <a title="Any customer can have a car painted any colour that he wants so long as it is black." href="http://en.wikiquote.org/wiki/Henry_Ford">frase</a> de Henry Ford no início do século XX: &#8220;Qualquer cliente pode ter um carro de qualquer cor que deseje, desde que seja preta&#8221;.</p>
<p>Descobri que se pode usar componentes dbExpress para acessar qualquer banco de dados MySQL que deseje no Delphi 2007, desde que seja um banco de dados da versão 5.0 do MySQL.</p>
<p>Por mais natural que pareça que funcione a versão estável mais recente, no caso a 5.1 (eu não digo nem a 6.0, em alpha-release), não adianta que não funciona. Tentei ainda usar o driver dbExpress que vem no recém-lançado Delphi 2009 e o resultado foi o mesmo. Só quando eu desinstalei o MySQL 5.1 e instalei o <a href="http://dev.mysql.com/downloads/mysql/5.0.html">MySQL 5.0</a> na máquina deu certo. Rápido e fácil como era de se esperar da dupla dinâmica MySQL e dbExpress.</p>
<p><img style="margin-right: 8px;" src="http://tbn0.google.com/images?q=tbn:KaV0xfgWV8PztM:http://www.hebertphp.net/wordpress/wp-content/uploads/2008/02/mysqlnetworkdt4.jpg" alt="MySQL" align="left" />Aparentemente, manter compatibilidade entre versões da libmySQL.dll não é uma grande preocupação para a Sun. Se serve de algum consolo, percebi incompatibilidade similar na versão mais recente do driver de MySQL para Ruby on Rails. O driver 2.7.3 funciona bem com MySQL 5.0, mas falha com o MySQL 5.1 ao gerar comandos simples como &#8220;SHOW TABLES&#8221;.</p>
<p>Nada justifica, no entanto, os erros catastróficos que o Delphi exibe quando falha em abrir uma query usando a DLL cliente do MySQL 5.1. Primeiro aparece uma mensagem de erro &#8220;Commands out of sync; you can&#8217;t run this command now&#8221;. Até aí tudo bem, é uma mensagem do próprio MySQL - quer dizer, não está tudo bem, mas é compreensível. Só que a partir da segunda tentativa de abrir o dataset já é mostrada uma apavorante mensagem de &#8220;Access Violation&#8221; na IDE do Delphi.</p>
<p>A qualidade do design do DBX 4 é excelente. Ainda assim, como não é possível controlar a qualidade dos drivers e DLLs cliente de terceiros, seria importante dedicar mais atenção ao tratamento de erros nas interfaces para não da margem a esse tipo de instabilidade.</p>
<p>No caso específico do MySQL acho importante a CodeGear correr para tornar os seus drivers compatíveis com as versões mais recentes, porque existem por aí em produção bancos de dados MySQL de todas as versões e simplesmente dizer que a culpa é da Sun não vale.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=U7JNn"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=U7JNn" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=jqoBN"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=jqoBN" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=SAKtN"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=SAKtN" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/441034915" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/11/mysql-no-delphi-2007/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/11/mysql-no-delphi-2007/</feedburner:origLink></item>
		<item>
		<title>Delphi Prism Video</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/436918870/</link>
		<comments>http://singularsistemas.com.br/blog/2008/10/delphi-prism-video/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 13:27:49 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Prism]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=105</guid>
		<description><![CDATA[Assista aqui a um rápido preview de 3:24&#8243; do Delphi Prism rodando no Visual Studio 2008 (em inglês), gravado por Jim McKeeth.
]]></description>
			<content:encoded><![CDATA[<p>Assista <a href="http://www.delphi.org/screencasts/3-DelphiPrismVideo1.html">aqui</a> a um rápido preview de 3:24&#8243; do Delphi Prism rodando no Visual Studio 2008 (em inglês), gravado por <span class="entry-author-name">Jim McKeeth.</span></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=GfL2m"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=GfL2m" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=SWMjM"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=SWMjM" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=Cy8aM"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=Cy8aM" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/436918870" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/10/delphi-prism-video/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/10/delphi-prism-video/</feedburner:origLink></item>
		<item>
		<title>Delphi Prism no Visual Studio .NET</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/434667704/</link>
		<comments>http://singularsistemas.com.br/blog/2008/10/delphi-prism-no-visual-studio-net/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 12:40:58 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[.NET]]></category>

		<category><![CDATA[CodeGear]]></category>

		<category><![CDATA[dbExpress]]></category>

		<category><![CDATA[linguagem]]></category>

		<category><![CDATA[Prism]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=104</guid>
		<description><![CDATA[Agora é oficial: ontem foi anunciada a próxima versão do Delphi for .NET, que se chamará Delphi Prism e será lançada até dezembro no CodeGear RAD Studio 2009. Ao invés da IDE do RAD Studio, funcionará como um plug-in de linguagem do Microsoft Visual Studio. O Delphi Prism é baseado na tecnologia Oxygene licenciada da [...]]]></description>
			<content:encoded><![CDATA[<p>Agora é oficial: ontem foi <a href="http://www.codegear.com/article/38851">anunciada</a> a próxima versão do Delphi for .NET, que se chamará <strong>Delphi Prism</strong> e será lançada até dezembro no CodeGear RAD Studio 2009. Ao invés da IDE do RAD Studio, funcionará como um plug-in de linguagem do Microsoft Visual Studio. O Delphi Prism é baseado na tecnologia <a href="http://www.remobjects.com/oxygene.aspx">Oxygene</a> licenciada da RemObjects, como já havia sido comentado por de <a href="http://www.ericksasse.com.br/remobjects-oxygene-e-o-novo-delphi-prism/">Erick Sasse</a> no início do mês.</p>
<p>Resumindo as informações que já se tem do Delphi Prism:</p>
<ul>
<li>Adeus VCL.NET - já vai tarde.</li>
<li>A linguagem traz recursos avançados como nullable types e &#8220;future&#8221; types, generics, sequences e query expressions (LINQ)</li>
<li>Funcionará com as tecnologias WPF, Silverlight, ASP.NET and LINQ</li>
<li>ADO.NET e ASP.NET providers baseados em dbExpress</li>
<li>DataSnap cliente, para conectar servidores DataSnap feitos em Win32</li>
<li>BlackFish SQL database</li>
<li>Precisará do .NET Framework 3.5 para rodar o VisualStudio</li>
<li>Produz executáveis compatíveis com qualquer versão do .NET Framework a partir da 1.1</li>
<li>Produz executáveis compatíveis com o framework .NET <a href="http://mono-project.com/Main_Page">Mono</a>, para Linux e Mac</li>
<li>Onde já tem Visual Studio instalado será apenas adicionado o plug-in de linguagem ao sistema</li>
<li>Onde não tem Visual Studio este será instalado apenas com a linguagem Delphi Prism (sem C# e VB)</li>
<li>Não será preciso adquirir uma nova licença do Visual Studio</li>
<li>Ainda não é possível desenvolver aplicativos .NET Compact Framework. A culpa não é da CodeGear, mas da Microsoft, que fez o CF fechado para as linguagens dela e não ao CLR</li>
<li>A CodeGear/Embarcadero e a RemObjects são parceiros comerciais. Uma não comprou, nem vai comprar a outra</li>
<li>O linguagem em si continuará a cargo da equipe de compiladores da RemObjects</li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=Zk9Fm"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=Zk9Fm" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=g1HWM"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=g1HWM" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=vNYRM"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=vNYRM" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/434667704" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/10/delphi-prism-no-visual-studio-net/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/10/delphi-prism-no-visual-studio-net/</feedburner:origLink></item>
		<item>
		<title>TField.Name do seu jeito</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/430217217/</link>
		<comments>http://singularsistemas.com.br/blog/2008/10/tfieldname-do-seu-jeito/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 01:53:19 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[DB]]></category>

		<category><![CDATA[VCL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=94</guid>
		<description><![CDATA[Cada equipe de desenvolvimento tem sua convenção de nomenclatura de campos no banco de dados. Há quem prefira só letras maiúsculas ou só letras minúsculas. Há quem use CamelCase, que é o padrão Pascal/Delphi. Há quem use sublinhado (&#8217;_') para separar palavras e há quem não use. Sem argumentos aqui sobre qual é melhor e [...]]]></description>
			<content:encoded><![CDATA[<p>Cada equipe de desenvolvimento tem sua convenção de nomenclatura de campos no banco de dados. Há quem prefira só letras maiúsculas ou só letras minúsculas. Há quem use <a href="http://pt.wikipedia.org/wiki/Camelcase">CamelCase</a>, que é o padrão Pascal/Delphi. Há quem use sublinhado (&#8217;_') para separar palavras e há quem não use. Sem argumentos aqui sobre qual é melhor e qual é pior.</p>
<p><img class="alignleft size-medium wp-image-101" style="float: left; margin-right: 8px;" title="tfieldrename_antes" src="http://singularsistemas.com.br/blog/wp-content/tfieldrename_antes-300x258.png" alt="TField.Name Antes" width="300" height="258" />O que é chato é criar campos persistentes para um dataset na IDE do Delphi e ver o nome dos componentes TField ficar com o nome formatado como na base de dados.</p>
<p>Dependendo da sua convenção, um dataset chamado cdsCliente, por exemplo, pode criar objetos TField com nomes estranhos como cdsClienteNOME, cdsClientenome_cliente ou cdsClienteENDERECO_BAIRRO. Todo esses casos fogem ao estilo padrão de nomenclatura de identificadores no Delphi (<a href="http://dn.codegear.com/article/10280">Object Pascal Style Guide</a>, de Charles Calvert).</p>
<p>Decidido a encontrar de uma vez por todas uma solução para esse problema, fui em busca da fonte da VCL. A princípio, a unit DB era o lugar que me pareceu mais óbvio para buscar o momento em que um <em>TField </em>é criado. De fato, é mesmo criado ali por um método de <em>TFieldDef</em>, mas&#8230; coisa estranha, em nenhum momento a propriedade <em>Name</em> é atribuída.</p>
<p>Descobri afinal que a definição do nome de um <em>TField </em>é feita somente pela IDE, através de &#8220;component editors&#8221;. Graças a São Borland! Assim não teria que criar um descendente de <em>TDataSet</em>, o que seria um preço alto demais a pagar. Tudo que tive que fazer é criar um desdencente de <em>TDSDesigner</em>, sobrescrever o método virtual <em>DoCreateField</em> reformatando a propriedade <em>Name </em>como eu queria e registrar o novo &#8220;component editor&#8221;.</p>
<p>O código final tem apenas 74 linhas e uma vez instalado como um package na IDE é totalmente transparente a sua utilização. Apenas adicione os campos pelo &#8220;Fields Editor&#8221; e a formatação dos nomes será automática.</p>
<p><img class="alignright size-medium wp-image-102" style="float: right; margin-left: 8px;" title="tfieldrename_depois" src="http://singularsistemas.com.br/blog/wp-content/tfieldrename_depois-300x258.png" alt="TField.Name Depois" width="300" height="258" />Nos exemplos anteriores, com o pacote instalado os componentes TField seriam criados como cdsClienteNome, cdsClienteNomeCliente ou cdsClienteEnderecoBairro, livres de sublinhados e maiúsculas.</p>
<p>O código fonte está disponível para <a href="http://singularsistemas.com.br/blog/wp-content/tfieldrename.zip">download</a>.</p>
<p>Só testei em Delphi 2007. Quem quiser testar em outras versões e me dar um feedback será bem vindo. De antemão eu sei que não vai compilar direto em versões anteriores ao Delphi 6, por causa das mudanças na unit DesignIntf, mas isso pode ser ajustado sem muita dificuldade.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=W19rm"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=W19rm" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=ADlGM"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=ADlGM" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=BogSM"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=BogSM" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/430217217" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/10/tfieldname-do-seu-jeito/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/10/tfieldname-do-seu-jeito/</feedburner:origLink></item>
		<item>
		<title>Previna AV com Assert</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/366895565/</link>
		<comments>http://singularsistemas.com.br/blog/2008/08/previna-av-com-assert/#comments</comments>
		<pubDate>Sun, 17 Aug 2008 00:55:32 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[compilador]]></category>

		<category><![CDATA[RTL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=91</guid>
		<description><![CDATA[Uma das razões mais comuns para acontecer Access Violations (AV) nos programas é quanto se tenta acessar um método ou uma propriedade de um objeto que ainda não foi alocado ou que já foi desalocado da memória.
Por exemplo:

procedure AV;
var
  List: TStringList;
begin
  // AV porque List é um objeto não alocado
  List.Add&#40;'teste'&#41;;
&#160;
  [...]]]></description>
			<content:encoded><![CDATA[<p>Uma das razões mais comuns para acontecer Access Violations (AV) nos programas é quanto se tenta acessar um método ou uma propriedade de um objeto que ainda não foi alocado ou que já foi desalocado da memória.</p>
<p>Por exemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">procedure</span> AV;
<span style="color: #000000; font-weight: bold;">var</span>
  List<span style="color: #000066;">:</span> TStringList;
<span style="color: #000000; font-weight: bold;">begin</span>
  <span style="color: #808080; font-style: italic;">// AV porque List é um objeto não alocado</span>
  List<span style="color: #000066;">.</span><span style="color: #006600;">Add</span><span style="color: #000066;">&#40;</span><span style="color: #ff0000;">'teste'</span><span style="color: #000066;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// ok, porque List foi previamente alocado</span>
  List <span style="color: #000066;">:</span><span style="color: #000066;">=</span> TStringList<span style="color: #000066;">.</span><span style="color: #006600;">Create</span>;
  List<span style="color: #000066;">.</span><span style="color: #006600;">Add</span><span style="color: #000066;">&#40;</span><span style="color: #ff0000;">'novamente'</span><span style="color: #000066;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// AV, porque o objeto foi desalocado e o valor</span>
  <span style="color: #808080; font-style: italic;">// da variável List é um ponteiro inválido</span>
  List<span style="color: #000066;">.</span><span style="color: #006600;">Free</span>;
  List<span style="color: #000066;">.</span><span style="color: #006600;">Add</span><span style="color: #000066;">&#40;</span><span style="color: #ff0000;">'outra vez'</span><span style="color: #000066;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// AV da mesma forma que antes, apenas a</span>
  <span style="color: #808080; font-style: italic;">// variável aponta para nil ($0000:0000)</span>
  List <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">nil</span>;
  List<span style="color: #000066;">.</span><span style="color: #006600;">Add</span><span style="color: #000066;">&#40;</span><span style="color: #ff0000;">'e finalmente'</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;</pre></div></div>

<p>Essas são receitas certas pra cometer violações de acesso de leitura de memória. Normalmente, em blocos de código pequenos esse tipo de coisa não ocorre, porque temos mais visibilidade e controle sobre o tempo de vida das variáveis. O problema fica maior quando o objeto é um parâmetro recebido de outra parte qualquer do código. Quem garante que o valor passado como parâmetro é válido?</p>
<p>Só pra ficar claro:</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">procedure</span> ShowText<span style="color: #000066;">&#40;</span>List<span style="color: #000066;">:</span> TStringList<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  ShowMessage<span style="color: #000066;">&#40;</span>List<span style="color: #000066;">.</span><span style="color: #006600;">Text</span><span style="color: #000066;">&#41;</span>; <span style="color: #808080; font-style: italic;">// AV? List é válido?</span>
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TestAV;
<span style="color: #000000; font-weight: bold;">var</span>
  Strings<span style="color: #000066;">:</span> TStringList;
<span style="color: #000000; font-weight: bold;">begin</span>
  ShowText<span style="color: #000066;">&#40;</span>Strings<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;</pre></div></div>

<p>Aqui TestAV chama ShowText passando como parâmetro um valor de objeto inválido, porque nunca foi alocado. Seja o valor igual a <em>nil</em> ou uma valor aleatório qualquer (dependendo do contexto, a variável pode conter &#8220;lixo&#8221; de memória), quando ShowText usar a propriedade Text do objeto vai produzir um AV.</p>
<p>O que eu uso para prevenir esses casos é um <em>Assert</em> básico.</p>
<p>O código acima com Assert ficaria assim:</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">procedure</span> ShowText<span style="color: #000066;">&#40;</span>List<span style="color: #000066;">:</span> TStringList<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  <span style="color: #808080; font-style: italic;">// Exceção (EAssert) caso List seja inválido</span>
  <span style="color: #000066;">Assert</span><span style="color: #000066;">&#40;</span>List &lt;&gt; <span style="color: #000000; font-weight: bold;">nil</span><span style="color: #000066;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// A partir daqui é seguro usar List</span>
  ShowMessage<span style="color: #000066;">&#40;</span>List<span style="color: #000066;">.</span><span style="color: #006600;">Text</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;</pre></div></div>

<p><em>Assert</em> tem como parâmetro um valor condicional (Boolean). Se falhar (False), dispara uma exceção <em>EAssert</em>. A vantagem é que, ao contrário de uma exceção de violação de acesso, a IDE vai te mostrar certinho onde ocorreu a violação, isto é, vai parar o debugger naquela linha do <em>Assert</em>. Sem uma verificação desse tipo, seria muito mais difícil identificar em todo o seu projeto o ponto que deu problema.</p>
<p>Se você quiser, pode ainda usar usar o segundo parâmetro opcional de Assert para dar uma mensagem ao usuário. Por exemplo: &#8220;Assert(List &lt;&gt; nil, &#8216;A função ShowText não recebeu um objeto TStringList válido&#8217;)&#8221;.</p>
<p>Outra vantagem do Assert é que depois que você estiver confiante da correção do código (quando esse dia chegar :) ), você poderá desativar um checkbox nas opções de compilação do Delphi para<br />
simplesmente omitir todo o código de verificação de &#8220;Assert&#8221; globalmente no projeto (lembre-se de dar um Build depois que mudar essa opção).</p>
<p>Dá muito trabalho? &#8220;Better safe, than sorry.&#8221;</p>
<p>Que atire a primeira pedra quem nunca fez um &#8220;Access Violation&#8221;. ;-)</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=Z9AWFk"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=Z9AWFk" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=iIiITK"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=iIiITK" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=SUrjjK"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=SUrjjK" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/366895565" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/08/previna-av-com-assert/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/08/previna-av-com-assert/</feedburner:origLink></item>
		<item>
		<title>Serialização de Variants</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/363447185/</link>
		<comments>http://singularsistemas.com.br/blog/2008/08/serializacao-de-variants/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 01:31:28 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[RTL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=89</guid>
		<description><![CDATA[Estou trabalhando em um projeto que faz uso extensivo de variáveis do tipo Variant que precisam ser armazenadas em objetos TStream. Os valores podem ser de qualquer tipo: inteiros, strings, datas e até arrays. Os streams são então levados de um lugar para outro em arquivos ou diretamente pela rede para serem lidos por outro [...]]]></description>
			<content:encoded><![CDATA[<p>Estou trabalhando em um projeto que faz uso extensivo de variáveis do tipo Variant que precisam ser armazenadas em objetos <em>TStream</em>. Os valores podem ser de qualquer tipo: inteiros, strings, datas e até arrays. Os streams são então levados de um lugar para outro em arquivos ou diretamente pela rede para serem lidos por outro processo.</p>
<p>É claro que eu não fui o primeiro a ter essa necessidade, então antes de começar a quebrar a cabeça fui buscar no Google as soluções que já tinham sido criadas. Primeiro encontrei um <a href="http://delphi.newswhat.com/geoxml/forumhistorythread?groupname=borland.public.delphi.oleautomation&amp;messageid=3f05926b@newsgroups.borland.com">comentário</a> de Deborah Pate (TeamB) no newsgroup Borland &#8220;oleautomation&#8221;. Foi um bom começo, mas ainda faltava muito.</p>
<p>Mais tarde encontrei os posts de <a href="http://npavlov.kodar.net/blog/?p=12">Nikolay Pavlov</a> - <em>nem acredito que encontrei um parente de <a href="http://pt.wikipedia.org/wiki/Ivan_petrovich_pavlov">Pavlov</a> e ainda um que programa em Delphi!</em> Nikolay estava bem mais próximo do que eu precisava, inclusive com o tratamento recursivo de arrays.</p>
<p>Como o código é livre, copiei, fiz diversas alterações e melhoramentos e estou publicando aqui a <a href="http://singularsistemas.com.br/blog/wp-content/streamvars.zip">minha versão</a> para quem se interessar.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=lzeWIk"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=lzeWIk" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=PalolK"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=PalolK" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=GGo7rK"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=GGo7rK" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/363447185" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/08/serializacao-de-variants/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/08/serializacao-de-variants/</feedburner:origLink></item>
		<item>
		<title>Notas 07/08/08</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/358466956/</link>
		<comments>http://singularsistemas.com.br/blog/2008/08/notas-070808/#comments</comments>
		<pubDate>Thu, 07 Aug 2008 14:31:19 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[CodeGear]]></category>

		<category><![CDATA[Tiburón]]></category>

		<category><![CDATA[tradução]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=87</guid>
		<description><![CDATA[Oi pessoal. Estamos de volta! Passei uns 2 meses sem escrever enquanto arrumava minha vida, me acomodando às muitas mudanças recentes. Se alguém interpretou minha ausência por abandono ou diminuição do meu interesse pelo Delphi, se enganou. Continuo investindo em novas tecnologias dentro e fora do mundo Delphi. Aliás, volto com várias idéias e experiências [...]]]></description>
			<content:encoded><![CDATA[<p>Oi pessoal. Estamos de volta! Passei uns 2 meses sem escrever enquanto arrumava minha vida, me acomodando às muitas mudanças recentes. Se alguém interpretou minha ausência por abandono ou diminuição do meu interesse pelo Delphi, se enganou. Continuo investindo em novas tecnologias dentro e fora do mundo Delphi. Aliás, volto com várias idéias e experiências novas para compartilhar.</p>
<p>***</p>
<p><em></em>A compra da CodeGear pela Embarcadero foi comercial e juridicamente finalizada a poucas semanas. Aqui no Brasil que eu saiba continua a mesma empresa e houve poucas mudanças na direção, embora agora se reportem a outra companhia lá fora.</p>
<p>***</p>
<p><a href="http://blogs.codegear.com/andreanolanusse/">Andreano Lanusse</a> apresentou um preview do Tiburon em português no dia 1 de agosto. A apresentação foi interessante e deixou uma boa impressão. O mais importante foi perceber que a CodeGear está mesmo investindo em melhorias no Delphi e em particular no Delphi Win32, ao contrário do que os pessimistas de plantão vinham dizendo. No blog do Andreano tem alguns artigos em português sobre as novidades do Delphi <span style="text-decoration: line-through;">2008</span> 2009 (codinome Tiburón).</p>
<p>***</p>
<p>&#8220;Anonymous methods&#8221; é um dos features mais polêmicos. No mínimo, é idéia interessante com um nome infeliz. Como apontou um <a href="http://blogs.codegear.com/andreanolanusse/2008/07/17/tiburon-anonymous-methods/#comment-3432">comentário</a> de Caleb, &#8220;anonymous methods&#8221; são de fato &#8220;<a href="http://en.wikipedia.org/wiki/Closure_(computer_science)">closures</a>&#8220;. O recurso de &#8220;closure&#8221; é comum em algumas linguagens modernas, mas ainda assim tem aplicabilidade questionável.</p>
<p>***</p>
<p>É engraçado para nós brasileiros a grande ênfase que se está dando a conversão completa de toda as libraries nativas Delphi (RTL, VCL, DBX, etc.) para Unicode. Eu lembro de ter assistido uma palestra em uma Borcon em que um representante da Borland americana foi pego de surpresa em público ao descobrir durante a apresentação que ninguém no Brasil tinha problemas com acentuação e ninguém estava ansioso por Unicode.</p>
<p>***</p>
<p>Unicode é bom para a globalização do Delphi. Por isso acaba sendo bom para todos nós, mesmo não tendo necessidade direta de usar Unicode (eu pelo menos não tenho pretensão de escrever programas em mandarin).</p>
<p>***</p>
<p>Não entendi ainda bem como funciona, mas fiquei admirado com a <span style="text-decoration: line-through;">nova</span> diretiva {$MethodInfo ON}, que permite inclusive o novo DataSnap evocar métodos remotos sem necessidade da parafernália Microsoft COM, interfaces, etc.</p>
<p><em>Atualização: Leonel comentou que a diretiva já existia em versões anteriores.</em></p>
<p>***</p>
<p>Aliás, por que diabos a CodeGear foi a essa altura do campeonato investir em melhorias na tecnologia COM? Há quem diga que estão &#8220;maqueando&#8221; correções de bugs como melhorias&#8230;</p>
<p>****</p>
<p>Delphi <a href="http://blogs.codegear.com/andreanolanusse/2008/07/24/tiburon-construindo-strings-com-tstringbuilder/">TStringBuilder</a> é legal. Já existe a muitos anos em bibliotecas gratuitas como JCL, mas é legal.</p>
<p>***</p>
<p>Eu quero meu Delphi Win32 com generics!!!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=HT1zuk"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=HT1zuk" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=G6QLmK"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=G6QLmK" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=jViGRK"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=jViGRK" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/358466956" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/08/notas-070808/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/08/notas-070808/</feedburner:origLink></item>
		<item>
		<title>DataSnap com Stored Procedures (1/3)</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/301854930/</link>
		<comments>http://singularsistemas.com.br/blog/2008/05/datasnap-com-stored-procedure-1/#comments</comments>
		<pubDate>Sat, 31 May 2008 13:05:24 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=76</guid>
		<description><![CDATA[A natureza do Delphi DataSnap é utilizar SQL dinâmico, que é construído e enviado em tempo de execução para o servidor. Talvez por isso muita gente não se dê conta que pode usar Stored Procedures (SP) em um servidor de aplicação DataSnap. Na verdade, nada nos impede usar SP para obter dados ou para resolver [...]]]></description>
			<content:encoded><![CDATA[<p>A natureza do Delphi DataSnap é utilizar SQL dinâmico, que é construído e enviado em tempo de execução para o servidor. Talvez por isso muita gente não se dê conta que pode usar Stored Procedures (SP) em um servidor de aplicação DataSnap. Na verdade, nada nos impede usar SP para obter dados ou para resolver atualizações no banco de dados e os SP podem ser muito úteis.</p>
<p>Vantagens de usar Stored Procedures:</p>
<ul>
<li>SP podem incluir lógica condicional, cursores, chamar outros SP, funções, etc.</li>
<li>SP são parametrizáveis (TParams)</li>
<li>SP são transações atômicas</li>
<li>SP são escritos em SQL</li>
<li>SP podem ser facilmente atualizados com o sistema no ar</li>
<li>SP têm plano de execução previamente &#8220;compilado&#8221;</li>
</ul>
<p>Desvantagens de usar Stored Procedures:</p>
<ul>
<li>SP não são portáveis entre bancos de dados diferentes</li>
<li>SP são somente-leitura</li>
<li>SP de SELECT dificultam a geração automática de SQL de atualização</li>
</ul>
<p>Usar SP não fere nenhum princípio de desenvolvimento multicamadas. De fato, o <a title="&quot;Lugar de SQL é no Servidor&quot;" href="http://singularsistemas.com.br/blog/2008/05/lugar-de-sql-e-no-servidor/">SQL fica no servidor</a>, não no cliente. Tem gente que prefere não ter nenhuma lógica no banco de dados e tratá-lo como um simples repositório de dados. Outros, pelo contrário, entendem que toda lógica de acesso a dados precisa estar no servidor de banco de dados. Finalmente, há aqueles, entre os quais eu me incluo, que preferem um equilíbrio, pesando custos e benefícios caso a caso.</p>
<p>Nos próximos artigos vou mostrar como usar SP para obter dados do servidor de aplicação e como usar SP para atualizar os dados em um <em>ApplyUpdates</em>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=HAhj2h"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=HAhj2h" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=YVWeOH"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=YVWeOH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=oJMmcH"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=oJMmcH" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/301854930" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/05/datasnap-com-stored-procedure-1/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/05/datasnap-com-stored-procedure-1/</feedburner:origLink></item>
		<item>
		<title>Scroll Grid Font Size</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/301210976/</link>
		<comments>http://singularsistemas.com.br/blog/2008/05/scroll-grid-font-size/#comments</comments>
		<pubDate>Fri, 30 May 2008 12:00:29 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[VCL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=83</guid>
		<description><![CDATA[Eu uso a toda hora Ctrl+Scroll do mouse para alterar o tamanho da fonte de uma página no browser. Daí eu fiquei com vontade de implementar isso no Delphi. Por que não um TDBGrid com a mesma funcionalidade?

No exemplo da imagem anterior, se você deixar o mouse sobre o grid e girar o botão de [...]]]></description>
			<content:encoded><![CDATA[<p>Eu uso a toda hora Ctrl+Scroll do mouse para alterar o tamanho da fonte de uma página no browser. Daí eu fiquei com vontade de implementar isso no Delphi. Por que não um TDBGrid com a mesma funcionalidade?</p>
<p><img class="alignnone size-full wp-image-84" title="grid-scroll-1" src="http://singularsistemas.com.br/blog/wp-content/grid-scroll-1.png" alt="" width="368" height="255" /></p>
<p>No exemplo da imagem anterior, se você deixar o mouse sobre o grid e girar o botão de rolagem para baixo enquanto mantém a tecla Control pressionada a fonte será aumentada até ficar como a imagem abaixo.</p>
<p><img class="alignnone size-full wp-image-85" title="grid-scroll-2" src="http://singularsistemas.com.br/blog/wp-content/grid-scroll-2.png" alt="" width="368" height="255" /></p>
<p>Semelhante ao que <a href="http://singularsistemas.com.br/blog/2008/04/usando-o-botao-scroll-em-um-tscrollbox/">fizemos anteriormente</a> para implementar a rolagem pelo mouse em um TScrollBox, tudo que é preciso é sobrescrever os eventos <em>OnMouseWheelDown</em> e <em>OnMouseWheelUp</em> com o tratamento adequado para aumentar ou diminuir o tamanho da fonte do grid, respectivamente.</p>
<p>O código principal é este:</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">DBGrid1MouseWheelDown</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>;
  Shift<span style="color: #000066;">:</span> TShiftState; MousePos<span style="color: #000066;">:</span> TPoint; <span style="color: #000000; font-weight: bold;">var</span> Handled<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Boolean</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  <span style="color: #000000; font-weight: bold;">if</span> ControlKeyPressed <span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #000000; font-weight: bold;">begin</span>
    ChangeGridFontSize<span style="color: #000066;">&#40;</span>DBGrid1<span style="color: #000066;">,</span> <span style="color: #000066;">+</span><span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
    Handled <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">True</span>;
  <span style="color: #000000; font-weight: bold;">end</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TMainForm<span style="color: #000066;">.</span><span style="color: #006600;">DBGrid1MouseWheelUp</span><span style="color: #000066;">&#40;</span>Sender<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">TObject</span>;
  Shift<span style="color: #000066;">:</span> TShiftState; MousePos<span style="color: #000066;">:</span> TPoint; <span style="color: #000000; font-weight: bold;">var</span> Handled<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Boolean</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  <span style="color: #000000; font-weight: bold;">if</span> ControlKeyPressed <span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #000000; font-weight: bold;">begin</span>
    ChangeGridFontSize<span style="color: #000066;">&#40;</span>DBGrid1<span style="color: #000066;">,</span> <span style="color: #000066;">-</span><span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
    Handled <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">True</span>;
  <span style="color: #000000; font-weight: bold;">end</span>;
<span style="color: #000000; font-weight: bold;">end</span>;</pre></div></div>

<p>Se a tecla Control não estiver pressionada, o valor de <em>Handled</em> continua False e o funcionamento normal da classe prossegue, rolando as linhas do grid. Se o resultado da função <em>ControlKeyPressed</em> (veja abaixo) é True, o botão Control está pressionado e devemos modificar o tamanho da fonte.</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> ControlKeyPressed<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Boolean</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000066; font-weight: bold;">Boolean</span><span style="color: #000066;">&#40;</span>GetKeyState<span style="color: #000066;">&#40;</span>VK_LCONTROL<span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">shr</span> <span style="color: #0000ff;">31</span><span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">or</span>
    <span style="color: #000066; font-weight: bold;">Boolean</span><span style="color: #000066;">&#40;</span>GetKeyState<span style="color: #000066;">&#40;</span>VK_RCONTROL<span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">shr</span> <span style="color: #0000ff;">31</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;</pre></div></div>

<p><em>GetKeyState</em> é uma função da API do Windows e a forma (bizarra) de interpretar seu resultado é verificar se o bit mais significante do resultado é 1. Na função eu verifico se o botão esquerdo ou o direito está pressionado naquele momento.</p>
<p>A mudança de tamanho da fonte em si é realizada pela rotina <em>ChangeGridFontSize</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">type</span>
  TDBGridHack <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #000066;">&#40;</span>TDBGrid<span style="color: #000066;">&#41;</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> ChangeGridFontSize<span style="color: #000066;">&#40;</span>Grid<span style="color: #000066;">:</span> TDBGrid; Delta<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">var</span>
  Size<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  Size <span style="color: #000066;">:</span><span style="color: #000066;">=</span> Grid<span style="color: #000066;">.</span><span style="color: #006600;">Font</span><span style="color: #000066;">.</span><span style="color: #006600;">Size</span> <span style="color: #000066;">+</span> Delta;
  <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #000066;">&#40;</span><span style="color: #0000ff;">6</span> &lt;<span style="color: #000066;">=</span> Size<span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">and</span> <span style="color: #000066;">&#40;</span>Size &lt;<span style="color: #000066;">=</span> <span style="color: #0000ff;">32</span><span style="color: #000066;">&#41;</span> <span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #000000; font-weight: bold;">begin</span>
    Grid<span style="color: #000066;">.</span><span style="color: #006600;">Font</span><span style="color: #000066;">.</span><span style="color: #006600;">Size</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> Size;
    TDBGridHack<span style="color: #000066;">&#40;</span>Grid<span style="color: #000066;">&#41;</span><span style="color: #000066;">.</span><span style="color: #006600;">LayoutChanged</span>;
  <span style="color: #000000; font-weight: bold;">end</span>;
<span style="color: #000000; font-weight: bold;">end</span>;</pre></div></div>

<p>Primeiro note que a procedure recebe um parâmetro Delta que pode ser positivo ou negativo. Se positivo, aumenta a fonte. Se negativo, diminui. A rotina limita o novo tamanho de fonte à faixa 6..32 por segurança.</p>
<p>E o que é esse TDBGridHack? Err&#8230; bem&#8230; digamos que é um &#8220;código de flexibilização&#8221;. :-)</p>
<p><em>LayoutChanged</em> é um método protegido de TDBGrid. Para poder usá-lo, precisamos declarar no escopo da unit uma classe descendente de TDBGrid. Dessa forma a nova classe será nossa &#8220;amiga&#8221; e poderemos usar seus métodos protegidos (mas não conte isso pra ninguém!). <em>LayoutChanged</em> é chamado para corrigir o número de linhas exibidas no grid quando a fonte é diminuida.</p>
<p>Você pode fazer o <a href="http://singularsistemas.com.br/blog/wp-content/FontScroll.zip">download</a> desse projeto de exemplo e experimentar a mesma técnica com outros tipos de componente.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=ovSX1h"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=ovSX1h" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=32fzTH"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=32fzTH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=lY0evH"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=lY0evH" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/301210976" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/05/scroll-grid-font-size/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/05/scroll-grid-font-size/</feedburner:origLink></item>
		<item>
		<title>TcxGrid como ListBox (parte 2/2)</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/299541447/</link>
		<comments>http://singularsistemas.com.br/blog/2008/05/tcxgrid-como-listbox-parte-22/#comments</comments>
		<pubDate>Wed, 28 May 2008 03:44:20 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[OOP]]></category>

		<category><![CDATA[VCL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=81</guid>
		<description><![CDATA[Na sequência (sem trema, pelas novas regras) do artigo anterior, veja como criar um descendente de TcxCustomDataSource para editar um TStringList (ou qualquer TStrings) com o componente TcxGrid.
Os componentes da DevExpress são excelentes exemplos de boa programação orientada a objetos. O conceito de GridView, por exemplo, é abstraído de tal forma que podemos ter visualização [...]]]></description>
			<content:encoded><![CDATA[<p>Na sequência (sem trema, pelas <a href="http://www1.folha.uol.com.br/folha/educacao/ult305u321373.shtml">novas regras</a>) do <a href="http://singularsistemas.com.br/blog/2008/05/tcxgrid-como-listbox-parte-12/">artigo anterior</a>, veja como criar um descendente de <em>TcxCustomDataSource</em> para editar um <em>TStringList</em> (ou qualquer <em>TStrings</em>) com o componente <em>TcxGrid</em>.</p>
<p>Os componentes da DevExpress são excelentes exemplos de boa programação orientada a objetos. O conceito de GridView, por exemplo, é abstraído de tal forma que podemos ter visualização como tabelas com linhas e colunas, gráficos ou cartões (&#8221;cards&#8221;), como os do gerenciador de contatos do Outlook. Por essa razão as &#8220;colunas&#8221; de um GridView são referidas como &#8220;Items&#8221;, já que não faria sentido chamar de coluna uma série de gráfico ou uma linha de um cartão.</p>
<p>A fonte de dados que alimenta um grid é também generalizada pela classe <em>TcxCustomDataSource</em>. A descendente <em>TcxDBDataSource</em> é especializada para trabalhar com datasets e implementa filtragem, agrupamento e cálculo de sumários. O componente <em>TcxGrid</em> não presume nada sobre a forma como os dados são obtidos, lidos e escritos. Lida apenas com os métodos e propriedades de <em>TcxCustomDataSource</em> e com isso permite o polimorfismo.</p>
<p>É fácil implementar um novo descendente de <em>TcxCustomDataSource </em>para lidar com <em>TStrings</em> ao invés de <em>TDataSet</em>. No exemplo abaixo são implementados apenas os métodos básicos que precisam ser sobrescritos em qualquer descendente de <em>TcxCustomDataSource</em>.</p>
<p>O resultado é um list box editável. Você pode usar as teclas de atalho &#8220;Ins&#8221; para inserir uma linha e &#8220;Ctrl+Del&#8221; para deletar. Também pode adicionar uma linha no final da lista no modo &#8220;append&#8221;.</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">{**********************************************}</span>
<span style="color: #808080; font-style: italic;">{                                              }</span>
<span style="color: #808080; font-style: italic;">{  cxStringsDataSource                         }</span>
<span style="color: #808080; font-style: italic;">{  by Daniel Maltarolli                        }</span>
<span style="color: #808080; font-style: italic;">{  http://singularsistemas.com.br/blog         }</span>
<span style="color: #808080; font-style: italic;">{                                              }</span>
<span style="color: #808080; font-style: italic;">{  01) 2008-05-22 Initial release              }</span>
<span style="color: #808080; font-style: italic;">{                                              }</span>
<span style="color: #808080; font-style: italic;">{**********************************************}</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">unit</span> cxStringsDataSource;
&nbsp;
<span style="color: #000000; font-weight: bold;">interface</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">uses</span> Classes<span style="color: #000066;">,</span> cxCustomData;
&nbsp;
<span style="color: #000000; font-weight: bold;">type</span>
  TcxStringsDataSource <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">class</span><span style="color: #000066;">&#40;</span>TcxCustomDataSource<span style="color: #000066;">&#41;</span>
  <span style="color: #000000; font-weight: bold;">private</span>
    FStrings<span style="color: #000066;">:</span> TStrings;
  <span style="color: #000000; font-weight: bold;">protected</span>
    <span style="color: #000000; font-weight: bold;">function</span> AppendRecord<span style="color: #000066;">:</span> TcxDataRecordHandle; <span style="color: #000000; font-weight: bold;">override</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> DeleteRecord<span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">:</span> TcxDataRecordHandle<span style="color: #000066;">&#41;</span>; <span style="color: #000000; font-weight: bold;">override</span>;
    <span style="color: #000000; font-weight: bold;">function</span> GetRecordCount<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>; <span style="color: #000000; font-weight: bold;">override</span>;
    <span style="color: #000000; font-weight: bold;">function</span> GetValue<span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">:</span> TcxDataRecordHandle; AItemHandle<span style="color: #000066;">:</span> TcxDataItemHandle<span style="color: #000066;">&#41;</span><span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Variant</span>; <span style="color: #000000; font-weight: bold;">override</span>;
    <span style="color: #000000; font-weight: bold;">function</span> InsertRecord<span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">:</span> TcxDataRecordHandle<span style="color: #000066;">&#41;</span><span style="color: #000066;">:</span> TcxDataRecordHandle; <span style="color: #000000; font-weight: bold;">override</span>;
    <span style="color: #000000; font-weight: bold;">procedure</span> SetValue<span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">:</span> TcxDataRecordHandle; AItemHandle<span style="color: #000066;">:</span> TcxDataItemHandle; <span style="color: #000000; font-weight: bold;">const</span> AValue<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Variant</span><span style="color: #000066;">&#41;</span>; <span style="color: #000000; font-weight: bold;">override</span>;
  <span style="color: #000000; font-weight: bold;">public</span>
    <span style="color: #000000; font-weight: bold;">constructor</span> Create<span style="color: #000066;">&#40;</span>Strings<span style="color: #000066;">:</span> TStrings<span style="color: #000066;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">implementation</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">uses</span> SysUtils<span style="color: #000066;">,</span> Variants;
&nbsp;
<span style="color: #808080; font-style: italic;">{ TcxStringsDataSource }</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">constructor</span> TcxStringsDataSource<span style="color: #000066;">.</span><span style="color: #006600;">Create</span><span style="color: #000066;">&#40;</span>Strings<span style="color: #000066;">:</span> TStrings<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  <span style="color: #000000; font-weight: bold;">inherited</span> Create;
  FStrings <span style="color: #000066;">:</span><span style="color: #000066;">=</span> Strings;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> TcxStringsDataSource<span style="color: #000066;">.</span><span style="color: #006600;">AppendRecord</span><span style="color: #000066;">:</span> TcxDataRecordHandle;
<span style="color: #000000; font-weight: bold;">begin</span>
  FStrings<span style="color: #000066;">.</span><span style="color: #000066;">Append</span><span style="color: #000066;">&#40;</span>EmptyStr<span style="color: #000066;">&#41;</span>;
  DataChanged;
  Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> TcxDataRecordHandle<span style="color: #000066;">&#40;</span>FStrings<span style="color: #000066;">.</span><span style="color: #006600;">Count</span> <span style="color: #000066;">-</span> <span style="color: #0000ff;">1</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TcxStringsDataSource<span style="color: #000066;">.</span><span style="color: #006600;">DeleteRecord</span><span style="color: #000066;">&#40;</span>
  ARecordHandle<span style="color: #000066;">:</span> TcxDataRecordHandle<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  FStrings<span style="color: #000066;">.</span><span style="color: #000066;">Delete</span><span style="color: #000066;">&#40;</span><span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">&#41;</span><span style="color: #000066;">&#41;</span>;
  DataChanged;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> TcxStringsDataSource<span style="color: #000066;">.</span><span style="color: #006600;">GetRecordCount</span><span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> FStrings<span style="color: #000066;">.</span><span style="color: #006600;">Count</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> TcxStringsDataSource<span style="color: #000066;">.</span><span style="color: #006600;">GetValue</span><span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">:</span> TcxDataRecordHandle;
  AItemHandle<span style="color: #000066;">:</span> TcxDataItemHandle<span style="color: #000066;">&#41;</span><span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Variant</span>;
<span style="color: #000000; font-weight: bold;">var</span>
  Index<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  Index <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">&#41;</span>;
  Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> FStrings<span style="color: #000066;">.</span><span style="color: #006600;">Strings</span><span style="color: #000066;">&#91;</span>Index<span style="color: #000066;">&#93;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> TcxStringsDataSource<span style="color: #000066;">.</span><span style="color: #006600;">InsertRecord</span><span style="color: #000066;">&#40;</span>
  ARecordHandle<span style="color: #000066;">:</span> TcxDataRecordHandle<span style="color: #000066;">&#41;</span><span style="color: #000066;">:</span> TcxDataRecordHandle;
<span style="color: #000000; font-weight: bold;">var</span>
  Index<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  Index <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">&#41;</span>;
  FStrings<span style="color: #000066;">.</span><span style="color: #000066;">Insert</span><span style="color: #000066;">&#40;</span>Index<span style="color: #000066;">,</span> EmptyStr<span style="color: #000066;">&#41;</span>;
  DataChanged;
  Result <span style="color: #000066;">:</span><span style="color: #000066;">=</span> ARecordHandle;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">procedure</span> TcxStringsDataSource<span style="color: #000066;">.</span><span style="color: #006600;">SetValue</span><span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">:</span> TcxDataRecordHandle;
  AItemHandle<span style="color: #000066;">:</span> TcxDataItemHandle; <span style="color: #000000; font-weight: bold;">const</span> AValue<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Variant</span><span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">var</span>
  Index<span style="color: #000066;">:</span> <span style="color: #000066; font-weight: bold;">Integer</span>;
<span style="color: #000000; font-weight: bold;">begin</span>
  Index <span style="color: #000066;">:</span><span style="color: #000066;">=</span> <span style="color: #000066; font-weight: bold;">Integer</span><span style="color: #000066;">&#40;</span>ARecordHandle<span style="color: #000066;">&#41;</span>;
  FStrings<span style="color: #000066;">.</span><span style="color: #006600;">Strings</span><span style="color: #000066;">&#91;</span>Index<span style="color: #000066;">&#93;</span> <span style="color: #000066;">:</span><span style="color: #000066;">=</span> VarToStrDef<span style="color: #000066;">&#40;</span>AValue<span style="color: #000066;">,</span> EmptyStr<span style="color: #000066;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">end</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">end</span><span style="color: #000066;">.</span></pre></div></div>

<p>Você precisa atribuir por código um objeto <em>TcxStringsDataSource</em> a GridView.DataController.CustomDataSource. É importante que o GridView seja um <em>TcxTableView</em>, não um <em>TcxDBTableView</em>. Para isso você precisará primeiro deletar no Form Designer o <em>TcxDBTableView</em> que é criado por default, criar um novo TableView e atribuí-lo a GridLevel1.</p>
<p>As propriedades do GridView são semelhantes àquelas usadas na <a href="http://singularsistemas.com.br/blog/2008/05/tcxgrid-como-listbox-parte-12/">parte um</a>, porém deixando o grid editável e &#8220;OptionsSelection.CellSelect = True&#8221;.</p>
<p>Veja um exemplo completo de utilização no <a href="http://singularsistemas.com.br/blog/wp-content/cxStringsDataSource.zip">arquivo anexo</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=8KP5Fh"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=8KP5Fh" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=Bqnf6H"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=Bqnf6H" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=R8gKfH"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=R8gKfH" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/299541447" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/05/tcxgrid-como-listbox-parte-22/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/05/tcxgrid-como-listbox-parte-22/</feedburner:origLink></item>
		<item>
		<title>TcxGrid como ListBox (parte 1/2)</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/298514022/</link>
		<comments>http://singularsistemas.com.br/blog/2008/05/tcxgrid-como-listbox-parte-12/#comments</comments>
		<pubDate>Mon, 26 May 2008 17:28:17 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[DevExpress]]></category>

		<category><![CDATA[VCL]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=80</guid>
		<description><![CDATA[Por que alguém reduziria um componente poderoso de grid como o QuantumGrid da DevExpress a um simples ListBox? Por várias razões, mas principalmente por mesclar alguns recursos avançados do TcxGrid com a simplicidade de um componente universalmente conhecido pelos usuários.
Pra começar, você pode usá-lo para selecionar registros em um dataset através de um campo qualquer. [...]]]></description>
			<content:encoded><![CDATA[<p>Por que alguém reduziria um componente poderoso de grid como o <a href="http://www.devexpress.com/Products/VCL/ExQuantumGrid/index.xml">QuantumGrid</a> da <a href="http://www.devexpress.com/">DevExpress</a> a um simples ListBox? Por várias razões, mas principalmente por mesclar alguns recursos avançados do TcxGrid com a simplicidade de um componente universalmente conhecido pelos usuários.</p>
<p>Pra começar, você pode usá-lo para selecionar registros em um dataset através de um campo qualquer. Basta configurar algumas propriedades do <em>TcxGridDBTableView</em> para obter o &#8220;look and feel&#8217; de um autêntico <em>TListBox</em> data-aware.</p>
<p>Pra começar, adicione a coluna para o campo que você quer selecionar. Pode também ser mais de uma coluna, mas aí já sai um pouquinho do padrão comum de um ListBox. Em seguida, ajuste as propriedades do GridView como indicado abaixo.</p>
<p>Em <em>OptionsView</em> ocultamos o Header, o GroupByBox e as linhas de grid. <em>ColumnAutoWidth </em>garante que a coluna ocupe perfeitamente a largura interna do grid. <em>CellEndEllipsis</em> dá um toque sofisticado, mostrando reticências (&#8221;&#8230;&#8221;) no fim de um item que não caiba totalmente na área cliente.</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;">OptionsView<span style="color: #000066;">.</span><span style="color: #006600;">CellEndEllipsis</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">True</span>
OptionsView<span style="color: #000066;">.</span><span style="color: #006600;">ColumnAutoWidth</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">True</span>
OptionsView<span style="color: #000066;">.</span><span style="color: #006600;">GridLines</span> <span style="color: #000066;">=</span> glNone
OptionsView<span style="color: #000066;">.</span><span style="color: #006600;">GroupByBox</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">False</span>
OptionsView<span style="color: #000066;">.</span><span style="color: #006600;">Header</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">False</span></pre></div></div>

<p>Em <em>OptionsSelection</em>, precisamos desabilitar <em>CellSelect</em>, para ter a barra de seleção esperada.</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;">OptionsSelection<span style="color: #000066;">.</span><span style="color: #006600;">CellSelect</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">False</span></pre></div></div>

<p>Em <em>OptionsBehavior</em>, temos alguns extras interessantes. <em>CellHints</em> mostra automaticamente hints popup quando o mouse para sobre uma linha cujo texto que não cabe inteiramente na largura. <em>IncSearch</em> ativa a busca incremental pelo teclado. <em>PullFocusing</em> produz o efeito de rolar as linhas quando o mouse é clicado sobre uma linha e arrastado enquanto é mantido pressionado.</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;">OptionsBehavior<span style="color: #000066;">.</span><span style="color: #006600;">CellHints</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">True</span>
OptionsBehavior<span style="color: #000066;">.</span><span style="color: #006600;">IncSearch</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">True</span>
OptionsBehavior<span style="color: #000066;">.</span><span style="color: #006600;">PullFocusing</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">True</span></pre></div></div>

<p>Finalmente, em OptionsData desabilitamos a edição, para ter um grid read-only.</p>

<div class="wp_syntax"><div class="code"><pre class="delphi delphi" style="font-family:monospace;">OptionsData<span style="color: #000066;">.</span><span style="color: #006600;">Deleting</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">False</span>
OptionsData<span style="color: #000066;">.</span><span style="color: #006600;">Editing</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">False</span>
OptionsData<span style="color: #000066;">.</span><span style="color: #006600;">Inserting</span> <span style="color: #000066;">=</span> <span style="color: #000000; font-weight: bold;">False</span></pre></div></div>

<p>Pronto. Com essas configurações é possível selecionar um registro simplesmente mostrando o &#8220;list box&#8221; para o usuário escolher pelo nome, com direito a busca incremental, reticências e hints para textos longos, além da barra de rolagem horizontal, que por default um ListBox não tem.</p>
<p>Na próxima parte deste artigo, vou mostrar como usar um TcxGrid para <em>editar</em> o conteúdo de um objeto TStrings qualquer usando um &#8220;CustomProvider&#8221;.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=dxB1Ph"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=dxB1Ph" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=5gRr9H"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=5gRr9H" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=NsuiFH"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=NsuiFH" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/298514022" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/05/tcxgrid-como-listbox-parte-12/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/05/tcxgrid-como-listbox-parte-12/</feedburner:origLink></item>
		<item>
		<title>Importe de XLS, Access, DBF e muito mais</title>
		<link>http://feeds.feedburner.com/~r/MaltaOnDelphi/~3/295912011/</link>
		<comments>http://singularsistemas.com.br/blog/2008/05/importe-de-xls-access-dbf-e-muito-mais/#comments</comments>
		<pubDate>Thu, 22 May 2008 15:48:27 +0000</pubDate>
		<dc:creator>Malta</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[DevExpress]]></category>

		<guid isPermaLink="false">http://singularsistemas.com.br/blog/?p=79</guid>
		<description><![CDATA[Eu uso a vários anos os componentes SMImport no Delphi para importar dados de arquivos em diversos formatos. Os componentes são muito flexíveis, rápidos, estáveis e suportam mais de 20 formatos diferentes de arquivo, incluindo XLS, XML, DBF, Access, Paradox e TXT.
A Scalabium tem também os componentes SMExport, que permitem exportar um dataset ou qualquer [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.scalabium.com/"><img class="alignright" style="float: right; border: 0px; margin-left: 4px;" src="http://www.scalabium.com/images/smischema.gif" alt="SMImport" width="165" height="120" /></a>Eu uso a vários anos os componentes <a href="http://www.scalabium.com/smi/index.htm">SMImport</a> no Delphi para importar dados de arquivos em diversos formatos. Os componentes são muito flexíveis, rápidos, estáveis e suportam mais de 20 formatos diferentes de arquivo, incluindo XLS, XML, DBF, Access, Paradox e TXT.</p>
<p>A <a href="http://www.scalabium.com/">Scalabium</a> tem também os componentes <a href="http://www.scalabium.com/sme/index.htm">SMExport</a>, que permitem exportar um dataset ou qualquer outra fonte de dados para uma série de formatos.</p>
<p>Eu comprei o pacote com os dois, SMImport e SMExport. Hoje em dia para exportar eu uso só o DevExpress, mas continuo confiando no SMImport para dar aos usuários das minhas aplicações a possibilidade de importar sozinhos dados de diversos formatos. É uma funcionalidade muito apreciada pelos usuários finais e por isso o investimento se paga rapidamente.</p>
<p>Hoje foi publicada uma nova versão do SMImport que implementa o formato de arquivo 12 do Excel, além de várias outras melhorias e atualizações.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=8BsgMh"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=8BsgMh" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=Faw5uH"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=Faw5uH" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/MaltaOnDelphi?a=MltLcH"><img src="http://feeds.feedburner.com/~f/MaltaOnDelphi?i=MltLcH" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/MaltaOnDelphi/~4/295912011" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://singularsistemas.com.br/blog/2008/05/importe-de-xls-access-dbf-e-muito-mais/feed/</wfw:commentRss>
		<feedburner:origLink>http://singularsistemas.com.br/blog/2008/05/importe-de-xls-access-dbf-e-muito-mais/</feedburner:origLink></item>
	</channel>
</rss>
