Di cosa parla esattamente questo tutorial

Questo tutorial si prefigge di insegnarvi le basi (con gli extra più comuni) per scrivere programmi usando le API Win32. Il linguaggio usato è il C, anche se compilatori C++ compilerebbero il codice ugualmente. Infatti la maggior parte delle informazioni sono applicabili ad ogni linguaggio che può accedere alle API, incluso Java, Assembly e Visual Basic. Non sarà presentato nessun codice relativo a questi linguaggi, ma vi posso dire che molte persone precedentemente hanno usato ed applicato con successo le informazioni presenti su questo documento nei linguaggi sopra citati.

Questo tutorial non vi insegnerà il linguaggio C, né vi dirà come fare a far funzionare il vostro compilatore (Borland C++, Visual C++, LCC-Win32, ecc…) Tuttavia dedicherò dei piccoli momenti nell’appendice per fornire alcune note sull’uso dei compilatori che conosco.

Se non sapete che cosa sono una macro o una typedef, oppure come funziona uno switch(), allora tornate indietro con il vostro browser e leggete prima un buon libro o tutorial sul linguaggio C.

Note Importanti

A volte nel testo indicherò alcune cose da leggere come IMPORTANTI perchè confondono molte persone e se non le leggetè molto probabilmente confonderanno anche voi. La prima è:
Il codice sorgente del file zip non è opzionale: nel tutorial è incluso solo il codice rilevante ai fini della discussione; per vedere come questo codice deve essere inserito in un programma, dovete consultare il codice sorgente del file ZIP. E questa è la seconda:
Leggete tutto! Se avete una domanda su una sezione del tutorial, se avete un pò di pazienza potrebbe trovare risposta più tardi nella lettura. Se proprio non riuscite a stare con il pensiero di non conoscere, al massimo fate una ricerca (I computer possono farlo) nel resto del documento prima di chiedere alle persone su irc o via email.
Un’altra cosa da ricordare è che una discussione circa l’oggetto A potrebbe trovare risposta nella discussione di B o di C oppure di L. Quindi guardate prima un pò intorno.

Bene, credo sia tutto; iniziamo a vedere un pò di codice.

Il primo programma in Win32

Se siete completi dilettanti assicuriamoci prima che sappiate compilare un’applicazione base di Win32. Passate il codice seguente al compilatore e se tutto va bene dovreste ottenere il programma per windows più semplice mai scritto.

Ricordate di compilarlo in C non in C++. Probabilmente non ci sarebbero differenze, ma siccome tutto il codice di questo tutorial è scritto in C solamente, avrebbe senso partire sul giusto binario. Nella maggiorparte dei casi tutto questo è ottenibile semplicemente scrivendo il codice in un file .c invece che .cpp. Se tutto questo vi confonde, chiamate il file test.c ed ignorate quello che ho detto.

#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, "Addio, Mondo Crudele!", "Nota", MB_OK);
    return 0;
}

Se questo programma non funziona, il primo passo è quello di leggere gli errori dati e se non li capite, cercate il loro significato sulla guida o la documentazione del tuo compilatore. Assicuratevi di aver specificato una GUI Win32 (NON una “console”) nel progetto/makefile/target o qualsiasi cosa viene applicata al compilatore. Sfortunatamente non vi posso essere di aiuto in questa fase, gli errori possono variare da compilatore a compilatore (e da persona a persona).
Potrete ricevere dei warning perchè non sono stati usati tutti i parametri passati a WinMain(), ma va bene. Ora che abbiamo stabilito che potete compilare un programma analizziamo un pò il codice…

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
   LPSTR lpCmdLine, int nCmdShow)

WinMain è l’equivalente di main() per DOS o UNIX. Qui il programma inizia l’esecuzione. I parametri sono i seguenti:

  • HINSTANCE hInstance Handle del modulo eseguibile del programma (il file.exe in memoria)
  • HINSTANCE hPrevInstance Sempre NULL per i programmi Win32.
  • LPSTR lpCmdLine La riga di comando in un’unica stringa. NON include il nome del programma.
  • int nCmdShow Un valore intero che può essere passato a ShowWindow(). Su questo ci torneremo più tardi..

hInstance è usato per cose tipo caricare delle risorse o per qualunque altra operazione effettuata su basi per-module. Un modulo è anche un EXE o una DLL caricata nel programma. Per la maggiorparte (se non per tutto) il tutorial, ci preoccuperemo solamente di un unico modulo, l’EXE.
hPrevInstance era usato in Win16 per passare l’handle dell’istanza precedente del programma (se ne esisteva una). Non viene più applicato in Win32 quindi ignorate il parametro.

Convenzioni di chiamata

WINAPI specifica la convenzione di chiamata ed è definito come _stdcall. Se non sapete cosa significa non preoccupatevi perchè non avrà alcun effetto sullo scopo di questo tutorial. Ricordatevi solamente che è necessario.

Tipi di dati in Win32

Vi accorgerete che molte delle keywords o dei tipi hanno definizioni specifiche in Windows, UINT per unsigned int, LPSTR per char* etc… Quello che scegliete dipende da voi. Se vi viene più semplice usare char* invece di LPSTR, fatelo tranquillamente. Assicuratevi solamente di conoscere che tipo è prima di sostituirlo con qualcos’altro.
Ricordatevi solamente questi pochi concetti e riuscirete sarà semplice interpretarli; Il prefisso LP sta per Long Pointer. In Win32 la parte Long è obsoleta quindi potete non considerarla. . Se invece non conoscete cos’è un puntatore… beh.. 1) Andate alla ricerca di un libro o di un tutorial sul C, oppure 2) andate avanti nella lettura e confondetevi ancora di più. Io raccomando #1, ma molta gente preferisce #2 (Anche io:). Ma non dite che non vi ho avvisato.

Un’altra cosa da ricordare è la C che segue LP e sta ad indicare una costante (const). LPCSTR per esempio indica un puntatore ad una stringa costante, una stringa che non può essere o non verrà modificata. LPSTR quindi non è const e può essere modificata.
Si potrebbero incontrare anche delle T mixate dentro. Non preoccupatevi di questo per ora, a meno che non state lavorando intenzionalmente in Unicode, che…. non significa niente :).