Cesar Romero

Delphi programming

Melhorando a aparência de imagens desabilitas no TImageList

Uma imagem pode explicar melhor o sentido deste post, veja como a aparência dos botões desabilitados da segunda imagem são melhores que da primeira imagem.

Desabled Images

Para deixar as imagens deste jeito eu usei 2 experts, primeiro o expert IDE Gradient para definir a aparência da barra de ferramentas com ou sem gradiente e o expert Delphi Nice Toolbar para melhorar a aparência das imagens.

Mas que tal se aplicar isto para todos os seus programas, além da IDE do Delphi? Para isto é necessário reimplementar parte do código do TImageList, então eu criei um QC para isto no Quality Central:

Report No: 80997            Status: Reported
Better look for TImageList disabled Images
http://qc.codegear.com/wc/qcmain.aspx?d=80997
QCWIN:Defect_No=80997

Se quer ver esta melhoria implementada por padrão no Delphi, vote neste QC, só clicar no link, fazer login com sua conta do EDN e votar, lembre-se que você pode dar até 10 votos por cada QC, se este QC tiver um bom número de votos, você pode ter esta melhoria na próxima versão do Delphi.

Este QC parece ser bem recebido pela comunidade, alguns grandes programadores conhecidos entraram em contato, um deles foi Anders Melander que até enviou um código que já pode ser utilizado nos nossos programas pra melhorar a aparência das imagens desabilitadas. Já que ele mandou o código para que eu incluísse no QC, não vejo problemas em divulgar aqui.

interface

uses
  ...

//---------------------------------------------------------------
//
//      TImageList work around for disabled glyph state
//
//---------------------------------------------------------------
// Insert this declaration before your form is declared to enable the
// workaround.
// This class can be deleted if TImageList is ever fixed.
//---------------------------------------------------------------
type
  TImageList = class(Controls.TImageList)
  protected
    procedure DoDraw(Index: Integer; Canvas: TCanvas; X, Y: Integer;
      Style: Cardinal; Enabled: Boolean = True); override;
  end;

implementation

uses
  CommCtrl,
  ...;

procedure TImageList.DoDraw(Index: Integer; Canvas: TCanvas; X, Y: Integer;
  Style: Cardinal; Enabled: Boolean);
var
  i: integer;
  Glyph, Mask: TBitmap;
begin
  if HandleAllocated then
  begin
    if (Enabled) then
    begin
      inherited;
      exit;
    end;

    Glyph := TBitmap.Create;
    try
      Glyph.SetSize(Width, Height);
      Glyph.PixelFormat := pf32bit;
      Glyph.Transparent := (ColorDepth <> cd32Bit);

      // Clear entire glyph - including alpha
      for i := 0 to Glyph.Height-1 do
        FillChar(Glyph.ScanLine[i]^, Glyph.Width*SizeOf(DWORD), $00);

      // Get glyph from imagelist
      ImageList_Draw(Handle, Index, Glyph.Canvas.Handle, 0, 0,
        ILD_TRANSPARENT);

      // Synthesize the disabled glyph image
      // TODO : Increase contrast of desaturated image.
      Desaturate(Glyph, 255);

      if (ColorDepth = cd32Bit) then
      begin
        // Note: Glyph.AlphaFormat should be done after the image has been
        // desaturated; afDefined premultiplies the RGB.
        Glyph.AlphaFormat := afDefined;
        // Alpha blended glyph
        // Draw glyph with AlphaBlend() via TBitmap.Draw().
        Canvas.Draw(X, Y, Glyph);
      end else
      begin
        // Masked glyph
        Mask := TBitmap.Create;
        try
          Mask.SetSize(Width, Height);
          Mask.Monochrome := True;
          Mask.Canvas.Brush.Color := clWhite;
          Mask.Canvas.FillRect(Rect(0, 0, Width, Height));
          // Get glyph mask from imagelist
          ImageList_Draw(Handle, Index, Mask.Canvas.Handle, 0, 0, ILD_MASK);

          // Draw glyph masked with MaskBlt
          //
          // MakeROP4($00AA0029, SRCCOPY):
          //   if (Mask = 1) then Dest := Dest
          //   if (Mask = 0) then Dest := SRCCOPY (translate black to
          //     TextColor, white to BkColor)
          // For each white pixel in the mask do nothing ($00AA0029 = NOOP).
          // For each black pixel in the mask draw the glyph.
          // Note: The special handling required by palette target devices
          // has not been implemented.
          MaskBlt(Canvas.Handle, 0, 0, Width, Height,
            Glyph.Canvas.Handle, 0, 0,
            Mask.Handle, 0, 0,
            MakeROP4($00AA0029, SRCCOPY));
        finally
          Mask.Free;
        end;
      end;

    finally
      Glyph.Free;
    end;
  end;
end;

Para utilizar este código, basta colocar na mesma unit do form onde está o componente TImageList. O compilador vai utilizar esta versão de TImageList.DoDraw no lugar da versão original da VCL.

O código do expert Delphi Nice Toolbar também pode ser utilizado para melhorar a aparência da ToolBar nos seus programas, ele usa o método de “patch” em memória, método utilizado pelo Andreas Hausladen no DelphiSpeedUP e no IDE Fix Pack.

Delphi Prism – Microsoft Case Studies

Nick Hodges postou em seu blog sobre o Estudo de Caso que a Microsoft fez sobre o Delphi Prism, elogiando o projeto criado utilizando o Visual Studio Shell.

Referências:

Turbo Power OnGuard 1.14

Roman Kassebaum anunciou a versão 1.14 do Turbo Power OnGuard. Esta versão suporta Delphi 2009 e Delphi 2010.

Site do projeto e download:
https://sourceforge.net/projects/tponguard/

VirtualTreeView no Delphi 2010

A VirtualTreeView  tem um bug quando utilizada com temas que causa um AV, a correção é bem simples, na unit VirtualTrees.pas procure pelo método local “procedure FillBitmap (ABitmap: TBitmap);”  e altere a linha

if not (coParentColor in FHeader.FColumns[FHeader.FMainColumn].FOptions) then

para:

if (FHeader.FMainColumn > -1) and not (coParentColor in  FHeader.FColumns[FHeader.FMainColumn].FOptions) then

o método completo ficou assim:

  procedure FillBitmap (ABitmap: TBitmap);
  begin
    with ABitmap, Canvas do
    begin
      Width := Size.cx;
      Height := Size.cy;
      if IsWinVistaOrAbove and (tsUseThemes in FStates) and (toUseExplorerTheme in FOptions.FPaintOptions) then
      begin
        if (FHeader.FMainColumn > -1) and not (coParentColor in FHeader.FColumns[FHeader.FMainColumn].FOptions) then
          Brush.Color := FHeader.FColumns[FHeader.FMainColumn].Color
        else
          Brush.Color := Self.Color;
      end
      else
        Brush.Color := clFuchsia;
      Transparent := True;
      TransparentColor := Brush.Color;
      FillRect(Rect(0, 0, Width, Height));
    end;
  end;

Como eliminar quebras de linhas

Hoje estava trabalhando com uma unit com 36000 linhas, com muitos linhas entre os procedimentos, totalmente desnecessário e procurei uma forma de deixar apenas uma linha entre os procedimentos.

Consegui fazer com o Notepad++, muito fácil:

  1. É necessário encontrar pelo menos 3 quebras de linhas seguidas: “\r\n\r\n\r\n”
  2. Marcar o modo de busca extendido
  3. Desmarcar busca no texto selecionado
  4. Substituir todos

Eliminei mais de 3000 linhas da unit.

Compendium – Filtros “Open Source” para DataSnap 2010

DSFC – DataSnap Filters Compendium, é um conjunto de 9 filtros para DataSnap 2010, divididos em 3 grupos:

HASH

  • MD5
  • MD4
  • SHA1
  • SHA512

CIPHER

  • Blowfish
  • Rijndael
  • 3TDES
  • 3DES

COMPRESS

  • LZO

Links

Limpando os arquivos do Windows Vista após SP2

Em um artigo anterior eu falei sobre como limpar os arquivos após a instalação do Vista SP1, hoje lembrei que já tenho o SP2 e fui procurar como torná-lo permanente, eliminando os arquivos anteriores.

Descobri que há um utilitário em “C:\windows\system32\compcln.exe” que torna permanente qualquer service pack ou atualização, eliminando o backup dos arquivos de versão anteriores, guardados caso você queira desinstalar uma destas atualizações.

Compcln

Compcln

Everything search engine

Hoje conheci este sensacional indexador de arquivos, pequeno, leve e eficiente. O melhor que já usei, antes testei o Google Desktop, Copernic e o padrão do Windows Vista.

Everything

O instalador completo tem apenas 334 KB, e vem com servidor ftp e http embutidos. O banco de dados também é mínimo, e ele indexou todo meu HD em menos de 2 minutos. Toda esta eficiência é por que ele indexa apenas o nome dos arquivos e pastas e não o seu conteúdo, o que pra mim é o ideal.

Ele tem várias opções para personalizar, como adicionar ou excluir pastas da indexação, suporte a internacionalização na interface, alem de configurações de visualização e servidores FTP e HTTP.

No Forum encontrei um plugin HotKeys, que com um duplo click no CTRL direito, ele faz a busca da palavra selecionada, 2x no shift ele busca no google, a combinação realmente faz a busca por arquivos ser algo simples e eficiente.

Referências

madExcept 3.0k para Delphi 2010

Mathias Rauen (Aka madshi ), acabou de disponibilizar o madExcept versão 2.5.11.1 com suporte ao Delphi 2010.

Eu estava esperando esta versão para poder compilar o Xananews com o Delphi 2010.

A lista de alterações desde a última versão:

- added Delphi/BCB 2010 support
- added detection for Win2008, Win7, Win2008r2
- fixed: cleartext disassembly missed instruction labels
- fixed: cleartext instruction labels were sometimes wrong
- madListProcesses: added gdi/user object count
- added %exceptClass%
- only exe modules hook/protect new threads by default now
- added HookThreads/DontHookThreads to overwrite default
- undocumented OnExceptBoxDestroy callback added
- fixed: in certain situations bug report wasn’t saved
  • added Delphi/BCB 2010 support
  • added detection for Win2008, Win7, Win2008r2
  • fixed: cleartext disassembly missed instruction labels
  • fixed: cleartext instruction labels were sometimes wrong
  • madListProcesses: added gdi/user object count
  • added %exceptClass%
  • only exe modules hook/protect new threads by default now
  • added HookThreads/DontHookThreads to overwrite default
  • undocumented OnExceptBoxDestroy callback added
  • fixed: in certain situations bug report wasn’t saved

Referências

TSQLConnection.Params como ConnectionString

Pra quem está acostumado a trabalhar com as tecnologias de banco de dados da Microsoft como ADO, sabe que as configurações de conexão de banco de dados são passadas em uma propriedade chamada ConnectionString, uma linha única contendo todos os parâmetros da conexão separados por ponto e vírgula, diferente da propriedade Params do TSQLConnection, que é uma TStringList.
Ontem eu estava reescrevendo umas classes auxiliares para o TSQLConnection, que agora são especialização de uma classe que salva e carrega as configurações da aplicação em um único arquivo XML, onde cada Objeto é um nó do XML, e cada TSQLConnection tem seu nó XML reservado, mas salvar como TStrings, ficava muito estranho no XML, então fiz umas alterações na minha classe para simular a propriedade ConnectionString.

A primeira alteração foi no método SetSQLConnection, onde eu defino 2 propriedades do Params, “StrictDelimiter = True” e “Delimiter:= ‘;’”.

procedure TDBHelper.SetSQLConnection(SQLConnection: TSQLConnection);
begin
  FSQLConnection:= SQLConnection;
  if (FSQLConnection = nil) then
    Exit;
  CloseConnection;
  FSQLConnection.Params.StrictDelimiter:= True;
  FSQLConnection.Params.Delimiter:= ';';
  // <snip>
end;

Em seguida implementei os métodos GetConnectionString e SetConnectionString, interagindo com a propriedade DelimitedText do TStringList.

function TDBHelper.GetConnectionString: string;
begin
 Result:= FSQLConnection.Params.DelimitedText;
end;

procedure TDBHelper.SetConnectionString(const Value: string);
begin
  FSQLConnection.Params.DelimitedText:= Value;
end;

A propriedade ConnectionString salva em XML ficou assim:

<property name="ConnectionString">
  drivername=FIREBIRD;blobsize=-1;commitretain=False;
  database=D:\DB\HTMCDATA.FDB;localecode=0000;
  Password=masterkey;rolename=RoleName;sqldialect=3;
  isolationlevel=ReadCommitted;user_name=sysdba;waitonlocks=False;
  trim char=True;HostName=localhost;ServerCharSet=WIN1252
</property>

Meu próximo passo neste projeto é adicionar ao sistema, um editor de XML visual que comecei a escrever, ainda não está pronto, mas já me ajuda em algumas tarefas básicas.


XmlViewer


XmlViewer