"Ok, o DBNavigator faz o trabalho de navegar pelos dados e gerenciar registros. Infelizmente, meus clientes desejam uma experiência mais amigável, como gráficos e legendas de botões personalizados... "
Este inquérito veio de um Desenvolvedor Delphi procurando uma maneira de aumentar o poder do componente DBNavigator.
O DBNavigator é um ótimo componente - fornece uma interface semelhante ao videocassete para navegar pelos dados e gerenciar registros em aplicativos de banco de dados. A navegação de registro é fornecida pelos botões Primeiro, Próximo, Anterior e Último. O gerenciamento de registros é fornecido pelos botões Editar, Postar, Cancelar, Excluir, Inserir e Atualizar. Em um componente, o Delphi fornece tudo o que você precisa para operar com seus dados.
No entanto, como também declarou o autor da consulta por e-mail, o DBNavigator não possui alguns recursos, como glifos personalizados, legendas de botões e outros.
Um DBNavigator mais poderoso
Muitos componentes Delphi possuem propriedades e métodos úteis que são marcados como invisíveis ("protegidos") para um desenvolvedor Delphi. Felizmente, para acessar esses membros protegidos de um componente, uma técnica simples chamada "hack protegido" pode ser usada.
Primeiro, você adiciona uma legenda a cada botão do DBNavigator, depois adiciona gráficos personalizados e, finalmente, habilita o OnMouseUp para cada botão.
Do DBNavigator "chato" a um dos seguintes:
- Gráficos padrão e legendas personalizadas
- Apenas legendas
- Gráficos e legendas personalizados
Vamos Rock 'n' Roll
O DBNavigator possui uma propriedade Buttons protegida. Este membro é uma matriz de TNavButton, um descendente de TSpeedButton.
Como cada botão nessa propriedade protegida é herdado do TSpeedButton, se você o utilizar, poderá trabalhar com as propriedades "padrão" do TSpeedButton, como: Legenda (uma sequência que identifica o controle para o usuário), Glyph (o bitmap que aparece no botão), Layout (determina onde a imagem ou o texto aparece no botão)...
Na unidade DBCtrls (onde DBNavigator está definido), você "lê" que a propriedade Buttons protegida é declarada como:
Botões: matriz[TNavigateBtn] do TNavButton;
Onde TNavButton herda de TSpeedButton e TNavigateBtn é uma enumeração, definida como:
TNavigateBtn =
(nbFirst, nbPrior, nbNext, nbLast, nbInsert,
nbDelete, nbEdit, nbPost, nbCancel, nbRefresh);
Observe que TNavigateBtn contém 10 valores, cada um identificando um botão diferente em um objeto TDBNavigator. Agora, vamos ver como hackear um DBNavigator:
DBNavigator aprimorado
Primeiro, configure um formulário Delphi de edição de dados simples, colocando pelo menos um DBNavigator, um DBGrid, um DataSoure e um Objeto de conjunto de dados de sua escolha (ADO, BDE, dbExpres, ...). Verifique se todos os componentes estão "conectados".
Segundo, corte um DBNavigator definindo uma classe "fictícia" herdada, acima da declaração Form, como:
tipo THackDBNavigator = classe(TDBNavigator);
tipo
TForm1 = classe(TForm)
...
Em seguida, para exibir legendas e gráficos personalizados em cada botão do DBNavigator, você precisará configurar alguns glifos. Você pode usar o componente TImageList e atribuir 10 imagens (.bmp ou .ico), cada uma representando uma ação de um botão específico de um DBNavigator.
Terceiro, no Evento OnCreate para o Form1, adicione uma chamada como:
procedimento TForm1.FormCreate (Remetente: TObject);
SetupHackedNavigator (DBNavigator1, ImageList1);
fim;
Certifique-se de adicionar a declaração deste procedimento na parte privada da declaração do formulário, como:
tipo
TForm1 = classe(TForm)
...
privateprocedure SetupHackedNavigator (const Navegador: TDBNavigator;
const Glifos: TImageList);
...
Quarto, adicione o procedimento SetupHackedNavigator. O procedimento SetupHackedNavigator adiciona gráficos personalizados a cada botão e atribui uma legenda personalizada a cada botão.
usa Botões; //!!! não esqueça
procedimento TForm1.SetupHackedNavigator
(const Navegador: TDBNavigator;
const Glifos: TImageList);
const
Legendas: matriz[TNavigateBtn] de corda =
('Inicial', 'Anterior', 'Posterior', 'Final', 'Adicionar',
'Apagar', 'Corrigir', 'Enviar', 'Retirar', 'Reviver');
(*
Legendas: array [TNavigateBtn] da string =
('Primeiro', 'Anterior', 'Próximo', 'Último', 'Inserir',
'Excluir', 'Editar', 'Publicar', 'Cancelar', 'Atualizar');
na Croácia (localizada):
Legendas: array [TNavigateBtn] da string =
('Prvi', 'Prethodni', 'Slijedeci', 'Zadnji', 'Dodaj',
'Obrisi', 'Promjeni', 'Spremi', 'Odustani', 'Osvjezi');
*)
var
btn: TNavigateBtn;
começar btn: = baixo (TNavigateBtn) para Alto (TNavigateBtn) faça com THackDBNavigator (Navigator) .Botões [btn] dobegin// da matriz Const das legendas
Legenda: = Legendas [btn];
// o número de imagens na propriedade Glyph
NumGlyphs: = 1;
// Remova o glifo antigo.
Glifo: = nada;
// Atribua o personalizado
Glifos. GetBitmap (Inteiro (btn), Glyph);
// gylph acima do texto
Layout: = blGlyphTop;
// explicado mais tarde
OnMouseUp: = HackNavMouseUp;
fim;
fim; (* SetupHackedNavigator *)
Ok, vamos explicar. Você percorre todos os botões no DBNavigator. Lembre-se de que cada botão é acessível a partir da propriedade da matriz Buttons protegida - portanto, a necessidade da classe THackDBNavigator. Como o tipo da matriz de botões é TNavigateBtn, você passa do "primeiro" (usando o Baixo função) até o "último" (usando o Alto função) um. Para cada botão, você simplesmente remove o glifo "antigo", atribui o novo (a partir do parâmetro Glyphs), adiciona a legenda da matriz Legendas e marca o layout do glifo.
Observe que você pode controlar quais botões são exibidos por um DBNavigator (não o invadido) por meio da propriedade VisibleButtons. Outra propriedade cujo valor padrão você pode querer alterar é Dicas - use-a para fornecer Dicas de Ajuda de sua escolha para o botão do navegador individual. Você pode controlar a exibição das dicas editando a propriedade ShowHints.
É isso aí. É por isso que você escolheu o Delphi!
Me de mais!
Por que parar aqui? Você sabe que, quando você clica no botão 'nbNext', a posição atual do conjunto de dados é avançada para o próximo registro. E se você quiser mover, digamos, 5 registros à frente se o usuário estiver segurando a tecla CTRL enquanto pressiona o botão? Que tal isso?
O DBNavigator "padrão" não possui o evento OnMouseUp - aquele que carrega o parâmetro Shift do TShiftState - permitindo testar o estado das teclas Alt, Ctrl e Shift. O DBNavigator fornece apenas o evento OnClick para você manipular.
No entanto, o THackDBNavigator pode simplesmente expor o evento OnMouseUp e permitir que você "veja" o estado das teclas de controle e até a posição do cursor acima do botão específico ao clicar!
Ctrl + Clique: = 5 linhas à frente
Para expor o OnMouseUp, basta atribuir seu procedimento personalizado de manipulação de eventos ao evento OnMouseUp para o botão do DBNavigator invadido. Isso já foi feito exatamente no procedimento SetupHackedNavigator:
OnMouseUp: = HackNavMouseUp;
Agora, o procedimento HackNavMouseUp pode se parecer com:
procedimento TForm1.HackNavMouseUp
(Remetente: TObject; Botão: TMouseButton;
Shift: TShiftState; X, Y: Inteiro);
const MoveBy: inteiro = 5;
beginifNÃO (O remetente é TNavButton) então Saída;
caso TNavButton (Remetente) .Index do
nbPrior:
E se (ssCtrl no Shift) então
TDBNavigator (TNavButton (Sender) .Parent).
Fonte de dados. DataSet. MoveBy (-MoveBy);
nbPróximo:
E se (ssCtrl no Shift) então
TDBNavigator (TNavButton (Sender) .Parent).
Fonte de dados. DataSet. MoveBy (MoveBy);
fim;
fim; (* HackNavMouseUp *)
Observe que você precisa adicionar a assinatura do procedimento HackNavMouseUp dentro da parte privada da declaração do formulário (próximo à declaração do procedimento SetupHackedNavigator):
tipo
TForm1 = classe(TForm)
...
privateprocedure SetupHackedNavigator (const Navegador: TDBNavigator;
const Glifos: TImageList);
procedimento HackNavMouseUp (Remetente: TObject; Botão: TMouseButton;
Shift: TShiftState; X, Y: Inteiro);
...
Ok, vamos explicar, mais uma vez. O procedimento HackNavMouseUp manipula o evento OnMouseUp para cada botão DBNavigator. Se o usuário estiver segurando a tecla CTRL enquanto clica no botão nbNext, o registro atual para o conjunto de dados vinculado é movido para "MoveBy" (definido como constante com o valor de 5).
O que? Muito complicado?
Sim. Você não precisa mexer com tudo isso se precisar verificar apenas o estado das teclas de controle quando o botão foi clicado. Veja como fazer o mesmo no "comum" Evento OnClick do DBNavigator "comum":
procedimento TForm1.DBNavigator1Click
(Remetente: TObject; Botão: TNavigateBtn);
função CtrlDown: Booleano;
var
Estado: TKeyboardState;
início
GetKeyboardState (State);
Resultado: = ((State [vk_Control] And 128) 0);
fim;
const MoveBy: inteiro = 5;
begincase Botão do
nbPrior:
E se CtrlDown então
DBNavigator1.DataSource. DataSet. MoveBy (-MoveBy);
nbPróximo:
E se CtrlDown então
DBNavigator1.DataSource. DataSet. MoveBy (MoveBy);
fim; //case
fim; (* DBNavigator2Click *)
Isso é tudo, pessoal
E, finalmente, o projeto está concluído. Ou você pode continuar. Aqui está um cenário / tarefa / ideia para você:
Digamos que você queira apenas um botão para substituir os botões nbFirst, nbPrevious, nbNext e nbLast. Você pode usar os parâmetros X e Y dentro do procedimento HackNavMouseUp para encontrar a posição do cursor quando o botão foi liberado. Agora, neste botão ("para governar todos"), você pode anexar uma imagem com quatro áreas, supondo que cada área imita um dos botões que você está substituindo... entendeu o ponto?