Come personalizzare il DBNavigator

“Ok, DBNavigator fa il suo lavoro di navigazione dei dati e gestione dei record. Sfortunatamente, i miei clienti vogliono un’esperienza più user-friendly, come la grafica dei pulsanti e le didascalie personalizzate, …”

Questa richiesta è arrivata da uno sviluppatore Delphi alla ricerca di un modo per aumentare la potenza del componente DBNavigator. 

DBNavigator è un ottimo componente: fornisce un’interfaccia simile a un videoregistratore per la navigazione dei dati e la gestione dei record nelle applicazioni di database. La navigazione tra i record è fornita dai pulsanti Primo, Successivo, Precedente e Ultimo. La gestione dei record è fornita dai pulsanti Modifica, Pubblica, Annulla, Elimina, Inserisci e Aggiorna. In un unico componente Delphi fornisce tutto ciò di cui hai bisogno per operare sui tuoi dati.

Tuttavia, come ha affermato anche l’autore della richiesta di posta elettronica, DBNavigator non dispone di alcune funzionalità come glifi personalizzati, didascalie dei pulsanti e altre.

Un DBNavigator più potente

Molti componenti Delphi hanno proprietà e metodi utili che sono contrassegnati come invisibili (“protetti”) da uno sviluppatore Delphi. Si spera che, per accedere a tali membri protetti di un componente, possa essere utilizzata una semplice tecnica chiamata “hack protetto”.

Innanzitutto, aggiungerai una didascalia a ogni pulsante DBNavigator, quindi aggiungerai grafica personalizzata e, infine, abiliterai OnMouseUp ogni pulsante. 

Dal “noioso” DBNavigator a uno di:

  • Grafica standard e didascalie personalizzate
  • Solo didascalie
  • Grafica personalizzata e didascalie personalizzate

Facciamo rock ‘n’ roll

Il DBNavigator ha una proprietà Buttons protetta. Questo membro è una matrice di TNavButton, un discendente di TSpeedButton. 

Poiché ogni pulsante in questa proprietà protetta eredita da TSpeedButton, se ci metti le mani sopra, sarai in grado di lavorare con proprietà TSpeedButton “standard” come: Caption (una stringa che identifica il controllo all’utente), Glyph (il bitmap che appare sul pulsante), Layout (determina dove appare l’immagine o il testo sul pulsante) …

Dall’unità DBCtrls (dove è definito DBNavigator) si “legge” che la proprietà Buttons protetta è dichiarata come:

Pulsanti: schieramento[TNavigateBtn] of TNavButton;

Dove TNavButton eredita da TSpeedButton e TNavigateBtn è un’enumerazione, definita come:

TNavigateBtn = 
(nbFirst, nbPrior, nbNext, nbLast, nbInsert,
nbDelete, nbEdit, nbPost, nbCancel, nbRefresh);

Si noti che TNavigateBtn contiene 10 valori, ognuno dei quali identifica un pulsante diverso su un oggetto TDBNavigator. Ora vediamo come hackerare un DBNavigator:

DBNavigator migliorato

Innanzitutto, imposta un semplice modulo Delphi per la modifica dei dati posizionando almeno un DBNavigator, un DBGrid, un DataSoure e un oggetto Dataset di tua scelta (ADO, BDE, dbExpres, …). Assicurati che tutti i componenti siano “collegati”.

In secondo luogo, hackera un DBNavigator definendo una classe “fittizia” ereditata, sopra la dichiarazione Form, come:

Digitare THackDBNavigator = classe(TDBNavigator);

Digitare
TForm1 = classe(TForm)
...

Successivamente, per poter visualizzare didascalie e grafici personalizzati su ogni pulsante DBNavigator, dovrai impostare alcuni glifi. È possibile utilizzare il componente TImageList e assegnare 10 immagini (.bmp o .ico), ciascuna rappresentante un’azione di un particolare pulsante di un DBNavigator.

Terzo, nell’evento OnCreate per Form1, aggiungi una chiamata come:

procedura TForm1.FormCreate (Sender: TObject);
SetupHackedNavigator (DBNavigator1, ImageList1);
fine;

Assicurati di aggiungere la dichiarazione di questa procedura nella parte privata della dichiarazione del modulo, come:

Digitare
TForm1 = classe(TForm)
...
procedura privata SetupHackedNavigator (const Navigatore: TDBNavigator;
const Glifi: TImageList);
...

Quarto, aggiungi la procedura SetupHackedNavigator. La procedura SetupHackedNavigator aggiunge grafica personalizzata a ciascun pulsante e assegna una didascalia personalizzata a ciascun pulsante.

usa Pulsanti; // !!! non dimenticare
procedura TForm1.SetupHackedNavigator
(const Navigatore: TDBNavigator;
const Glifi: TImageList);
const
Didascalie: schieramento[TNavigateBtn] di stringa =
("Iniziale", "Precedente", "Più tardi", "Finale", "Aggiungi",
"Cancella", "Correggi", "Invia", "Ritira", "Rianima");
(*
Didascalie: array [TNavigateBtn] di string =
("Primo", "Precedente", "Successivo", "Ultimo", "Inserisci",
"Elimina", "Modifica", "Pubblica", "Annulla", "Aggiorna");

in Croazia (localizzato):
Didascalie: array [TNavigateBtn] di string =
("Primo", "Precedente", "Successivo", "Ultimo", "Aggiungi",
"Elimina", "Modifica", "Salva", "Annulla", "Aggiorna");
*)
var
btn: TNavigateBtn;
beginfor btn: = Basso (TNavigateBtn) a Alto (TNavigateBtn) fare con THackDBNavigator (Navigator) .Buttons [btn] dobegin// dall'array const Captions
Caption: = Captions [btn];
// il numero di immagini nella proprietà Glyph
NumGlyphs: = 1;
// Rimuove il vecchio glifo.
Glifo: = zero;
// Assegna quello personalizzato
Glyphs.GetBitmap (Integer (btn), Glyph);
// gylph sopra il testo
Layout: = blGlyphTop;
// spiegato in seguito
OnMouseUp: = HackNavMouseUp;
fine;
fine; (* SetupHackedNavigator *)

Ok, spieghiamo. Si itera attraverso tutti i pulsanti nel DBNavigator. Ricorda che ogni pulsante è accessibile dalla proprietà dell’array Buttons protetta, quindi la necessità della classe THackDBNavigator. Poiché il tipo di array Buttons è TNavigateBtn, si passa dal pulsante “primo” (utilizzando la funzione Low) a quello “last” (utilizzando la funzione High). Per ogni pulsante, rimuovi semplicemente il glifo “vecchio”, assegna quello nuovo (dal parametro Glyphs), aggiungi la didascalia dall’array Captions e contrassegna il layout del glifo.

Notare che è possibile controllare quali pulsanti vengono visualizzati da un DBNavigator (non da quello violato) tramite la sua proprietà VisibleButtons. Un’altra proprietà di cui potresti voler modificare il valore predefinito è Suggerimenti: usala per fornire suggerimenti di guida a tua scelta per il singolo pulsante del navigatore. È possibile controllare la visualizzazione dei suggerimenti modificando la proprietà ShowHints.

Questo è tutto. Ecco perché hai scelto Delphi!

Dammi di più!

Perché fermarsi qui? Sai che quando fai clic sul pulsante “nbNext” la posizione corrente del set di dati viene avanzata al record successivo. Cosa succede se si desidera spostare, diciamo, 5 record in avanti se l’utente tiene premuto il tasto CTRL mentre preme il pulsante? Che ne dici di quello? 

Il DBNavigator “standard” non dispone dell’evento OnMouseUp, quello che contiene il parametro Shift di TShiftState, che consente di verificare lo stato dei tasti Alt, Ctrl e Shift. DBNavigator fornisce solo l’evento OnClick da gestire. 

Tuttavia, il THackDBNavigator può semplicemente esporre l’evento OnMouseUp e consentirti di “vedere” lo stato dei tasti di controllo e persino la posizione del cursore sopra il pulsante specifico quando viene cliccato!

Ctrl + clic: = 5 righe in anticipo

Per esporre OnMouseUp è sufficiente assegnare la procedura di gestione degli eventi personalizzata all’evento OnMouseUp per il pulsante del DBNavigator hackerato. Questo è esattamente già fatto nella procedura SetupHackedNavigator:
OnMouseUp: = HackNavMouseUp;

Ora, la procedura HackNavMouseUp potrebbe essere simile a:

procedura TForm1.HackNavMouseUp
(Mittente: TObject; Pulsante: TMouseButton;
Shift: TShiftState; X, Y: intero);
const MoveBy: intero = 5;
beginif NON (Il mittente è TNavButton) poi Exit;
Custodie TNavButton (Sender) .Index of
nbPrior;
if (ssCtrl in Shift) poi
TDBNavigator (TNavButton (Sender) .Parent).
DataSource.DataSet.MoveBy (-MoveBy);
nbNext:
if (ssCtrl in Shift) poi
TDBNavigator (TNavButton (Sender) .Parent).
DataSource.DataSet.MoveBy (MoveBy);
fine;
fine; (* HackNavMouseUp *)

Si noti che è necessario aggiungere la firma della procedura HackNavMouseUp all’interno della parte privata della dichiarazione del modulo (vicino alla dichiarazione della procedura SetupHackedNavigator):

Digitare
TForm1 = classe(TForm)
...
procedura privata SetupHackedNavigator (const Navigatore: TDBNavigator;
const Glifi: TImageList);
procedura HackNavMouseUp (Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: intero);
...

Ok, spieghiamo, ancora una volta. La procedura HackNavMouseUp gestisce l’evento OnMouseUp per ogni pulsante DBNavigator. Se l’utente tiene premuto il tasto CTRL mentre fa clic sul pulsante nbNext, il record corrente per il dataset collegato viene spostato “MoveBy” (definito come costante con il valore di 5) record avanti.

Che cosa? Troppo complicato?

Sì. Non è necessario fare confusione con tutto questo se è necessario controllare solo lo stato dei tasti di controllo quando si fa clic sul pulsante. Ecco come fare lo stesso nell’evento OnClick “ordinario” del DBNavigator “ordinario”:

procedura TForm1.DBNavigator1Click
(Mittente: TObject; Button: TNavigateBtn);
function CtrlDown: Boolean;
var
State: TKeyboardState;
iniziare
GetKeyboardState (stato);
Risultato: = ((State [vk_Control] And 128) 0);
fine;
const MoveBy: intero = 5;
caso iniziale Pulsante of
nbPrior;
if CtrlDown poi
DBNavigator1.DataSource.DataSet.MoveBy (-MoveBy);
nbNext:
if CtrlDown poi
DBNavigator1.DataSource.DataSet.MoveBy (MoveBy);
fine; //Astuccio
fine; (* DBNavigator2Click *)

È tutto gente

E finalmente il progetto è fatto. Oppure puoi andare avanti. Ecco uno scenario / compito / idea per te: 

Supponiamo che tu voglia un solo pulsante per sostituire i pulsanti nbFirst, nbPrevious, nbNext e nbLast. È possibile utilizzare i parametri X e Y all’interno della procedura HackNavMouseUp per trovare la posizione del cursore quando il pulsante è stato rilasciato. Ora, a questo pulsante (“per regolarli tutti”) puoi allegare un’immagine che ha 4 aree, ciascuna area dovrebbe imitare uno dei pulsanti che stai sostituendo … capito?