Tips&Tricks I trucchi del mestiere

 

Bypassare la console di Windows


Questo semplice tip illustra come attraverso l'istruzione "pragma comment" sia possibile bypassare" la console di Windows.
Tip fornito dal sig. E. Di Santo

//---Console "bypass" û E. Di Santo ---//
//Queste istruzioni sono necessarie
//per poter utilizzare la funzione "PlaySound"
#include 
#pragma comment(lib,"winmm.lib")

//Questa Φ l'istruzione vera e propria
//che permette di "bypassare" la console
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )  

void main()
{
	PlaySound("SystemStart",NULL, SND_ALIAS|SND_SYNC);
	return;
}



Creazione di componenti a run-time


Il tip consente di creare componenti a run-time.
Tip fornito dal sig. L.Nalli

La prima operazione da compiere consiste nella preparazione della windows: si inseriscono due panel, uno per ospitare la toolbar con i componenti da inserire, l'altro sul quale posare i componenti scelti. A questo punto si aggiungano tre pulsanti alla toolbar, il primo per indicare che nessun componente Φ stato selezionato, il secondo per inserire un TButton, l'ultimo per inserire un TEdit. I tre toolbutton devono avere le proprietα AllowAllUp e Grouped settate a true, il tutto per ottenere un effetto simile a quello dell'IDE di Delphi. Si setti per ogni bottone della barra un tag differente partendo da uno. Il primo pulsante avrα tag uguale a uno, il secondo uguale a due e cos∞ via. Si dichiari la variabile Selected di tipo intero e si inserisca nell'evento Click del primo pulsante la riga seguente:

Selected:=TToolButton(Sender).Tag;

Una volta associato l'evento ad ogni pulsante della toolbar, cliccando su un tasto, la variabile Selected assumerα il valore del tag del pulsante premuto. Si dichiari la variabile ControlRef di tipo TControlClass. Nell'evento MouseDown del panel che ospiterα i controlli selezionati scriviamo:

case Selected of
  2:
    ControlRef:=TButton;
  3:
    ControlRef:=TEdit;
end;

Mediante questo codice, a seconda del valore assunto da Selected, la variabile ControlRef assumerα un valore differente, il quale coincide con il ClassType del componente che si vuole inserire.
Prima di proseguire si dichiarino due variabili, Counter e ControlName, rispettivamente di tipo intero e di tipo stringa.
Si aggiunga il codice seguente all'evento MouseDown:


if Selected > 1 then
  with ControlRef.Create(Self) do
    begin
      Inc(Counter);
      Visible:=false;
      Parent:=Self;
      ControlName:=ControlRef.ClassName;
      Delete(ControlName,1,1);
      Name:=ControlName + IntToStr(Counter);
      Left:=X;
      Top:=Y;
      Visible:=true;
      tbNone.Down:=true;  //tbNone = name del primo toolbutton
      tbNoneClick(tbNone);
    end;

Tramite l'utilizzo della Class Reference, si pu≥ notare come si possa aggiungere qualsiasi controllo usufruendo dello stesso codice.



Compilare le classi ôal voloö


Il tip proposto riguarda la compilazione a run-time, di classi java in modo veloce ed efficiente usando una classe delle librerie del java2 sdk in alternativa al metodo, pi∙ intuitivo ma meno elegante, che prevede la creazione di un processo separato e l' invocazione mediante la exec del compilatore javac.
UnÆapplicazione pu≥, quindi, creare i propri file java e ottenerne una compilazione per poi caricane le classi appena create tramite la Reflection; ci≥ garantisce la disponibilitα di classi da essa stessa create. La libreria da includere Φ la \lib\tools.jar presente nella directory del Java 2 SDK.
Tip fornito dal sig. M.Pace

import java.io.*;
import java.util.*;

public class Compilertip {
  public static void main(String args[]) throws IOException  {
       if(args.length==0){      
          System.out.println("Linea di comando: java Compilertip file1 file2 ecc");    
       }else{
          Compile(args);
       }            
   }

 /*Compila i file i cui nomi sono nel vettore fornito come parametro*/
   static public boolean Compile(String[] filenames){
        try{
           int filecompilati = 0;       
           
           for(int i=0;i<filenames.length;i++){
              String fname = filenames[i]; 
              String sourceFile =  this.currentpath+""+fname[i]+".java";
              int compileReturnCode = com.sun.tools.javac.Main.compile(new String[] 
{sourceFile});
              if (compileReturnCode == 0) {
                System.out.println("File "+ filenames[i] + " compilato con successo.");
                filecompilati++;
              }else{
                System.out.println("Errore nella compilazione di "+  filenames[i] + ". Termino.");
                return false;         
              }
            }//for
       
             if(filecompilati == filenames.length){
               System.out.println("Tutti i file ("+filecompilati+") compilati con successo.");
               return true;
             }     
             catch(Exception e){
             /*... gestione dell' errore...*/   
             }    
             
             return false;
   }    
   }                                  
/*
      javac -classpath  c:\j2sdk1.4.2\lib\tools.jar Compilertip.java
      java  -classpath  c:\j2sdk1.4.2\lib\tools.jar Compilertip.java
*/



Input bufferizzato


Un tip Java che risolve un problema spesso riscontrato, quello della gestione dell'input da tastiera non bufferizzato e con echo disabilitato (utile anche per l'inserimento di password).
A questo scopo faremo uso dei JNI (Java Native Interface) di Java, che offre al programmatore la possibilitα di far interagire codice C/C++ con il codice Java in maniera relativamente semplice.
Tip fornito dal sig. C. Sicilia

package it.kya.io;
import java.io.IOException;
public class KeyBoard
{
	static
	{
		System.loadLibrary("KeyBoard");
	}
	public static native int read() throws IOException;
}

La classe KeyBoard fornisce lÆinterfaccia necessaria al nostro scopo, dichiarando il metodo read.
Il secondo passo Φ quello di compilare la classe con il semplice comando:


javac KeyBoard.java

La compilazione creerα la classe KeyBoard.class nel package it.kya.io.
Il terzo passo Φ quello di creare lÆheader per le funzioni C da implementare, a questo scopo useremo il tool javah, presente nella cartella bin del jdk:


javah ûjni ûo KeyBoard.h it.kya.io.KeyBoard

Questa procedura genererα il file KeyBoard.h del tutto simile a quanto proposto:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class it_kya_io_KeyBoard */

#ifndef _Included_it_kya_io_KeyBoard
#define _Included_it_kya_io_KeyBoard
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     it_kya_io_KeyBoard
 * Method:    read
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_it_kya_io_KeyBoard_read
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

A questo punto non ci rimane che implementare le funzioni in codice C, il prossimo passo sarα, quindi, quello di creare un file KeyBoard.c contenente le funzioni dichiarate nellÆheader.
Bisogna dire che una funzione scritta in C non Φ portabile e richiede quindi che venga ricompilata sui diversi sistemi operativi e visto che la portabilitα Φ un punto di forza di Java bisognerα, quantomeno, fornire una libreria per Windows e una per Linux.
Essendo LÆI/O generalmente legato al sistema operativo, in particolare la lettura dalla tastiera, avremo bisogno di librerie diverse per i due sistemi. Per Windows useremo conio.h, per Linux curses.h, utilizzeremo le macro per gestire una compilazione sul medesimo file, quindi nel file KeyBoard.c scriveremo:

#if defined _WIN32
#	include 
#elif defined __linux__
#	include 
#else
#	error Operating system is undefined or unknown!
#endif

#include 
#include "KeyBoard.h"

JNIEXPORT jint JNICALL Java_it_kya_io_KeyBoard_read
	(JNIEnv *env, jobject obj)
{
	jint ch;
#if defined _WIN32
	ch = _getch();
#elif defined __linux__
	initscr();
	cbreak();
	noecho();
	ch = getchar();
	echo();
    endwin();
	if(ch == ERR)
	{
		jclass newExc = (*env)->FindClass(env, "IOException");
		if (newExc != NULL)
		{
			(*env)->ThrowNew(env, newExc, "I/O Input error");
		}
		(*env)->DeleteLocalRef(env, newExc);
	}
#endif
	return ch;
}



La convalida della partita IVA


Programmando in ambito web ( JSP ecc.), ci si trova spesso a dover controllare la correttezza di alcuni campi, inseriti dall'utente.
Ci≥, spesso, porta alla perdita di non poco tempo, per lo sviluppo di funzioni di controllo specializzate per il campo. In genere i pi∙ laboriosi sono il codice fiscale (di cui una soluzione Φ giα stata pubblicata) e la Partita Iva.
La funzione qui riportata esegue un controllo su una stringa contenete una Partita Iva e restituisce valore true se essa Φ valida, false altrimenti.
Tip fornito dal sig. G. Sanfilippo

boolean checkValidPartitaIva(String PartitaIva)
{ int Somma01 = 0; int Somma02 = 0; int CheckNumber;
  if (PartitaIva.length() != 11) return false;
  try 
  { if(Float.parseFloat(PartitaIva) < Float.parseFloat("0")) return false;
  }  catch (NumberFormatException NFE) {NFE.printStackTrace(); return false;}
  for (int i = 0; i < 9; i += 2) 
  { CheckNumber = Integer.parseInt(""+PartitaIva.charAt(i));  
    Somma01 += CheckNumber;  
    CheckNumber = Integer.parseInt(""+PartitaIva.charAt(i+1));  
    Somma01 += Math.floor(CheckNumber/5) + (CheckNumber << 1) % 10; 
  }
  Somma02 = 10 - (Somma01 % 10);
  CheckNumber = Integer.parseInt(""+PartitaIva.charAt(10));
  if (Somma02 != CheckNumber) return false; else return true;
}



Gli utenti cambiano la dimensione dei controlli


Grazie a due semplice chiamate ad API, Φ possibile mettere gli utenti in grado di ridimensionare i controlli presenti nelle applicazioni che realizziamo, in modo del tutto simile a quanto si fa nel Design Mode di Visual Basic 6: cliccando su un bordo, o su uno spigolo, e trascinandolo per ridefinire i contorni del controllo.
Il codice suppone che nella form principale sia presente una picture box (Picture1) e gestisce il caso del ridimensionamento orizzontale, ma Φ facilmente estensibile a tutti gli altri casi.
Tip fornito dal sig.R.Fabozzi

Private Declare Function ReleaseCapture Lib _
	"user32" () As Long
Private Declare Function SendMessage Lib _
	"user32" Alias "SendMessageA" (ByVal hWnd _
	As Long, ByVal wMsg As Long, ByVal wParam _
	As Long, lParam As Any) As Long
Private Const WM_NCLBUTTONDOWN = &HA1

Private Const HTLEFT = 10
Private Const HTRIGHT = 11
Private Sub Picture1_MouseDown(Button As _
	Integer, Shift As Integer, X As Single, Y As Single)
	Dim nParam As Long
	With Picture1
		' You can change these coordinates to whatever 
		' you want
		If (X > 0 And X < 100) Then
			nParam = HTLEFT
		ElseIf (X > .Width - 100 And X < .Width) Then 
		' these too
			nParam = HTRIGHT
		End If
		If nParam Then
			Call ReleaseCapture
			Call SendMessage(.hWnd, _
				WM_NCLBUTTONDOWN, nParam, 0)
		End If
	End With
End Sub
Private Sub Picture1_MouseMove(Button As _
	Integer, Shift As Integer, X As Single, Y As Single)
	Dim NewPointer As MousePointerConstants
	' You can change these coordinates to whatever you want
	If (X > 0 And X < 100) Then
		NewPointer = vbSizeWE
	ElseIf (X > Picture1.Width - 100 And X < _
		Picture1.Width) Then ' these too
		NewPointer = vbSizeWE
	Else
		NewPointer = vbDefault
	End If
	If NewPointer <> Picture1.MousePointer Then
		Picture1.MousePointer = NewPointer
	End If
End Sub



Leggere e scrivere in un file .INI


Il tip, inserito in un modulo BAS (o CLS), permette di leggere e scrivere informazioni nei file .INI, il tutto senza utilizzare complicate procedure di ricerca all'interno di un file, ma utilizzando le API di Windows.
Tip fornito dal sig. S.Tomaselli

Declare Function WritePrivateProfileString Lib "Kernel32" Alias "WritePrivateProfileStringA" 
ByVal lpApplicationname As String, ByVal lpKeyName As Any, ByVal lsString As Any, ByVal lplFilename As String) As Long

Declare Function GetPrivateProfileInt Lib "Kernel32" Alias "GetPriviteProfileIntA" (ByVal 
lpApplicationname As String, ByVal lpKeyName As String, ByVal nDefault As Long, ByVal lpFileName As String) As Long

Declare Function GetPrivateProfileString Lib "Kernel32" Alias "GetPrivateProfileStringA" (ByVal 
lpApplicationname As String, ByVal lpKeyName As String, ByVal lpDefault As String, 
ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As 
Long

Global File
Global appname
Global Keyname
Global Value

Public Function Store(File As String, Heading As String, Section As String, Value As String)
Dim lpAppName As String, lpFileName As String, lpKeyName As String, lpString As 
String
Dim U As Long
lpAppName = Heading
lpKeyName = Section
lpString = Value
lpFileName = File
U = WritePrivateProfileString(lpAppName, lpKeyName, lpString, lpFileName)
If U = 0 Then
Beep
Else
Store = "Success"
End If
End Function

Public Function GetValue(File As String, Heading As String, Section As String)
Dim x As Long
Dim Temp As String * 50
Dim lpAppName As String, lpKeyName As String, lpDefault As String, lpFileName As String
Temp = Space$(50)
lpAppName = Heading
lpKeyName = Section
lpDefault = no
lpFileName = File

x = GetPrivateProfileString(lpAppName, lpKeyName, lpDefault, Temp, Len(Temp), lpFileName)

If x = 0 Then
Beep
Else
en = InStr(1, Temp, Chr$(0))
If en > 0 Then Temp = Mid$(Temp, 1, en - 1)
GetValue = Trim$(Temp)
End If
End Function 



Un controllo ListView in modalitα ôreportö


Sovente capita di realizzare delle applicazioni in cui Φ necessario utilizzare un cotrollo ListView, in modalitα Report, per la visualizzazione dei dati. Purtroppo non Φ possibile editare gli stessi come la stessa semplicitα di un DataGrid.
Il tip proposto consente di "eliminare" questo problema visualizzando un controllo ComboBox all'interno di una colonna di una riga selezionata, quando si fa click sul controllo ListView, dando la possibilitα di cambiare il valore di un item, scegliendo tra una delle voci proposte dal ComboBox visualizzato.
Con la stessa tecnica Φ possibile aggiungere altri controlli standard come ProgressBar, Command Buttons, ecc.
Trovate lÆapplicazione completa allegata al cd-rom che accompagna la rivista o nella sezione download del sito www.ioprogrammo.it
Tip fornito dal sig. P.Libro


Un risolutore dÆespressioni matematiche


Il codice riportato Φ un risolutore dÆespressioni matematiche numeriche (non letterali e non equazioni). Rispetta le prioritα delle operazioni (prima potenze e radici, poi moltiplicazioni e divisioni ed in ultimo addizioni e sottrazioni).
E' possibile utilizzare vari livelli di parentesi ma solo parentesi tonde. Supporta le funzioni matematiche standard di Visual Basic. E' progettato per poter funzionare con il separatore decimale ma anche con la virgola.
La funzione "Simple" risolve le espressioni senza parentesi. La funzione principale "Solve" estrae il contenuto delle parentesi e lo fa risolvere alla funzione "Simple".
Impostando "ShowPassages" su "True" saranno restituiti i passaggi compiuti dalla funzione per risolvere l'espressione.
Trovate le funzioni, definite in modulo .BAS, allegato al cd-rom che accompagna la rivista o nella sezione download del sito www.ioprogrammo.it
Tip fornito dal sig. S. Tomaselli