PDA

Visualizza la versione completa : [C++] Passaggio di dati da finestra di dialogo a finestra "parent"


MRj92
15-08-2007, 14:10
eccomi di nuovo!

la mia situazione è questa:

ho una finestra (la principale), e un dialog modale che richiede username,password e un numero. Il dialog elabora se la passord è giusta e poi dovrebbe passare l'username alla main window. Ma come effettuare questo passaggio?

:confused:

grazie a tutti! :ciauz:

andbin
15-08-2007, 15:46
Originariamente inviato da MRj92
ho una finestra (la principale), e un dialog modale che richiede username,password e un numero. Il dialog elabora se la passord è giusta e poi dovrebbe passare l'username alla main window. Ma come effettuare questo passaggio?Ci sono diverse soluzioni, che si differenziano principalmente per quanto riguarda eleganza/design/semplicità.

Per passare lo username puoi quindi:

A) Usare una variabile globale. Tanto hai detto che è una dialog "modale", pertanto puoi avere solo una dialog di login per volta e la funzione DialogBox() è "bloccante", termina solo a seguito di una EndDialog nella dialog-procedure.
Questa è la soluzione più "sporca" ma anche la più immediata.

B) Invece di usare DialogBox() si può usare DialogBoxParam() che ha un parametro in più di tipo LPARAM per passare un valore "custom" qualunque. Si può passare ad esempio un puntatore ad una struttura. Il valore LPARAM dwInitParam viene passato solamente al ricevimento del messaggio WM_INITDIALOG e in genere la cosa migliore per "tenerlo vivo" è: 1) usare SetWindowLongPtr/GetWindowLongPtr per avere il valore nell'offset DWLP_USER oppure 2) usare SetProp/GetProp per avere il valore in una property con nome associata alla finestra.
Leggere attentamente la documentazione delle funzioni menzionate (quest'ultima frase sembra quella che si legge sui medicinali :D ).

C) Inviare alla finestra padre (della dialog box) un messaggio custom. Questa sarebbe una comunicazione asincrona, quindi è ovviamente da valutare. I messaggi custom partono da WM_USER in poi.

Altre soluzioni sarebbero dei "mix", ad esempio impostare una property sulla finestra padre che contiene un puntatore alla stringa con lo username. Non è il massimo..... (oddio che robe mi vengono in mente in pieno Agosto....)

Personalmente, tutte quelle volte che ho dovuto restituire più informazioni di tipo eterogeneo da una dialog-box modale, ho usato il metodo B) definendo una apposita struttura.

MRj92
15-08-2007, 17:39
A) Usare una variabile globale. Tanto hai detto che è una dialog "modale", pertanto puoi avere solo una dialog di login per volta e la funzione DialogBox() è "bloccante", termina solo a seguito di una EndDialog nella dialog-procedure.
Questa è la soluzione più "sporca" ma anche la più immediata.

ci avevo pensato anch'io però non mi piace tanto... come hai detto tu è la più "sporca".


B) Invece di usare DialogBox() si può usare DialogBoxParam() che ha un parametro in più di tipo LPARAM per passare un valore "custom" qualunque. Si può passare ad esempio un puntatore ad una struttura. Il valore LPARAM dwInitParam viene passato solamente al ricevimento del messaggio WM_INITDIALOG e in genere la cosa migliore per "tenerlo vivo" è: 1) usare SetWindowLongPtr/GetWindowLongPtr per avere il valore nell'offset DWLP_USER oppure 2) usare SetProp/GetProp per avere il valore in una property con nome associata alla finestra.
Leggere attentamente la documentazione delle funzioni menzionate (quest'ultima frase sembra quella che si legge sui medicinali ).

:confused: non ci ho capito molto... soprattutto dal "tenerlo vivo" in poi... :D


C) Inviare alla finestra padre (della dialog box) un messaggio custom. Questa sarebbe una comunicazione asincrona, quindi è ovviamente da valutare. I messaggi custom partono da WM_USER in poi.

mi ispira assai!! :mame: potresti approfondire un po'?



.... (oddio che robe mi vengono in mente in pieno Agosto....)

Eh si! il caldo da alla testa!
:D


abbi pazienza perchè sono un po' duro a capire le cose!

grazie ancora una volta per la disponibilità

andbin
15-08-2007, 19:52
Originariamente inviato da MRj92
ci avevo pensato anch'io però non mi piace tanto... come hai detto tu è la più "sporca".In certi casi l'ho usata. Tanto la programmazione a livello di API Win32 è tutto tranne che elegante/pulita/lineare....


Originariamente inviato da MRj92
:confused: non ci ho capito molto... soprattutto dal "tenerlo vivo" in poi... :D Significa sostanzialmente:

a) Definire ad esempio una struttura:

typedef struct
{
CHAR username[30];
} LOGIN, *PLOGIN;

b) Quando devi aprire la dialog-box si usa DialogBoxParam e si passa l'indirizzo alla struttura:

LOGIN login;
DialogBoxParam (hInstance, ........, DialogProc, (LPARAM) &login);
Nota che 'login' va anche bene se è una variabile locale. È sufficiente che esista fino a quando ti serve. Quando DialogBoxParam termina farai qualcosa con quel campo username.

c) In risposta a WM_INITDIALOG:

case WM_INITDIALOG:
SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR) lParam);
return TRUE;
In questo modo lParam (che contiene il puntatore alla struttura) è salvato in una area riservata e associata alla finestra). Così è sempre disponibile, anche successivamente quando ricevi altri messaggi.

d) A seguito di una autenticazione con successo, dovrai chiudere la dialog e restituire lo username:

....
PLOGIN plogin;
plogin = (PLOGIN) GetWindowLongPtr (hDlg, DWLP_USER);
GetDlgItemText (hDlg, IDC_USERNAME, plogin->username, sizeof (plogin->username));
EndDialog (hDlg, 1);
....

Come vedi nulla di trascendentale. Io ho usato una struttura perché in genere è comoda, se si dovessero aggiungere altri campi i vari step fatti non cambiano.


Originariamente inviato da MRj92
mi ispira assai!! :mame: potresti approfondire un po'?I messaggi custom specifici per una applicazione partono da WM_USER in poi, nel tuo caso ad esempio:


#define WM_LOGINSUCCESS (WM_USER+0)

Quando determini che la autenticazione ha avuto successo fai:


char username[30];

GetDlgItemText (hDlg, IDC_USERNAME, username, sizeof (username));
SendMessage (GetParent (hDlg), WM_LOGINSUCCESS, 0, (LPARAM)(LPSTR) username);

La window-procedure del padre della dialog riceverà il messaggio:

case WM_LOGINSUCCESS:
{
LPSTR lpszUsername = (LPSTR) lParam;

.....fai quello che vuoi....
return 0;
}
Nota che SendMessage è sincrona, chiama la window-procedure e ritorna solo quando la w.p. ritorna. Questo vuol dire che se anche la variabile 'username' è locale, "vive" sicuramente fino a quando la SendMessage ritorna, che è ciò che serve.

MRj92
16-08-2007, 10:02
#define WM_LOGINSUCCESS (WM_USER+0)


ma scusa WM_USER+o non è uguale a WM_USER??

comunque uso i custom messages.

Posso passare anche una struttura anzichè solo una stringa?

Grazie mille!
:zizi:

andbin
16-08-2007, 11:08
Originariamente inviato da MRj92


#define WM_LOGINSUCCESS (WM_USER+0)


ma scusa WM_USER+o non è uguale a WM_USER??Sì ma volevo solo evidenziare che puoi usare qualunque valore da WM_USER in poi.


Originariamente inviato da MRj92
Posso passare anche una struttura anzichè solo una stringa?Certamente.

MRj92
16-08-2007, 11:54
concetto afferrato! :D alla promissa andbin!

grazie ancora

Loading