Finestra con Menu – Programma Windows

In questo breve articolo mostro come fare una finestra con menu.

Vi piacerebbe fare un programma, che gira sotto Windows, con un Menu? Se siete interessati all’argomento, ecco uno spunto da cui partire.

Apriamo il Blocco Note ( Notepad ) e scriviamo il file di testo che contiene il Menu. Salviamo e rinominiamo con estensione .rc ( resource compiler ). In questo caso, il file è stato nominato “miaico.rc“. Ecco il contenuto del file “miaico.rc“:

1 ICON "miaico.ico"


#define IDM_New 40001
#define IDM_Quit 40002
#define IDM_Copy 40003
#define IDM_Paste 40004


My_Menu MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New", IDM_New
MENUITEM "&Quit", IDM_Quit
END
POPUP "&Edit"
BEGIN
MENUITEM "&Copy", IDM_Copy
MENUITEM "&Paste", IDM_Paste
END
END

Dal codice risulta chiaro che “miaico.ico” è il file che contiene l’icona del programma. Si può fare un “bmp” con Paint e convertirlo in “ico” con ffmpeg. IL Menu si chiama “My_Menu” e contiene le voci “File” e “Edit“. La Voce “File” contiene le sottovoci “New” e “Quit“, mentre, la voce “Edit” contiene “Copy” e “Paste“. Vi sono anche dei #define, dei quali capiremo l’utilità a breve. IL file “miaico.rc” si compila con windres, attraverso il comando: PROMPT> windres miaico.rc miaico.o

Si ottiene il file oggetto “miaico.o“.

Integrazione del Menu nel sorgente del programma.

Vediamo ora il sorgente C++ del programma e come si collega il Menu.

Ecco il sorgente del programma ( file “semplice.cpp” )

/* Creation of a simple Windows API program */

#include <windows.h>

#define IDM_New 40001       // Stessi define già visti nel file miaico.rc
#define IDM_Quit 40002
#define IDM_Copy 40003
#define IDM_Paste 40004


/*  Declare Windows procedure  */
LRESULT CALLBACK ProceduraFinestra (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char nomeclasse[ ] = "WindowsApp";


int WINAPI
WinMain (HINSTANCE istanzaquestoprogramma,
         HINSTANCE hPrevInstance,
         LPSTR lpszArgument,
         int nFunsterStil)

{
    HWND finestra;               /* This is the handle for our window */
    MSG messaggi;            /* Here messaggi to the application are saved */
    WNDCLASSEX strutturafinestra;        /* Data structure for the windowclass */

    /* The Window structure */
    strutturafinestra.hInstance = istanzaquestoprogramma;
    strutturafinestra.lpszClassName = nomeclasse;
    strutturafinestra.lpfnWndProc = ProceduraFinestra;      /* This function is called by windows */
    strutturafinestra.style = CS_DBLCLKS;                 /* Catch double-clicks */
    strutturafinestra.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    strutturafinestra.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    strutturafinestra.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    strutturafinestra.hCursor = LoadCursor (NULL, IDC_ARROW);
    strutturafinestra.lpszMenuName = "My_Menu";  // definito in miaico.rc
    strutturafinestra.cbClsExtra = 0;   /* No extra bytes after the window class */
    strutturafinestra.cbWndExtra = 0;  /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    strutturafinestra.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&strutturafinestra))
        return 0;

    /* The class is registered, let's create the program*/
    finestra = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           nomeclasse,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           istanzaquestoprogramma,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (finestra, SW_SHOW);

    /* Run the messaggio loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messaggi, NULL, 0, 0))
    {
        /* Translate virtual-key messaggi into character messaggi */
        TranslateMessage(&messaggi);
        /* Send messaggio to ProceduraFinestra */
        DispatchMessage(&messaggi);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messaggi.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK
ProceduraFinestra (HWND carciofi, UINT tagliatelle, WPARAM wParam, LPARAM lParam)
{
    switch (tagliatelle)  // carciofi... tagliatelle.. chiamali come vuoi.               

// sono soltanto parametri formali 
    {
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the messaggio queue */
            break;

        case WM_COMMAND:

        if (LOWORD(wParam) == IDM_Quit) {PostQuitMessage (0);}; 

// se clicco la voce "Quit" esco...

        if (LOWORD(wParam) == IDM_New) {MessageBox(NULL,"New","New",NULL);};

        if (LOWORD(wParam) == IDM_Copy) {MessageBox(NULL,"Copy","Copy",NULL);};

        if (LOWORD(wParam) == IDM_Paste) {MessageBox(NULL,"Paste","Paste",NULL);};

        break;


        default:                      /* for messaggi that we don't deal with */
            return DefWindowProc (carciofi, tagliatelle, wParam, lParam);
    }

    return 0;
}

Nel sorgente C++ si vedono i collegamenti col Menu, definito in “miaico.rc“. Ci sono gli stessi #define, sfruttati nella porzione di codice che riguarda il messaggio windows WM_COMMAND. L’istruzione di assegnazione “strutturafinestra.lpszMenuName = ‘My_Menu’;” indica al programma C++ che il menu da caricare si chiama “My_Menu“, come indicato nel file “miaico.rc“.

Comandi per compilare il progetto.

Ecco, infine i comandi per compilare il progetto.

C:\..\tuopercorso>cmd    // Apre la console nel "tuopercorso"

C:\..\tuopercorso>g++ -c semplice.cpp  // genera il file oggetto "semplice.o"

C:\..\tuopercorso>windres miaico.rc miaico.o // genera il file oggetto "miaico.o"

C:\..\tuopercorso>g++ --machine-windows semplice.o miaico.o -o semplice.exe 

// collega i file oggetto .o e genera l'eseguibile "semplice.exe". L'opzione --machine-windows serve per ottenere un eseguibile che avrà soltanto la finestra di Windows ( con il menu ), senza la console.


L’articolo si conclude qui. Spero possa essere utile a qualcuno.

Andrea Paolini ( Amministratore del Blog )