Macros e Arrays Constantes

Quem acompanha o DelphiFeeds deve conhecer os recentes posts do Joe White sobre macros na IDE Delphi. Depois que ele começou a escrever a algumas semanas, um monte de gente começou a postar suas macros preferidas.

Pra não ficar de fora, eu também vou falar um pouco das minhas macros. :-)

Macros são séries de teclas digitadas pelo usuário no editor de código que podem ser repetidas. Pressione Ctrl+Shift+R (R de Record) para iniciar a gravação de uma macro, digite qualquer seqüência de teclas (inclusive teclas de função e movimentos de cursor) e pressione novamente Ctrl+Shift+R para terminar a gravação. Pressione Ctrl+Ship+P (P de Play) para repetir a macro.

A situação é a seguinte: eu quero mostrar em run-time o valor corrente de uma propriedade enumeração para fazer debug.

Neste exemplo vamos mostrar o valor da propriedade State de um TDataSource, que é do tipo TDataSetState.

A declaração do tipo encontramos na interface da unit DB.pas:

TDataSetState = (dsInactive, dsBrowse, dsEdit, dsInsert,
  dsSetKey, dsCalcFields, dsFilter, dsNewValue, dsOldValue,
  dsCurValue, dsBlockRead, dsInternalCalc, dsOpening);

Arrays constantes

Em .NET poderíamos simplesmente fazer um typecast implícito da enumeração para string, mas em Win32 isso não é possível. Temos que fazer uma conversão manual para string.

Toda enumeração tem um valor numérico ordinal correspondente, por default baseado em 0 (zero). Por exemplo, o resultado de Ord(dsInactive) é 0, de Ord(dsBrowse) é 1 e por aí em diante. A idéia é usar esse valor ordinal como índice em um array constante que tenha os nomes de cada valor de TDataSetState, como o exemplo abaixo.

const
  DataSetStates: array[TDataSetState] of String = (
    'dsInactive',
    'dsBrowse',
    'dsEdit',
    'dsInsert',
    'dsSetKey',
    'dsCalcFields',
    'dsFilter',
    'dsNewValue',
    'dsOldValue',
    'dsCurValue',
    'dsBlockRead',
    'dsInternalCalc',
    'dsOpening');
begin
  ShowMessage(DataSetStates[DataSource1.State]);
end;

Notou que a indexação do array é o tipo de dado TDataSetState? Essa sintaxe é equivalente a dsInactive..dsOpening, que são, respectivamente, o primeiro e o último valores da enumeração.

As macros

O objetivo das macros é converter a definição do tipo de dado TDataSetSate em um array de strings constante.

Dividimos a tarefa em duas etapas. A primeira é quebrar os nomes em linhas e a segunda é colocar os espaços, apóstrofos e vírcula apropriadamente em cada linha.

Copie e cole a definição de TDataSetState no seu código e posicione o cursor no início da primeira palavra (dsInactive). Vamos fazer a primeira macro:

  1. Ctrl+Shift+R (iniciar gravação)
  2. Ctrl+Right (próxima palavra)
  3. Enter (quebra linha)
  4. Ctrl+Shift+R (terminar gravação)

Pronto. Já temos uma macro gravada. Agora apenas pressione seguidamente Ctrl+Shift+P para repetir o processo para cada item.

Como já havia duas quebras de linha no código original, ficaram algumas linhas extra, que precisamos remover (a propósito, você sabia que Ctrl+Y apaga a linha corrente do cursor?).

Pra finalizar, a segunda macro:

Coloque o cursor na primeira linha (qualquer coluna) e digite:

  1. Ctrl+Shift+R (iniciar gravação)
  2. Home (início da linha)
  3. Ctrl+T (apaga espaços até a próxima palavra)
  4. 4 espaços (”indentação”)
  5. apóstrofo
  6. End (fim da linha)
  7. Left (pula a vírgula)
  8. apóstrofo
  9. Down (vai para a linha de baixo)
  10. Ctrl+Shift+R (terminar gravação)

Agora repita Ctrl+Shift+P para cada linha e você já tem todo o trabalho pesado feito, sem ter que lembrar dos nomes e da ordem dos valores, sem erros e muito rápido!

Experimente fazer o mesmo com TFieldType, para mostrar os tipos dos campos de um dataset.

Comments

5 Responses to “Macros e Arrays Constantes”

  1. Leonel on April 10th, 2008 2:35 pm

    Gosto bastante de macros, mas não gostei muito do exemplo. :)

    program Project1;
    {$APPTYPE CONSOLE}
    uses
      Db, TypInfo;
    var
      i: TDataSetState;
    begin
      for i := Low(TDataSetState) to High(TDataSetState) do
        Writeln(GetEnumName(TypeInfo(TDataSetState), Ord(i)));
      Readln;
    end.
  2. Malta on April 10th, 2008 2:57 pm

    Legal, Leonel. Não conhecia GetEnumName. Muito bom pra fazer debug.

    A técnica do array constante se justifica, no entanto, quando se quer um nome para exibição diferente do declarado no código. É o caso de FieldTypeNames em DB.pas (que basicamente só tira o prefixo “ft”), MenuKeyCaps em Menus.pas e ButtonNames em Dialogs.pas, todos exemplos comuns encontrados na VCL. Uma macro como essa ajuda a estabelecer o número e a sequência exata dos valores.

  3. francisco.gamarra on August 11th, 2008 10:33 pm

    Tem alguma maneira de criar um repositório de macros?

  4. Malta on August 11th, 2008 11:17 pm

    O GExperts tem um bom repositório de macros.

  5. francisco.gamarra on August 12th, 2008 8:36 am

    Alguém sabe alguma maneira de criar atalhos de teclados para essas macros? ou colocar botoes de atalho para elas?

Deixe uma Resposta




XHTML: Você pode usar essas tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="">