Condividi tramite


Uso di Windows

Gli esempi in questa sezione descrivono come eseguire le attività seguenti:

Creazione di una finestra principale

La prima finestra creata da un'applicazione è in genere la finestra principale. Per creare la finestra principale, usare la funzione CreateWindowEx, specificando la classe della finestra, il nome della finestra, gli stili della finestra, le dimensioni, la posizione, l'handle di menu, l'handle di istanza e i dati di creazione. Una finestra principale appartiene a una classe di finestra definita dall'applicazione, pertanto è necessario registrare la classe window e fornire una routine finestra per la classe prima di creare la finestra principale.

La maggior parte delle applicazioni usa in genere lo stile WS_OVERLAPPEDWINDOW per creare la finestra principale. Questo stile offre alla finestra una barra del titolo, un menu della finestra, un bordo di ridimensionamento e pulsanti per minimizzare e massimizzare. La funzioneCreateWindowExrestituisce un handle che identifica in modo univoco la finestra.

Nell'esempio seguente viene creata una finestra principale appartenente a una classe finestra definita dall'applicazione. Il nome della finestra, finestra principale, verrà visualizzato nella barra del titolo della finestra. Combinando gli stili WS_VSCROLL e WS_HSCROLL con lo stile WS_OVERLAPPEDWINDOW, l'applicazione crea una finestra principale con barre di scorrimento orizzontali e verticali oltre ai componenti forniti dallo stile WS_OVERLAPPEDWINDOW. Le quattro occorrenze della costante CW_USEDEFAULT impostano le dimensioni iniziali e la posizione della finestra sui valori predefiniti definiti dal sistema. Specificando NULL anziché un handle di menu, la finestra avrà il menu definito per la classe window.

HINSTANCE hinst; 
HWND hwndMain; 
 
// Create the main window. 
 
hwndMain = CreateWindowEx( 
    0,                      // no extended styles           
    "MainWClass",           // class name                   
    "Main Window",          // window name                  
    WS_OVERLAPPEDWINDOW |   // overlapped window            
             WS_HSCROLL |   // horizontal scroll bar        
             WS_VSCROLL,    // vertical scroll bar          
    CW_USEDEFAULT,          // default horizontal position  
    CW_USEDEFAULT,          // default vertical position    
    CW_USEDEFAULT,          // default width                
    CW_USEDEFAULT,          // default height               
    (HWND) NULL,            // no parent or owner window    
    (HMENU) NULL,           // class menu used              
    hinst,                  // instance handle              
    NULL);                  // no window creation data      
 
if (!hwndMain) 
    return FALSE; 
 
// Show the window using the flag specified by the program 
// that started the application, and send the application 
// a WM_PAINT message. 
 
ShowWindow(hwndMain, SW_SHOWDEFAULT); 
UpdateWindow(hwndMain); 

Si noti che l'esempio precedente chiama la funzione ShowWindow dopo aver creato la finestra principale. Questa operazione viene eseguita perché il sistema non visualizza automaticamente la finestra principale dopo la creazione. Passando il flag SW_SHOWDEFAULT a ShowWindow, l'applicazione consente al programma che ha avviato l'applicazione di impostare lo stato di visualizzazione iniziale della finestra principale. La funzione UpdateWindow invia alla finestra il primo messaggio WM_PAINT.

Creazione, elenco e ridimensionamento di finestre figlie

È possibile dividere l'area client di una finestra in diverse aree funzionali utilizzando le sottofinestre. La creazione di una finestra figlio è simile alla creazione di una finestra principale: è possibile usare la funzioneCreateWindowEx. Per creare una finestra di una classe finestra definita dall'applicazione, è necessario registrare la classe finestra e fornire una procedura finestra prima di creare la finestra figlia. È necessario assegnare alla finestra figlio lo stile di WS_CHILD e specificare una finestra padre per la finestra figlio al momento della creazione.

L'esempio seguente divide l'area client della finestra principale di un'applicazione in tre aree funzionali creando tre finestre figlio di dimensioni uguali. Ogni finestra figlia ha la stessa altezza dell'area client della finestra principale, ma è larga un terzo. La finestra principale crea le finestre figlio in risposta al messaggio WM_CREATE, che la finestra principale riceve durante il proprio processo di creazione della finestra. Poiché ogni finestra figlia ha lo stile WS_BORDER, ognuna ha un bordo sottile. Inoltre, poiché lo stile WS_VISIBLE non è specificato, ogni finestra figlia viene inizialmente nascosta. Si noti inoltre che a ogni finestra secondaria viene assegnato un identificatore di finestra secondaria.

Quando le dimensioni cambiano, la finestra principale ridimensiona e posiziona le finestre figlio in risposta al messaggio di WM_SIZE che riceve. In risposta a WM_SIZE, la finestra principale recupera le dimensioni dell'area client usando la funzione GetClientRect e quindi passa le dimensioni alla funzione EnumChildWindows. EnumChildWindows a sua volta passa l'handle a ogni finestra figlio alla funzione di callback definita dall'applicazioneEnumChildProc. Questa funzione ridimensiona e posiziona ogni finestra figlio chiamando la funzione MoveWindow; le dimensioni e la posizione si basano sulle dimensioni dell'area client della finestra principale e sull'identificatore della finestra figlio. Successivamente, EnumChildProc chiama la funzione ShowWindow per rendere visibile la finestra.

#define ID_FIRSTCHILD  100 
#define ID_SECONDCHILD 101 
#define ID_THIRDCHILD  102 
 
LONG APIENTRY MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    RECT rcClient; 
    int i; 
 
    switch(uMsg) 
    { 
        case WM_CREATE: // creating main window  
 
            // Create three invisible child windows. 

            for (i = 0; i < 3; i++) 
            { 
                CreateWindowEx(0, 
                               "ChildWClass", 
                               (LPCTSTR) NULL, 
                               WS_CHILD | WS_BORDER, 
                               0,0,0,0, 
                               hwnd, 
                               (HMENU) (int) (ID_FIRSTCHILD + i), 
                               hinst, 
                               NULL); 
            }
 
            return 0; 
 
        case WM_SIZE:   // main window changed size 
 
            // Get the dimensions of the main window's client 
            // area, and enumerate the child windows. Pass the 
            // dimensions to the child windows during enumeration. 
 
            GetClientRect(hwnd, &rcClient); 
            EnumChildWindows(hwnd, EnumChildProc, (LPARAM) &rcClient); 
            return 0; 

        // Process other messages. 
    } 
    return DefWindowProc(hwnd, uMsg, wParam, lParam); 
} 
 
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam) 
{ 
    LPRECT rcParent; 
    int i, idChild; 
 
    // Retrieve the child-window identifier. Use it to set the 
    // position of the child window. 
 
    idChild = GetWindowLong(hwndChild, GWL_ID); 
 
    if (idChild == ID_FIRSTCHILD) 
        i = 0; 
    else if (idChild == ID_SECONDCHILD) 
        i = 1; 
    else 
        i = 2; 
 
    // Size and position the child window.  
 
    rcParent = (LPRECT) lParam; 
    MoveWindow(hwndChild, 
               (rcParent->right / 3) * i, 
               0, 
               rcParent->right / 3, 
               rcParent->bottom, 
               TRUE); 
 
    // Make sure the child window is visible. 
 
    ShowWindow(hwndChild, SW_SHOW); 
 
    return TRUE;
}

Eliminazione di una finestra

È possibile usare la funzione DestroyWindow per eliminare definitivamente una finestra. In genere, un'applicazione invia il messaggio di WM_CLOSE prima di eliminare una finestra, dando alla finestra la possibilità di richiedere conferma prima che la finestra venga eliminata definitivamente. Una finestra che include un menu della finestra riceve automaticamente il messaggio di WM_CLOSE quando l'utente fa clic su Chiudi dal menu della finestra. Se l'utente conferma che la finestra deve essere eliminata definitivamente, l'applicazione chiama DestroyWindow. Il sistema invia il messaggio di WM_DESTROY alla finestra dopo averlo rimosso dalla schermata. In risposta a WM_DESTROY, la finestra salva i dati e libera tutte le risorse allocate. Una finestra principale conclude l'elaborazione di WM_DESTROY chiamando la funzione PostQuitMessage per uscire dall'applicazione.

Nell'esempio seguente viene illustrato come richiedere la conferma dell'utente prima di eliminare una finestra. In risposta a WM_CLOSE, viene visualizzata una finestra di dialogo contenente i pulsanti , Noe Annulla. Se l'utente fa clic , viene chiamato DestroyWindow; in caso contrario, la finestra non viene eliminata definitivamente. Poiché l'applicazione gestisce il messaggio di WM_CLOSE, 0 viene restituito in tutti i casi. Poiché la finestra eliminata è una finestra principale, nell'esempio viene chiamato PostQuitMessage in risposta a WM_DESTROY.

case WM_CLOSE: 
 
    // Create the message box. If the user clicks 
    // the Yes button, destroy the main window. 
 
    if (MessageBox(hwnd, szConfirm, szAppName, MB_YESNOCANCEL) == IDYES) 
        DestroyWindow(hwndMain); 
    return 0; 
 
case WM_DESTROY: 
 
    // Post the WM_QUIT message to 
    // quit the application terminate. 
 
    PostQuitMessage(0); 
    return 0;

Uso di finestre a più livelli

Per fare in modo che una finestra di dialogo venga visualizzata come finestra traslucente, creare prima di tutto il dialogo come di consueto. Quindi, in WM_INITDIALOG, impostare il bit a livelli dello stile esteso della finestra e chiamare SetLayeredWindowAttributes con il valore alfa desiderato. Il codice potrebbe essere simile al seguente:

// Set WS_EX_LAYERED on this window 
SetWindowLong(hwnd, 
              GWL_EXSTYLE, 
              GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);

// Make this window 70% alpha
SetLayeredWindowAttributes(hwnd, 0, (255 * 70) / 100, LWA_ALPHA);

Si noti che il terzo parametro di SetLayeredWindowAttributes è un valore compreso tra 0 e 255, con 0 che rende la finestra completamente trasparente e 255 rendendola completamente opaca. Questo parametro simula la più versatile BLENDFUNCTION della funzione AlphaBlend.

Per rendere nuovamente questa finestra completamente opaca, rimuovere il bit di WS_EX_LAYERED chiamando SetWindowLong e quindi richiedere il ridisegno della finestra. Rimuovere il bit serve a informare il sistema che può liberare parte della memoria associata alla stratificazione e al reindirizzamento. Il codice potrebbe essere simile al seguente:

// Remove WS_EX_LAYERED from this window styles
SetWindowLong(hwnd, 
              GWL_EXSTYLE,
              GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);

// Ask the window and its children to repaint
RedrawWindow(hwnd, 
             NULL, 
             NULL, 
             RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);

Per usare finestre figlio stratificate, l'applicazione deve dichiararsi compatibile con Windows 8 nel manifesto.

Per windows 10/11, è possibile includere questo frammento di compatibilità nel relativo app.manifest per renderlo compatibile con Windows 10:

...
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows 10 GUID -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
    </application>
</compatibility>
...

Altre informazioni sulla modifica del manifesto dell'app sono disponibili qui: manifesti dell'applicazione