GT Uptime 1.0

12. dicembre 2011 16.44

Oggi rendo disponibile una piccola utility: GT Uptime. Questo software permette di conoscere da quanto tempo il vostro computer è attivo (il famoso uptime). E' un software che richiede il framework .NET 4.0.

 

L'utilizzo del software è molto semplice: una volta installato è possibile avviarlo dall'icona creata nel menu start. Vi sarà presentata una form dentro la quale una label indicherà il periodo di uptime del vostro computer. Se minimizzato ad icona, GT Uptime resterà attivo in background installando un'icona nella tray bar di Windows. Passando con il mouse sopra l'icona nella tray bar vi verrà mostrata in una finestrella balloon il periodo di uptime. Cliccando sempre sulla stessa icona, il form principale verrà nuovamente mostrato a video.

 

GTUptime.zip (348,25 kb)

Creare un file CAB per l'installazione di un programma per Windows Mobile

22. luglio 2010 08.22

Lo scopo di questo mini tutorial è quello di creare un file CAB per l'installazione di una nostra applicazione per Windows Mobile. Il procedimento qui descritto prende in considerazione il caso in cui l'applicazione sia scritta utilizzando il .NET Compact Framework 3.5 e Visual Studio 2008 su cui è installato il più recente SDK per Windows Mobile.

 

Passo I: Creazione del progetto di setup

La prima cosa da fare è aggiungere allo soluzione del nostro programma un nuovo progetto: clicchiamo con il tasto destro del mouse sull'icona della soluzione nell'apposita alberatura e selezioniamo dal menu contestuale la voce "Aggiungi -> Nuovo Progetto". Dalla finestra di dialogo che ci verrà presentata selezionare sulla sinistra il tipo di progetto "Altri tipi di progetto -> Installazione e Distribuzione" e come modello "Progetto CAB per Smart Device". Per semplicità chiamiamo il nuovo progetto "MySetup"

 

Passo II: Aggiunta dell'output di progetto

Nell'alberatura della soluzione a questo punto avremo il nuovo "MySetup". Cliccando con il tasto destro sull'icona del progetto selezioniamo dal menu contestuale la voce "Aggiungo -> output di progetto". Dalla finestra di dialogo che ci verrà visualizzata sarà sufficiente selezionare il progetto dell'applicazione e Visual Studio aggiungerà per noi le dipendenze rilevate e il file eseguibile.

 

Passo III: Piccole personalizzazioni

A questo punto vogliamo una piccola ma importante personalizzazione: vorremmo che nella cartella "Programmi" di Windows Mobile comparisse l'icona della nostra applicazione. Molto semplice: nella finestra dell'alberatura della soluzione, facciamo doppio click sull'icona dell'output del progetto aggiunto e ci verrà presentata una finestra divisa in due area di cui quella sinistra è occupata dal "File system nel computer di destinazione". Bene, facciamo click con il tasto destro del mouse su quest'area della finestra e dal menu contestuale visualizzato scegliamo la voce "Aggiungi cartella speciale -> Cartella dei programmi". Facendo questo sarà possibile aggiungere nell'area a destra della nuova voce creata un link all'eseguibile: per fare questo selezioniamo dalla parte sinistra della finestra la voce "Cartella applicazion", facciamo click con il tasto destro del mouse nell'area destra sull'icona dell'output del progetto e dal menu contestuale scegliamo la voce "Crea collegamento ...". A questo punto rinominiamo il collegamento creato con il nome della nostra applicazione e trasciniamolo sulla voce "Cartella dei programmi" dell'area sinistra della finestra.

 

Bene a questo punto possiamo compilare il nostro progetto d'installer che genererà per noi il file CAB da trasferire sul dispositivo Windows Mobile cui vogliamo installare la nostra applicazione.

Semplici operazioni di imaging con .Net 3.5 e WPF

18. luglio 2010 13.47

Lo scopo di questo breve tutorial è quello di mostrare come con poche righe di codice .Net 3.5 e Windows Presentation Foundation (WPF) ci permettono di aprire, modificare il colore di un’immagine e salvare il risultato finale. Per quanto riguarda la costruzione della GUI in XAML rimandiamo direttamente al progetto in allegato.

Come anticipato, il nostro scopo è quello di caricare un’immagine (per semplicità gestiremo immagini BMP, GIF e JPEG) in un oggetto del tipo System.Windows.Controls.Image, applicare un filtro all’immagine caricata (per semplicità convertiremo l’immagine in bianco e nero, ovvero in un’immagine con 1 bit di colore), visualizzeremo nel medesimo controllo il risultato e salveremo la stessa in un file (anch’esso del tipo BMP, GIF o JPEG).

Premettiamo che sfortunatamente WPF non ha ancora a disposizione dei controllo di apertura/salvataggio di un file, per cui saremo costretti ad includere nel nostro progetto anche la libreria System.Windows.Forms.

OpenFileDialog openFile = new OpenFileDialog();

openFile.Filter = "BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|JPEG files (*.jpg)|*.jpg";
openFile.ShowDialog();

fileToProcess = openFile.FileName;

if (fileToProcess != String.Empty || fileToProcess != "")
{
    Uri myUri = new Uri(fileToProcess, UriKind.RelativeOrAbsolute);

    switch (openFile.FilterIndex)
    {
        case 0:
            BmpBitmapDecoder decoder = new BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            BitmapSource bitmapSource = decoder.Frames[0];
            mainImage.Source = bitmapSource;

            break;

         case 1:
             GifBitmapDecoder gifDecoder = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
             BitmapSource gifBitmapSource = gifDecoder.Frames[0];
                        mainImage.Source = gifBitmapSource;

             break;

          case 3:
              JpegBitmapDecoder jpgDecoder = new JpegBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
              BitmapSource jpgBitmapSource = jpgDecoder.Frames[0];
              mainImage.Source = jpgBitmapSource;

              break;

          default:
              break;
      }
 }

Passo 1: caricamento dell’immagine nel controllo Image (mainImage).

OpenFileDialog openFile = new OpenFileDialog();

openFile.Filter = "BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|JPEG files (*.jpg)|*.jpg";
openFile.ShowDialog();

fileToProcess = openFile.FileName;

if (fileToProcess != String.Empty || fileToProcess != "")
{
    Uri myUri = new Uri(fileToProcess, UriKind.RelativeOrAbsolute);

    switch (openFile.FilterIndex)
    {
        case 0:
            BmpBitmapDecoder decoder = new BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            BitmapSource bitmapSource = decoder.Frames[0];
            mainImage.Source = bitmapSource;

            break;

         case 1:
             GifBitmapDecoder gifDecoder = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
             BitmapSource gifBitmapSource = gifDecoder.Frames[0];
                        mainImage.Source = gifBitmapSource;

             break;

          case 3:
              JpegBitmapDecoder jpgDecoder = new JpegBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
              BitmapSource jpgBitmapSource = jpgDecoder.Frames[0];
              mainImage.Source = jpgBitmapSource;

              break;

          default:
              break;
      }
 }

Il codice precedente non ha bisogno di molte spiegazioni: tramite l’usuale controllo OpenFileDialog otteniamo il nome del file da caricare che andremo a “decodificare” tramite un’istanza della classe BmpBitmapDecodre/GifBitmapDecoder/JpgBitmapDecoder. A sua volta quest’oggetto restituirà un frame che contiene il “sorgente”, ovvero un’istanza di ImageSource che è il formato di “input” del controllo System.Windows.Controls.Image, ovvero l’oggetto che mostra a video l’immagine caricata dal file.

 

Passo 2: conversione in bianco e nero dell’immagine caricata.

FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap();

newFormatedBitmapSource.BeginInit();
newFormatedBitmapSource.Source = (BitmapSource)mainImage.Source;
newFormatedBitmapSource.DestinationFormat = PixelFormats.BlackWhite;
newFormatedBitmapSource.EndInit();

Image myImage = new Image();
myImage.Source = newFormatedBitmapSource;
mainImage.Source = myImage.Source;

Anche in questo caso il codice è molto semplice: un oggetto FormatConvertedBitmap prenderà come sorgente l’immagine caricata nel controllo Image e tramite la proprietà DestinationFormat applicherà il filtro che abbiamo scelto, in questo caso il formato di pixel con 1 bit di colore.

 

Successivamente provvederemo a creare un’oggetto Image a partire dalla conversione appena operata che sarà la nuova “sorgente” del controllo Image che di conseguenza mostrerà l’immagine modificata.

 

Passo 3: Salvataggio su disco dell’immagine modificata.

SaveFileDialog saveFile = new SaveFileDialog();

saveFile.Filter = "BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|JPEG files (*.jpg)|*.jpg";
saveFile.ShowDialog();

fileToSave = saveFile.FileName;

if (fileToSave != String.Empty || fileToSave != "")
{
    double actualHeight = mainImage.RenderSize.Height;
    double actualWidth = mainImage.RenderSize.Width;
    double renderHeight = actualHeight * 1;
    double renderWidth = actualWidth * 1;

    RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)renderWidth, (int)renderHeight, 96, 96, PixelFormats.Pbgra32);
    VisualBrush sourceBrush = new VisualBrush(mainImage);
    DrawingVisual drawingVisual = new DrawingVisual();
    DrawingContext drawingContext = drawingVisual.RenderOpen();

    using (drawingContext)
    {
        drawingContext.PushTransform(new ScaleTransform(1, 1));
        drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
    }

    renderTarget.Render(drawingVisual);

    switch (saveFile.FilterIndex)
    {
        case 1:
            BmpBitmapEncoder bmpEncoder = new BmpBitmapEncoder();
            bmpEncoder.Frames.Add(BitmapFrame.Create(renderTarget));

            using (FileStream fileStream = new FileStream(fileToSave, FileMode.Create))
            {
                bmpEncoder.Save(fileStream);
                fileStream.Flush();
                fileStream.Close();
            }

            break;

        case 2:
            GifBitmapEncoder gifEncoder = new GifBitmapEncoder();
            gifEncoder.Frames.Add(BitmapFrame.Create(renderTarget));                        

            using (FileStream fileStream = new FileStream(fileToSave, FileMode.Create))
            {
                gifEncoder.Save(fileStream);
                fileStream.Flush();
                fileStream.Close();
            }

            break;

        case 3:
            JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder();
            jpgEncoder.QualityLevel = 100;
            jpgEncoder.Frames.Add(BitmapFrame.Create(renderTarget));

            using (FileStream fileStream = new FileStream(fileToSave, FileMode.Create))
            {
                jpgEncoder.Save(fileStream);
                fileStream.Flush();
                fileStream.Close();
            } 

            break;

        default:
            break;
    }
}

Questo metodo è un po’ più lungo dei precedenti ma alla fine non è molto complicato. Tramite l’usuale oggetto SaveFileDialog otteniamo il nome del file su cui salvare l’immagine che abbiamo precedentemente modificato. Calcoliamo altezza e larghezza dell’immagine mostrata a video e le stesse informazioni per l’immagine che andremo a salvare. Notiamo che in questo caso avviene una moltiplicazione per 1: stiamo semplicemente usando la scala 1:1.

 

Gli oggetti del tipo VisualBrush, DrawingVisual e DrawingContext ci permettono di “selezionare” l’immagine contenuta nel controllo Image a partire dal punto inizale di coordinate (0,0) al punto finale (actualWidth, actualHeight). Il risultato della selezione verrà “registrato” in un oggetto RenderTargetBitmap che non fa altro che convertire un oggetto “visual” appunto in una bitmap.

 

Lo switch successivo è molto semplice: a seconda del tipo di output scelto (bmp, gif o jpg) creeremo un oggetto “encoder” cui verrà aggiunto un frame contenente la bitmap precedentemente creata. Questo encoder possiede un metodo “save” che permette di salvare il contenuto dell’encodere in uno stream creato ad hoc. In questo caso lo stream su cui andremo a salvare è uno stream su file.

Comprimere e decomprimere MemoryStream con DeflateStream e .Net

18. luglio 2010 13.40

A volte capita di dover comprimere/decomprimere dei flussi di dati in memoria perché magari li si deve spedire sulla rete tramite socket tcp, web services ecc. ecc. Il compito non è particolarmente difficile e come al solito il framework .Net ci viene incontro fornendoci le “basi” del piatto: MemoryStream per la gestione degli stream in memoria e GZipStream/DeflateStream (per la cui differenza vi rimando all’ottima documentazione su MSDN) per la compressione degli stream.

L’esempio che propongo di seguito mostra appunto l’utilizzo delle classi MemoryStream per il “trasporto” delle informazioni verso la classe “comprimente” che in questo caso ho scelto essere la DeflateStream.

Vediamo per prima cosa la compressione:

public static byte[] Comprimi(byte[] data)
{
     MemoryStream ms = new MemoryStream();
     DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress);
     ds.Write(data, 0, data.Length);
     ds.Flush();
     ds.Close();
     return ms.ToArray();
}

Il contenuto di questo metodo è molto semplice: si passa in input un array di byte, si crea un MemoryStream che conterrà il contenuto dell’array di byte in formato compresso, si crea un DeflateStream che avrà come primo parametro lo stream in cui verrà scritto ciò che si andrà a comprimere, e come secondo parametro la modalità di compressione (compressione/decompressione).

 

A questo punto tramite il metodo Write possiamo effettivamente scrivere nello stream di memoria l’array di byte compresso.

 

Qualche riga in più, ma non troppo, per il metodo di decompressione:

public static byte[] Decomprimi(byte[] data)
{
     MemoryStream ms = new MemoryStream(data);
     DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress);

     Listl = new List();
     int theByte = ds.ReadByte();

     while (theByte != -1)
     {
          l.Add((byte)theByte);
          theByte = ds.ReadByte();
     }

     byte[] retVal = l.ToArray();         

     return retVal;
}

Vediamolo in dettaglio: creeremo un MemoryStream in cui caricheremo dentro l’array di byte compresso. Creeremo un oggetto DeflateStream il cui primo parametro questa volta sarà il MemoryStream con i valory di input e specificheremo che vogliamo applicare a questi una decompressione.

 

A questo punto leggeremo byte per byte il contenuto del DeflateStream e aggiungeremo il byte letto ad una lista di byte che verray alla fine convertita in un array di byte che finalmente conterrà il contenuto “scompattato” dell’array di partenza.

 

Se supponiamo d’avere un comune file di testo nella radice del disco “C”, un possibile esempio di quanto visto sopra potrebbe essere:

static void Main(string[] args)
{
     byte[] myarray = File.ReadAllBytes(@"C:\TEST.TXT");
     byte[] myArrayCompresso = Comprimi(myarray);
     byte[] myArrayDecompresso = Decomprimi(myArrayCompresso);

     String letto = System.Text.ASCIIEncoding.ASCII.GetString(myArrayDecompresso);
     System.Console.WriteLine("Ho letto:\n" + letto + "\n");

     Console.WriteLine("Premi  per terminare");
     Console.ReadLine();
}

Info su di me

Il mio nome è Gennaro Eduardo Tangari e sono uno sviluppatore certificato su tecnologie Microsoft .NET che lavora prevalentemente su applicazioni web enterprise e mobile.

Attualmente lavoro presso Value Team S.p.A. con la qualifica di Senior Consultant su progetti internazionali e nazionali basati su tecnologie Microsoft, con particolare cura verso Microsoft Dynamics CRM.

Questo blog nasce dall'esigenza di condividere esperienze e metodologie acquisite durante gli anni di lavoro cercando di restituire alla rete quello che la rete stessa mi ha dato: informazioni utili.

 

Certificazione

 

 

QRCode