Newsgroup: it.comp.lang.c++
Titolo: Finestre di dialogo e strutture

Salve a tutta il NG!
Ho un problema, probabilmente molto stupido, ma che (ovviamente :) )
non so come si risolve. Dunque, la mia applicazione, per Win95, consta
in una finestra principale e una di dialogo. Quest'ultima deve
ricevere in ingresso i dati che devono poi riempire una struttura, che
è una variabile locale alla procedura della finestra principale. 
Ad esempio, supponete che la struttura sia
struct {
	int valore;
} Intero;
e che la procedura dalla dialog sia
BOOL CALLBACK StructDlgProc (HWND hDlg, UINT iMsg, WPARAM wParam,
LPARAM lParam) {
	switch (iMsg) {
   	case WM_INITDIALOG :
       	return TRUE ;
	case WM_COMMAND :
      		switch (LOWORD (wParam)) {
         		case IDOK:
			// Qui cosa metto? GetWindowText? E come?
         }
   	break ;
   }
   return FALSE ;
}
Domande:
1. Come leggo i valori a partire da quelli inseriti nella finestra di
dialogo? Mi è stato detto che devo usare GetWindowText, ma non so
come.
2. Come collego questi alla mia struttura? Cioè, come riporto il
valore letto nella Dialog nel valore indicato dalla struttura, che,
possibilmente, non è una variabile globale?
Grazie a tutti
Pietro

possibilmente, non č una variabile globale?
Gli approcci sono tanti; il piu` semplice e` di avere una
funzione (magari il metodo di un oggetto) che chiami
passandogli i dati; il piu` Windows-oriented e` di fare
un SendMessage di WM_COPYDATA, dopo avere
posto opportunamente i dati nella COPYDATASTRUCT
che il messaggio passa (se sono piu` di 32 bit, dovrai
passare il resto attraverso un buffer, la cui lunghezza in
byte, e l'indirizzo, sono parte di detta struttura).  Ce ne
sono, naturalmente, parecchi altri.
Alex

sono, naturalmente, parecchi altri.
Non sono molto esperto di programmazione Windows, per cui questi
passaggi non mi sono chiarissimi: ho visto la documentazione della
struttura COPYDATASTRUCT, e del messaggio WM_COPYDATA. 
Dato che la mia struttura č piů gande di 32 bit, come la scompongo?
Devo usare un buffer globale, o mi č sufficiente il puntatore? 
Che parametri devo passare su wparam e lparam in SendMessage()?
Faccio ancora confusione in questi passaggi. Grazie comunque per la
celeritŕ della risposta.
Pietro

celerità della risposta.
A volte il modo piu` semplice di rispondere a queste domande,
e mostrare ad un principiante come si usa esattamente una data
tecnologia, e` fornire un mini-esempio ridotto all'osso.  Con le
API nude di Windows, anche un "Hello World" e` abbastanza
prolisso, ahime`, comunque, ecco una versione completa del mio
solito programmino-giocattolo di esempio, che fa uso dei vari
elementi che paiono per te essere problematici in questo caso:
un dialogo modale che spedisce alla finestra genitrice dei dati
con un WM_COPYDATA attraverso la SendMessage, dati che
vengono memorizzati "localmente" alla finestra genitrice e da
essa usati per ridipingersi opportunamente.  Spero che possa
essere utile a te e ad eventuali altri interessati, fatemi sapere!
Supponiamo di avere fra le risorse nell'RC un dialogo di id
"Id_Dialogo", con bottoni IDOK e IDCANCEL, piu` un bottone
di id IDC_BUTTON1, e un edit field di id IDC_EDIT1.  Allora...:
#define STRICT
#include <windows.h>
#include "resource.h"
// dichiarazione forward della window procedure
LRESULT CALLBACK WindowProc(HWND hWnd, UINT wMsg,
    WPARAM wParam, LONG lParam);
// dichiarazione forward della dialog procedure
BOOL CALLBACK DlgProc(HWND hwndDlg, UINT uMsg,
    WPARAM wParam, LPARAM lParam);
// l'entry point di qualsiasi programma Windows:
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrev,
    LPSTR lpCmdline, int nShow)
{
    // 1. defiamo la classe per la nostra finestrella
    WNDCLASS wndClass;
    ZeroMemory(&wndClass, sizeof(wndClass));
    wndClass.hInstance     = hInstance;
    wndClass.lpfnWndProc   = WindowProc;
    wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndClass.lpszClassName = "Esempio";
    if(!RegisterClass(&wndClass))
        return FALSE;
    // 2. creiamo la finestra in questione
    HWND mywin = CreateWindow("Esempio", "Finestra d'esempio",
        WS_POPUPWINDOW|WS_CAPTION|WS_VISIBLE,  // gli stili
        10, 10, 500, 100,
        0, 0, GetModuleHandle(0), 0);
    // 2.1 inizializziamo i suoi dati
    SetWindowText(mywin, "Finestrella");
    SetWindowLong(mywin, GWL_USERDATA, 0);
    // 3. attiviamo il dialogo (modale) figlio della finestra
    int rc = DialogBox(hInstance, "Id_Dialogo", mywin, DlgProc);
    // 4. quando il dialogo esce, e` tutto finito
    return 0;
}
// la dialog procedure del nostro dialogo modale
BOOL CALLBACK
DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg) {
    // 3.1: quando viene premuto un bottone...:
    case WM_COMMAND: {
        int cmd = LOWORD(wParam);
        if(cmd == IDC_BUTTON1) {
            // se e` il Button1, raccogliamo i dati e li spediamo
            // alla nostra finestra genitrice con WM_COPYDATA
            int nChar;
            char buff[80];
            nChar = GetDlgItemText(hwndDlg, IDC_EDIT1,
                buff, 80);
            if(nChar) {
                COPYDATASTRUCT cds;
                cds.dwData = 0;
                cds.cbData = nChar;
                cds.lpData = buff;
                SendMessage(GetParent(hwndDlg), WM_COPYDATA,
                    (WPARAM)hwndDlg, (LPARAM)&cds);
            }
            return 1; // abbiamo "consumato" noi il messaggio
        } else if(cmd==IDOK || cmd==IDCANCEL) {
            // alla pressione di OK o Cancel, terminiamo
            return EndDialog(hwndDlg,cmd);
        }
                     }
    }
    // per qualsiasi altro msg, diciamo che non lo gestiamo noi:
    return 0;
}
// la window procedure della nostra finestrella
LRESULT CALLBACK
WindowProc(HWND hWnd, UINT wMsg, WPARAM wParam, LONG lParam)
{
    switch(wMsg)
    {
    case WM_COPYDATA: {
            // arrivano dati...!  Molliamo gli eventuali dati precedenti:
            COPYDATASTRUCT *pCds;
            char* pc;
            int nChar;
            LONG ld = GetWindowLong(hWnd,GWL_USERDATA);
            if(ld) free((void*)ld);
            // ci facciamo copia dei nuovi dati in arrivo:
            pCds = (COPYDATASTRUCT*)lParam;
            nChar = pCds->cbData;
            pc = (char*)malloc(nChar+1);
            memcpy(pc, pCds->lpData, nChar);
            pc[nChar] = 0;
            // ricordiamo questo puntatore, e` nostro...:
            SetWindowLong(hWnd,GWL_USERDATA,(LONG)pc);
            // garantiamo un immediato repaint
            InvalidateRect(hWnd, 0, TRUE);
            UpdateWindow(hWnd);
                      }
        break;
    case WM_PAINT: {
        HDC         hDC;
        PAINTSTRUCT ps;
        if(hDC = BeginPaint(hWnd, &ps)) {
            LONG ld = GetWindowLong(hWnd,GWL_USERDATA);
            if(ld) {
                // se abbiamo dati, li mostriamo
                char* pc = (char*)ld;
                TextOut(hDC, 10, 20, pc, lstrlen(pc));
            }
            EndPaint(hWnd, &ps);
        }
                   }
        break;
    default:
        return DefWindowProc(hWnd, wMsg, wParam, lParam);
    }
    return FALSE;
}
Alex