Tips&Tricks I trucchi del mestiere

 




Come utilizzare l'aritmetica

In questo tip analizziamo i principali casi di utilizzo delle espressioni aritmetiche in Java. Un piccolo ripasso sulle dichiarazioni e sul modo di utilizzare le variabili all'interno di espressioni matematiche.
public class SimpleArithmetic
{
  public static void main(String[] args)
  {
    int withdraw  = 300;
    int deposit   = 400;

    // dichiarare e inizializzare le variabili
    int balance   = deposit - withdraw;

    // incrementare un valore
    balance =     balance + 100;
    balance +=    100;

    // utilizzare valori booleani
    boolean isGood = false;
    isGood = !isGood; // isGood ora Φ vero

    // tutti gli opeartori hanno la semantica =
    // di seguito trovate un paio di esempi 
    int value = 100 * 10;
    value /= 5;
    value *= 2;

    // ed ecco una classica espressione aritmetica
    int yourValue = ( (value+balance) / (withdraw * deposit) );
  }
}


Come realizzare metodi ricorsivi

Un piccolo esempio che illustra come utilizzare la ricorsione per ottenere tutte le diverse combinazioni di un dato insieme di lettere. Pur non trovando una immediata utilitα pratica, pu≥ essere un buono spunto per chi comincia ad occuparsi di ricorsione in Java, da notare l'utilizzo della variabile statica sum.
public class LetterCombinations {

 private static String sum = "";

 public static void main(String[] argv) {
    long l = System.currentTimeMillis();
    printAlphabetCombinations(4,"");
    System.out.println("Time:"+ (System.currentTimeMillis() - l)/1000 + " sec");
 }

 public static void printAlphabetCombinations(int recurseCounter,String current) {
    String temp = current;
    if (recurseCounter==0) {
       System.out.println(temp);
       return;
    }
    else {
       recurseCounter--;
       for (int i=0; i<26;i++) {
         temp = current+(char)(65+i);
         printAlphabetCombinations(recurseCounter,temp);
       }
    }
 }
}


RomanNumeral

Una semplice ma completa implementazione di una classe per la gestione dei numeri romani. Grazie a questo codice sarα possibile effettuare la conversione da e verso i numeri scritti secondo la numerazione romana. Un'idea simpatica ed un'ottima realizzazione.
public class RomanNumeral extends Number implements Comparable	 {

	private static final char[] charList = { 'M', 'D', 'C', 'L', 'X', 'V', 'I' };
	private static final int[] valList = { 1000, 500, 100, 50, 10, 5, 1 };

	private String strVal;
	private int intVal;




	/**
	* Class constructor specifying initial int value.
	* @param value the initial value
	*/
	public RomanNumeral(int value) {
		intVal = value;
		strVal = compose(value);
	}

	/**
	* Class constructor specifying initial Number value.
	* @param value the initial value
	*/
	public RomanNumeral(Number value) {
		intVal = value.intValue();
		strVal = compose(intVal);
	}

	/**
	* Class constructor specifying initial String value.
	* @param value the initial value
	*/
	public RomanNumeral(String value) {
		strVal = value;
		intVal = eval(value);
	}




	// --- filling in abstracts from Number

	/**
	* returns current value in byte form.
	* @return current value in byte form.
	*/
	public byte byteValue() {
		return (byte) this.intVal;
	}

	/**
	* returns current value in double form.
	* @return current value in double form.
	*/
	public double doubleValue() {
		return (double) this.intVal;
	}

	/**
	* returns current value in float form.
	* @return current value in float form.
	*/
	public float floatValue() {
		return (float) this.intVal;
	}

	/**
	* returns current value in int form.
	* @return current value in int form.
	*/
	public int intValue() {
		return this.intVal;
	}

	/**
	* returns current value in long form.
	* @return current value in long form.
	*/
	public long longValue() {
		return (long) this.intVal;
	}

	/**
	* returns current value in short form.
	* @return current value in short form.
	*/
	public short shortValue() {
		return (short) this.intVal;
	}




	// --- filling in abstract from Comparable

	/**
	* returns a value based on the comprative location in a list of
	* this instance versus the passed Object.
	*
	* @param obj Object to compare against
	* @return a possitive value if instance is greater-than passed Object,
	*	a negative value if less-than, and zero if the same
	*/
	public int compareTo(Object obj) {
		if(obj == null) return 1;
		// we are larger than null

		Number n = (Number) obj;
		int i = n.intValue();
		if(i == intVal)	
			return 0;	// the same
		else if(i < intVal)
			return 1;	// we are more than they
		else
			return -1;	// they are more than we
	}




	// --- over-riding Object

	/**
	* Compares for equality
	* @param obj Object to compare equality with
	* @return boolean indicating equality
	*/
	public boolean equals(Object obj) {
		return (new Integer(intVal)).equals(obj);
	}

	/**
	* returns current value in String form formatted as a roman numeral.
	* @return current value in String form formatted as a roman numeral.
	*/
	public String toString() {
		return this.strVal;
	}




	// --- some simple math

	/**
	* Adds a Number to the current value.
	* @param addMe Number to add to current value
	*/
	public void more(Number addMe) {
		if(addMe == null) throw new NumberFormatException("NULL cannot be converted to a RomanNumeral");
		more(addMe.intValue());
	}

	/**
	* Adds an int to the current value.
	* @param addMe int to add to current value
	*/
	public void more(int addMe) {
		intVal += addMe;
		strVal = compose(intVal);
	}

	/**
	* Subtracts a Number from the current value.
	* @param subMe Number to subtract from current value
	*/
	public void less(Number subMe) {
		if(subMe == null) throw new NumberFormatException("NULL cannot be converted to a RomanNumeral");
		less(subMe.intValue());
	}

	/**
	* Subtracts an int from the current value.
	* @param subMe int to subtract from current value
	*/
	public void less(int subMe) {
		intVal -= subMe;
		strVal = compose(intVal);
	}

	/**
	* Multiplies current value by a Number.
	* @param times Number by which to multiply current value
	*/
	public void by(Number times) {
		if(times == null) throw new NumberFormatException("NULL cannot be converted to a RomanNumeral");
		by(times.intValue());
	}

	/**
	* Multiplies current value by an int.
	* @param times int by which to multiply current value
	*/
	public void by(int times) {
		intVal = intVal * times;
		strVal = compose(intVal);
	}




	// --- important for formulation

	/**
	* Composes a String, roman numeral representation of a Number
	* @param val Number from which to compose a String roman numeral
	* @return String, roman numeral representation of the passed Number
	* @exception NumberFormatException If value is out of range, a NumberFormatException is thrown
	*/
	public static String compose(Number val) throws NumberFormatException {
		return compose(val.intValue());
	}

	/**
	* Composes a String, roman numeral representation of an int
	* @param val int from which to compose a String roman numeral
	* @return String, roman numeral representation of the passed int
	* @exception NumberFormatException If value is out of range, a NumberFormatException is thrown
	*/
	public static String compose(int val) throws NumberFormatException {

		if(val < 1) throw new NumberFormatException("Value out of bounds for excodession as a Roman Numeral");

		String allVal = "";

		while(val > 0) {
			for(int I = 0; I < valList.length; I++) {
				int J = I + 2 - (I%2);
				if( val >= valList[I] ) {
					val -= valList[I];
					allVal += ("" + charList[I]);
					break;
				}
				else if( (J < valList.length) && (val >= (valList[I] - valList[J]))) {
					val -= (valList[I] - valList[J]);
					allVal += ("" + charList[J] + charList[I]);
					break;
				}
			}
		}

		return allVal;
	}

	/**
	* Evaluates a String, roman numeral excodession into an int
	* @param roman String to evaluate as a roman numeral
	* @return int value of the passed excodession
	* @exception NumberFormatException If excodession is a mal-formed roman numeral, a NumberFormatException is thrown
	*/
	public static int eval(String roman) throws NumberFormatException {

		int allVal = 0;

		byte[] b = roman.toUpperCase().getBytes();

		for(int I = 0; I < b.length; I++) {
			int val_a = valOf((char) b[I]);
			if(I < b.length - 1) {
				int val_b = valOf((char) b[I+1]);
				if(val_b > val_a) {
					allVal += (val_b - val_a);
					I++;
				}
				else {
					allVal += val_a;
				}
			}
			else {
				allVal += val_a;
			}
		}

		return allVal;
	}




	private static int valOf(char c) throws NumberFormatException {

			for(int I = 0; I < RomanNumeral.valList.length; I++) {
				if(RomanNumeral.charList[I] == c) return RomanNumeral.valList[I];
			}

			throw new NumberFormatException("Unrecognized RomanNumeral Value: '" + c + "'");
	}


	// --- for use as a stand-alone program

	public static void main(String[] args) {
		if(args.length < 1) {
			//print out the quick 'how-to'
			System.out.println("use: RomanNumeral < n >\n Prints translation of n; if n is a number,
			prints the roman numeral equiv.\n If n is a roman numeral, prints an arabic number");
		}
		else {
			try {
				//first attempt to compose it from an int
				System.out.println("" + RomanNumeral.compose(Integer.parseInt(args[0])));
			}
			catch(Exception e) {
				try {
					//try to compose it from a String
					System.out.println("" + RomanNumeral.eval(args[0]));
				}
				catch(Exception f) {
					//print the Exception, exit
					System.err.println(f);
					System.exit(1);
				}
			}
		}
		System.exit(0); //it's good practice
	}

}

        

 



Come generare le eccezioni

Questo tip dimostra come far si che un metodo lanci una eccezione e come utilizzare correttamente la clausola throw.
public class PieEater
{
  private int piesEaten;

  // la clausola throw indica che il metodo pu≥ lanciare una eccezione PieException
  public int howManyPies() throws PieException
  {
    // do some processing
    if( piesEaten > 100 )
    {
      // crea una eccezione PieException e la lancia
      throw new PieException( "non ha mangiato tutte le torte!" );
    }

    return piesEaten;
  }
}




Come generare numeri casuali secondo la distribuzione di Poisson

Sruttando la classe java.util.Random, il codice che presentiamo implementa un algoritmo per la generazione di numeri casuali che rispettino la distribuzione di Poisson. Estremamente utile sia in ambito ingegneristico che in ambito statistico: la classe pu≥ essere facilmente personalizzata per usi pi∙ verticali.
import java.util.Random;


public class RandomPoissonDistribution
{
  private Random rand;
  private long mean;

  public RandomPoissonDistribution(long mean)
  {
    this.mean = mean;
    rand = new Random();
  }

  /**
   * Return a random number with Poisson distribution.
   */
  public long nextLong()
  {
    // See Knuth, TAOCP, vol. 2, second print
    // section 3.4.1, algorithm Q on page 117
    // Q1. [Calculate exponential]
    double p = Math.exp(-(double)mean);
    long N = 0;
    double q = 1.0;

    while (true)
      {
	// Q2. [Get uniform variable]
	double U = rand.nextDouble();
	// Q3. [Multiply]
	q = q * U;
	// Q4. [Test]
	if (q >= p)
	  N = N + 1;
	else
	  return N;
      }
  }

  public static void main(String[] args)
  {
    RandomPoissonDistribution poisson 
      = new RandomPoissonDistribution(10);

    for (int i = 0; i <= 10; i++)
      System.out.println(poisson.nextLong());
  }
}

 



Come realizzare conversioni di base

Con il codice che qui presentiamo Φ possibile convertire numeri in base dieci verso qualsiasi altra base. Oltre ad essere molto utile, consente di familiarizzare con l'utilizzo della matematica in C++
#include 
#include 

int main() {
  const char digits[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  unsigned long int num, initial;
  unsigned int base, place, converted[32];
  cout << "Enter decimal value and the base to convert it to: ";
  cin >> num >> base;
  initial = num;
  place = int( log(num) / log(base) );
  const unsigned int start = place;
  while (place != 0) {
    converted[place] = int(initial/pow(base, place));
    initial %= int(pow(base, place--));
  }
  converted[place] = initial;
  if (base > sizeof(digits))
    for(place = start; place != -1; place--)
      cout << converted[place] << " "; 
  else
    for(place = start; place != -1; place--)
      cout << digits[converted[place]];
  cout << endl;
  return 0;
}


Come salvare e recuperare le impostazioni degli utenti

Una calsse che si occupa di gestire le impostazioni definite dagli utenti, attraverso la creazione di un file in cui sono immagazzinate un insieme di chiavi e valori su cui Φ possibile effettuare ricerche e modifiche in un secondo momento. Per immagazzinare e poi leggere i valori sono disponibili i due metodi writeValueToFile e readValueFromFile
#include 

class aflibEnvFile {

public:

   aflibEnvFile(
      char * env_file,
      char * env_dir = NULL);

   aflibEnvFile();

   ~aflibEnvFile();

   bool readValueFromFile(const string key_str,string& results);
   bool readValueFromFile(const string key_str,int& result);
   bool readValueFromFile(const string key_str,unsigned int& result);
   bool readValueFromFile(const string key_str,long int& result);
   bool readValueFromFile(const string key_str,unsigned long& result);
   bool readValueFromFile(const string key_str,bool& result);

   void writeValueToFile(const string key_str,const string value);
   void writeValueToFile(const string key_str,const int value);
   void writeValueToFile(const string key_str,const unsigned int result);
   void writeValueToFile(const string key_str,const long int result);
   void writeValueToFile(const string key_str,const unsigned long result);
   void writeValueToFile(const string key_str,const bool value);

   void deleteFile(void);
private:

string _env_file;

};


#endif
----HEADER END
----SOURCE
#include 
#include 
#include 
#include 

#include "aflibEnvFile.h"

#define DEFAULT_DIR ".aflib"
#define DEFAULT_FILE "aflibenv"
#define MAX_LINE_SIZE  2048

aflibEnvFile::aflibEnvFile(
   char * env_file,
   char * env_dir)
{
   char * home_dir;

   // Store the correct environment directory
   if (env_dir == NULL)
   {
      if (getenv("HOME"))
      {
         home_dir = getenv("HOME");
         _env_file.append(home_dir);
         _env_file.append("/");
      }
      else
      {
         cerr << "Environment var HOME not set!" << endl;
      }

      _env_file.append(DEFAULT_DIR);
   }
   else
   {
      _env_file.append(env_dir);
   }

   _env_file.append("/");

   // Store the correct environment file
   if (env_file == NULL)
   {
      _env_file.append(DEFAULT_FILE);
   }
   else
   {
      _env_file.append(env_file);
   }
}
aflibEnvFile::aflibEnvFile()
{
   char * home_dir;

   if (getenv("HOME"))
   {
      home_dir = getenv("HOME");
      _env_file.append(home_dir);
      _env_file.append("/");
   }
   else
   {
      cerr << "Environment var HOME not set!" << endl;
   }

   _env_file.append(DEFAULT_DIR);
   _env_file.append("/");

   _env_file.append(DEFAULT_FILE);
}

aflibEnvFile::~aflibEnvFile()
{
}

bool aflibEnvFile::readValueFromFile(const string key_str,int& result)
{
  string Buffer;
  if (readValueFromFile(key_str,Buffer))
{
result = atoi(Buffer.c_str());
return true;
}
else
return false;
}

bool aflibEnvFile::readValueFromFile(const string key_str,unsigned int& result)
{
  string Buffer;
  if (readValueFromFile(key_str,Buffer))
{
result = atoi(Buffer.c_str());
return true;
}
else
return false;
}

bool aflibEnvFile::readValueFromFile(const string key_str,long int& result)
{
  string Buffer;
  if (readValueFromFile(key_str,Buffer))
{
result = atol(Buffer.c_str());
return true;
}
else
return false;
}

bool aflibEnvFile::readValueFromFile(const string key_str,unsigned long& result)
{
  string Buffer;
  if (readValueFromFile(key_str,Buffer))
{
result = atol(Buffer.c_str());
return true;
}
else
return false;
}

bool aflibEnvFile::readValueFromFile(const string key_str,bool& result)
{
  string Buffer;
  if (readValueFromFile(key_str,Buffer))
{
result = (Buffer == "true");
return true;
}
else
return false;
}

bool aflibEnvFile::readValueFromFile(const string key_str,string& results)
{
   // This function will read a string from the env file that corresponds to the
   // key key_str passed in.
   FILE *  fd = 0;
   char  buf[MAX_LINE_SIZE];
   bool ret_flag = false;
   char* key;
   char* value;

   /* open file */
   fd = fopen(_env_file.c_str(), "r");

   if (fd)
   {
      while (fgets(buf, MAX_LINE_SIZE-1, fd))
      {
         key = strtok(buf, "\t");
         value = strtok(NULL, "\n");
         /* find key in file */
         if (!strcasecmp(key,key_str.c_str()))
         {
            results = value;
            ret_flag = true;
         }
      }
      fclose(fd);
   }

   return(ret_flag);
}

void aflibEnvFile::writeValueToFile(const string key_str,const bool value)
{
  value ?
  writeValueToFile(key_str,string("true")) :
  writeValueToFile(key_str,string("false"));
}

void aflibEnvFile::writeValueToFile(const string key_str,const int value)
{
  char Buffer[30];

sprintf(Buffer,"%i",value);
  writeValueToFile(key_str,string(Buffer));
}

void aflibEnvFile::writeValueToFile(const string key_str,const unsigned int value)
{
  char Buffer[30];

sprintf(Buffer,"%i",value);
  writeValueToFile(key_str,string(Buffer));
}

void aflibEnvFile::writeValueToFile(const string key_str,const long int value)
{
  char Buffer[30];

sprintf(Buffer,"%li",value);
  writeValueToFile(key_str,string(Buffer));
}

void aflibEnvFile::writeValueToFile(const string key_str,const unsigned long value)
{
  char Buffer[30];

sprintf(Buffer,"%lu",value);
  writeValueToFile(key_str,string(Buffer));
}

void aflibEnvFile::writeValueToFile(const string key_str,const string value)
{
   // This function will write a value for the key key_str. If the key_str
   // already exists then it will be overwritten.

   std::vector FileEntries;
   FILE *fd=NULL,*ftemp=NULL;
   char * dir_str;
   char * dir_ptr;
   char  buf[MAX_LINE_SIZE];
   chartempname[12];

   dir_str = strdup(_env_file.c_str());
   if (dir_str)
   {
      /* remove file from the directory string */
      dir_ptr = strrchr(dir_str, (int)'/');
      if (dir_ptr)
      {
         *dir_ptr = 0;

         /* make the directory path if it does not exist */
         mkdir(dir_str, S_IRUSR | S_IWUSR | S_IXUSR |
                        S_IRGRP | S_IWGRP | S_IXGRP |
                        S_IROTH | S_IXOTH);

// if file exists we need to save contents
if ((fd = fopen(_env_file.c_str(), "r")) != NULL)
        {
        while (fgets(buf, MAX_LINE_SIZE-1, fd))
            FileEntries.push_back(string(buf));
          fclose(fd);
}
/*
Changed GS - 20020802
Instead of opening the original file for write access (this destroyes the
existing contents), creates a temporary file and writes into it, then
deletes the original file and renames the temporary
*/
strcpy(tempname,"CGXXXXXX");
if ((ftemp = fdopen(mkstemp(tempname),"w")) != NULL)
{
char *key1,*key2;
char buff1[80],buff2[80];

strncpy(buff1,key_str.c_str(),80);
key1 = strtok(buff1,"\t");
for (std::vector::iterator iter = FileEntries.begin(); iter < FileEntries.end(); iter++)
          {
strncpy(buff2,(*iter).c_str(),80);
key2 = strtok(buff2,"\t");
// IF not the key string then write out to file
if (strcmp(key1,key2) != 0)
{
fprintf(ftemp,"%s",iter->c_str());
fflush(ftemp);
}
}
fprintf(ftemp, "%s\t%s\n", key_str.c_str(),value.c_str());
fflush(ftemp);
fclose(ftemp);
remove(_env_file.c_str());
strcpy(buf,"mv ");
strcat(buf,tempname);
strcat(buf," ");
strcat(buf,_env_file.c_str());
system(buf);
remove(tempname);
}
else
        {
cerr << "Can't open file " << _env_file.c_str() << endl;
        }
     }
     delete dir_str;
   }
}

void aflibEnvFile::deleteFile(void)
{
remove(_env_file.c_str());
}



Come calcolare il determinante di una matrice

Una porzione di codice che consente un rapido calcolo del terminante di una matrice. Il codice Φ costruito sulla base del templare CArray di MFC. Riadattare il codice presentato pu≥ essere la soluzione ideale nel caso in cui si stiano sviluppando applicazioni matematiche che richiedano la risoluzioni di sistemi di equazioni lineari.

template< class ElType >
ElType EHMatrix<ElType>::Determinant() const
{
	if( nRows() != nCols() )
		throw MatException( IDR_ERMATRIXOP ); // Or some other appropriate
                      // way to remind yourself that only a nitwit would try to 
                      // take the determinant of a nonsquare matrix.
	if( nRows() == 0 )
		return 0;
	CArray<EHVector<ElType>*, EHVector<ElType>>*> Rowps; // Array of POINTERS to 
              // vectors that are copies of the original matrix's rows.  Swapping 
              // rows that are pointers is much more efficient that swapping entire
              // arrays.
	Rowps.SetSize( nRows() );
	for( int r=1; r<=Rowps.GetSize(); r++ ) // 
	{
		Rowps[r-1] = new EHVector<ElType>; // NOTE: Matrix class this is from
		(*(Rowps[r-1])) = m_Rows[r];  // is 1 based, the array the rows are
	}                                     // being copied into is 0 based
	ElType det=1; // Start with determinant as 1
// Now row reduce, aka Reduce Row Echelon Form

#define EL(n,m) (*(Rowps[n]))[m+1] // To take care of both dereferencing and 0,1 base
                                   // discrepancy

	for( r=0; r<Rowps.GetSize(); r++ )
	{
		if( EL(r,r) == 0 ) // Swap with a row that has non zero in that col
		{
			int searchr=r+1;
			while( searchr < Rowps.GetSize()  && EL( searchr, r )==0 )
				searchr++;
			if (searchr==Rowps.GetSize())
			{
				det=0; // This system doesn't have a unique solution
				goto XDeterminant_done;
			}
			EHVector<ElType>* TempRp = Rowps[r];
			Rowps[r] = Rowps[searchr];
			Rowps[searchr] = TempRp;
			det *= -1; // Swapping rows negated determinant
		}

		det *= EL(r,r); 
		(*(Rowps[r])) /= EL(r,r);
		for( int RedRow = r+1; RedRow<Rowps.GetSize(); RedRow++ )
		{
			(*(Rowps[RedRow])) += (*(Rowps[r])) * (-1*EL(RedRow,r));
		}
	}
// matrix is now upper triangular with diagonal of all ones, so its determinant is 1
// The Row swaps and divisions it took to get to this point have determined what the
// determinant of the original matrix was
#undef EL

XDeterminant_done:
	for( r=0; r<Rowps.GetSize(); r++ )
	{
		delete Rowps[r]; //
	}
	return det;
}
// matrix is now upper triangular with diagonal of all ones, so its determinant is 1
// The Row swaps and divisions it took to get to this point have determined what the
// determinant of the original matrix was
#undef EL

XDeterminant_done:
	for( r=0; r<Rowps.GetSize(); r++ )
	{
		delete Rowps[r]; //
	}
	return det;
}





Come allineari i controlli sulle form

Quando si creano form ridimensionabili, una delle migliori soluzioni estetiche consiste nel sistemare i pulsanti principali o in alto a destra o in basso a sinistra. Per garantire l'allineamento in ogni situazione, Φ scrivere in un modulo la subroutine indicata di seguito:

Sub ButtonRight(X As Control, _
        Frm As Form, Offset as Integer)
                X.Left = Frm.ScaleWidth - _
                        X.Width - Offset
End Sub

Con la costante Offset Φ possibile specificare la distanza fra ogni pulsante e riutulizzare cos∞ il medesimo codice per pi∙ pulsanti. Una volta sistemati i pulsanti sulla form, Φ necessario aggiungere all'evento Form_Resize il seguente codice:

Private Sub Form_Resize()
        ButtonRight Command1, Me, 0
        ButtonRight Command2, Me, _
                Command1.Width
End Sub




Come spostare controlli e form

Per spostare un controllo o una form in una nuova posizione, Φ possible settare le proprietα Left e Top, indicando in nuovi valori.

frmCustomer.Left = frmCustomer.Left + 100 
frmCustomer.Top = frmCustomer.Top + 50 

Un metodo alternative Φ utilizzare il metodo Move, che risulta pi∙ veloce di circa il 40% rispetto al codice appena visto:

frmCustomer.Move frmCustomer.Left + 100, frmCustomer.Top + 50 



Come generare l'evento clic

Quando si ha necessitα di generare un evento Click, Φ possibile settare a True la proprietα del pulsante corrispondente:
cmdAdd.Value = True 

Cos∞ facendo Φ possibile attivare facilmente un comando su una form diversa rispetto a quella in cui Φ scritto il codice, tuttavia risulta pi∙ veloce chiamare direttamente la procedura relativa all'evento che ci interessa:

Call cmdAdd_Click 



Come installare un font speciale

Quanto spiegato in questo tip consente di caricare e rimuovere qualsiasi font, il tutto senza andare a utilizzare la cartella dei font di Windos. Questo sistema consente di utilizzare nuovi font senza dover riavviare il sistema.
'API: Dichiarazioni
Private Declare Function AddFontResource Lib "gdi32" Alias
"AddFontResourceA" (ByVal lpFileName As String) As Long
Private Declare Function RemoveFontResource Lib "gdi32" Alias
"RemoveFontResourceA" (ByVal lpFileName As String) As Long

'CODICE

Public Function LoadFont(FntFileName As String) As Boolean
    Dim FntRC As Long
        FntRC = AddFontResource(FntFileName)
        If FntRC = 0 Then 'no success
         LoadFont = False
        Else 'success
         LoadFont = True
        End If
End Function
'FntFileName include anche il path
Public Function RemoveFont(FntFileName As String) As Boolean
     Dim RC As Long

     Do
       RC = RemoveFontResource(FntFileName)
     Loop  Until RC=0

End Function




Come allineare il testo in un pulsante

Quando si vuole allineare il testo in un pulsante, l'azione pi∙ comune Φ quello di inserire degli spazo bianchi. Per avere lo stesso effetto in modo "pi∙ professionale", si pu≥ aggiungere il codice qui presentato in un modulo BAS. Richiamando la funzione, si potrα specificare esattamente il tipo di allineamento voluto, sia orizzontale che verticale.
Option Explicit

Private Declare Function GetWindowLong Lib _
	"user32" Alias "GetWindowLongA" (ByVal hWnd _
	As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib _
	"user32" Alias "SetWindowLongA" (ByVal hWnd _
	As Long, ByVal nIndex As Long, ByVal _
	dwNewLong As Long) As Long

Private Const BS_LEFT As Long = &H100

Private Const BS_RIGHT As Long = &H200

Private Const BS_CENTER As Long = &H300

Private Const BS_TOP As Long = &H400

Private Const BS_BOTTOM As Long = &H800

Private Const BS_VCENTER As Long = &HC00


Private Const BS_ALLSTYLES = BS_LEFT Or BS_RIGHT _
	Or BS_CENTER Or BS_TOP Or BS_BOTTOM Or _
	BS_VCENTER

Private Const GWL_STYLE& = (-16)

Public Enum bsHorizontalAlignments
	bsLeft = BS_LEFT
	bsRight = BS_RIGHT
	bsCenter = BS_CENTER
End Enum

Public Enum bsVerticalAlignments
	bsTop = BS_TOP
	bsBottom = BS_BOTTOM
	bsVCenter = BS_VCENTER
End Enum

Public Sub AlignButtonText(cmd As CommandButton, _
	Optional ByVal HStyle As _
	bsHorizontalAlignments = bsCenter, _
	Optional ByVal VStyle As _
	bsVerticalAlignments = bsVCenter)

	Dim oldStyle As Long

	' get current style
	oldStyle = GetWindowLong(cmd.hWnd, GWL_STYLE)

	' clear existing alignment setting(s)
	oldStyle = oldStyle And (Not BS_ALLSTYLES)

	' set new style and refresh button
	Call SetWindowLong(cmd.hWnd, GWL_STYLE, _
		oldStyle Or HStyle Or VStyle)
	cmd.Refresh
End Sub




Come valutare le espressioni

La funzione eval esegue las striga di codice che riceve come argomento. La sintassi Φ:
eval(codestring) 

L'argomento Φ un oggetto String che contiene codice JavaScript. La Stringa Φ passata al parser JavaScript, e viene dunque eseguita come normale codice. Se ci sono istruzioni JavaScript, sono dunque eseguite regolarmente mentre, se Φ presente una espressione, la stessa viene valutata ed il valore risultante Φ ritornato come valore della funzione. Ecco un esempio:

eval("primo=1973; secondo=29; document.write(primo + secondo);"); 

Codice che darα come risultato:

2002

E' da notare che l'argomento codestring Φ opzionale ma, se non si indica alcun argomento, eval restituirα "undefined".




Come leggere un numero in una stringa

La funzione parseInt si occupa di cercare il primo intero presente in una stringa. Il numero di argomenti accettati da parseInt Φ pari a due: il primo Φ la stringa in cui cercare il numero, mentre il secondo parametro indica la base dell'intero Φ pu≥ andare da 2 a 36 (ad esempio 16 per un esadecimale). Il secondo parametro Φ opzionale e, nel caso in cui non viene fornito, il parser cercherα di individuare da solo la base del numero presente nella stringa: se la stringa comincia con una cifra compresa fra 1 e 9, verrα considerata la base 10; se la stringa inizia con 0x oppure 0X, il numero verrα considerato esadecimale; se la stringa comincia con uno zero, il numero sarα analizzato in base otto. Una volta scelta la base, il parser analizza la stringa da sinistra verso destra fino ad incontrare il primo carattere non corrispondente ad alcuna cifra coerente con la base. A partire da questa posizione la restante parte della stringa viene ignorata e parseInt restituisce il valore trovato come intero (attenzione: non come stringa!). Questa funzione intercetta solo il primo intero presente in una stringa e non considera eventuali numeri decimali: tutti i caratteri posizionati dopo un punto o una virgola sono dunque ignorati. Se il primo carattere non Φ uno spazio bianco nΦ un carattere numerico, la funzione restituisce "NaN": Not a Number.

document.write("
" + parseInt("50")) document.write("
" + parseInt("50.12345")) document.write("
" + parseInt("32.00000000")) document.write("
" + parseInt("71.348 92.218 95.405")) document.write("
" + parseInt(" 37 aardvarks")) document.write("
" + parseInt("Nato nel 1973"))

Questo l'output:

50
50
32
71
37
NaN 

La funzione pu≥ essere utilmente utilizzata per effettuare delle conversioni di base:

document.write(parseInt("110", 2)) 

Output:

6 

La corrispettiva funzione per i numeri in virgola mobile Φ parseFloat. La funzione determina se il primo carattere della stringa ricevuta come argomento Φ un numero, in caso affermativo processa la stringa fino a che intercetta la fine del numero. Anche in questo caso il valore Φ ritornato come numero e non come stringa.

document.write("
" + parseFloat("50")) document.write("
" + parseFloat("50.12345")) document.write("
" + parseFloat("32.00000000")) document.write("
" + parseFloat("71.348 92.218 95.405")) document.write("
" + parseFloat("37 aardvarks")) document.write("
" + parseFloat("Nato nel 1979"))

Ecco il risultato:

50
50.12345
32.00000000
71.348
37
NaN 



Come verificare che un drive sia pronto

La funzione riportata accetta come parametro la lettera identificativa del drive di cui vogliamo verificare lo stato. La funzione ritorna poi un valore booleano: true se il drive Φ pronto, false se il disco non Φ presente nel drive.

function DiskInDrive(Drive: Char): Boolean; 
var 
ErrorMode: word; 
begin 
{ make it upper case } 
if Drive in ['a'..'z'] then Dec(Drive, $20); 
{ make sure it's a letter } 
if not (Drive in ['A'..'Z']) then 
raise EConvertError.Create('Not a valid drive ID'); 
{ turn off critical errors } 
ErrorMode := SetErrorMode(SEM_FailCriticalErrors); 
try 
{ drive 1 = a, 2 = b, 3 = c, etc. } 
if DiskSize(Ord(Drive) - $40) = -1 then 
Result := False 
else 
Result := True; 
finally 
{ restore old error mode } 
SetErrorMode(ErrorMode); 
end; 
end;



Come mostrare la dialog con le proprietα di un file

La procedura che presentiamo consente di richiamare la finestra di proprietα dei file. Per poterla utilizzare correttamente Φ necessario aggiungere ShellApi alla clausola USES

procedure PropertiesDialog(FileName:String); 
var 
  sei: TShellExecuteInfo; 
begin 
  FillChar(sei, SizeOf(sei), 0); 
  sei.cbSize := SizeOf(sei); 
  sei.lpFile := PChar(filename); 
  sei.lpVerb := 'properties'; 
  sei.fMask  := SEE_MASK_INVOKEIDLIST; 
  ShellExecuteEx(@sei); 
end; 

Ed ecco come richiamare la procedura

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  if Opendialog1.Execute then PropertiesDialog(Opendialog1.FileName); 
end;




Come creare un file temporaneo

Se si ha bisogno di un file temporaneo, il primo problema Φ trovare un nome univoco per salvarlo e riferirlo univocamente. La funzione che presentiamo si limita proprio a questo, ritornando un nome di file univoco da utilizzare successivamente per la creazione di un file temporaneo.

function GetTempFile(const Extension: string): string; 
var 
  Buffer: array[0..MAX_PATH] OF Char; 
  aFile : string; 
begin 
  GetTempPath(Sizeof(Buffer)-1,Buffer); 
  GetTempFileName(Buffer,'~',0,Buffer); 
  result := StrPas(Buffer); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
ShowMessage(GetTempFile('.tmp')); 
// Il file temporaneo sarα del tipo C:\WINDOWS\TEMP\~61D5.TMP 
end; 



Come rendere una form trasparente

Se si vuole dare uno stile inconsueto ed accattivante alle proprie applicazioni, una possibilitα Φ offerta da questo tip. Con il form completamente trasparente, le nostre applicazioni non correranno il rischio di passare inosservate!

unit Unit1; 

interface 

uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  StdCtrls; 

type 
  TForm1 = class(TForm) 
    Button1: TButton; 
    Button2: TButton; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
  private 
    { Private declarations } 
  public 
    { Public declarations } 
    procedure dovisible; 
    procedure doinvisible; 
end; 

var 
  Form1: TForm1; 
  FullRgn,ClientRgn,CtlRgn:HWND; 

implementation 

{$R *.DFM} 

procedure TForm1.DoInvisible; 
var 
  AControl : TControl; 
  A, Margin, X, Y, CtlX, CtlY : Integer; 
begin 
  Margin := ( Width - ClientWidth ) div 2; 
  FullRgn := CreateRectRgn(0, 0, Width, Height); 
  X := Margin; 
  Y := Height - ClientHeight - Margin; 
  ClientRgn := CreateRectRgn( X, Y, X + ClientWidth, Y + ClientHeight ); 
  CombineRgn( FullRgn, FullRgn, ClientRgn, RGN_DIFF ); 
  for A := 0 to ControlCount - 1 do 
  begin 
    AControl := Controls[A]; 
    if ( AControl is TWinControl ) or ( AControl is TGraphicControl ) 
    then with AControl do 
    begin 
      if Visible then 
      begin 
        CtlX := X + Left; 
        CtlY := Y + Top; 
        CtlRgn := CreateRectRgn( CtlX, CtlY, CtlX + Width, CtlY + Height ); 
        CombineRgn( FullRgn, FullRgn, CtlRgn, RGN_OR ); 
      end; 
    end; 
  end; 
  SetWindowRgn(Handle, FullRgn, TRUE); 
end; 

procedure TForm1.DoVisible; 
begin 
  FullRgn := CreateRectRgn(0, 0, Width, Height); 
  CombineRgn(FullRgn, FullRgn, FullRgn, RGN_COPY); 
  SetWindowRgn(Handle, FullRgn, TRUE); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  DoVisible; 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
begin 
  DoInvisible; 
end; 

end.



Come impedire lo spostamento di una finestra

Con il codice qui presentato Φ possibile fissare la posizione di una finestra sullo schermo. Qualsiasi tentativo dell'utente di spostarla fallirα miseramenteà Nella sezione Private dichiaramo la procedura:

procedure WMWindowPosChanging(var Message: TWMWindowPosChanging); 
          message WM_WINDOWPOSCHANGING; 

Mentre questo sarα il codice della procedura sarα:

procedure TForm1.WMWindowPosChanging(var Message: TWMWindowPosChanging); 
begin 
  with Message.WindowPos^ do 
  Flags:= Flags OR SWP_NOMOVE; 
end;