PDA

View Full Version : [API windows] Pulire dialog


17Qwerty71
18-02-2006, 06:56
Esiste una WinAPI per eliminare tutti i controlli appartenenti ad una dialog?
Se voglio mantenere la stessa dialog ma trasformarla con controlli diversi (tipo passare da una schermata ad un'altra) è possibile, senza dover creare elemento per elemento? :confused:


Grazie :)

kk3z
18-02-2006, 10:39
Se ho capito bene (passare da una schermata a un'altra), intendi per esempio il passaggio da un tab all'altro? Se è così, io di solito creo diversi dialog nel file risorse con uno solo con lo stile WS_VISIBLE, e li creo tutti insieme con CreateDialog. A questo punto, a ogni cambio di tab, nascondo l'ultimo dialog e mostro quello attuale.

Se non è questo quello che vuoi fare, puoi usare EnumChildWindows e chiamare DestroyWindow per ogni finestra passata. Ocio ( :D ) che EnumChildWindows ti enumera anche le finestre child delle finestre child, quindi dovresti controllare che la finestra parent (con GetParent()) sia uguale alla finestra di cui stai enumerando le finestre child.

17Qwerty71
18-02-2006, 10:51
Se ho capito bene (passare da una schermata a un'altra), intendi per esempio il passaggio da un tab all'altro? Se è così, io di solito creo diversi dialog nel file risorse con uno solo con lo stile WS_VISIBLE, e li creo tutti insieme con CreateDialog. A questo punto, a ogni cambio di tab, nascondo l'ultimo dialog e mostro quello attuale.

Se non è questo quello che vuoi fare, puoi usare EnumChildWindows e chiamare DestroyWindow per ogni finestra passata. Ocio ( :D ) che EnumChildWindows ti enumera anche le finestre child delle finestre child, quindi dovresti controllare che la finestra parent (con GetParent()) sia uguale alla finestra di cui stai enumerando le finestre child.
Cioè, paticamente vorrei che la dialog si svuotasse di tutti i suoi elementi figli e che ne ne caricasse degli altri descritti sempre in un file di risorse ;)
Un'esempino semplice semplice? :stordita:

kk3z
18-02-2006, 10:59
Prima chiarisci te, dove deve essere questo dialog? All'interno di un'altra finestra (come child), o come popup? Nel secondo caso basterebbe distruggere il primo dialog e crearne un'altro (due dialog differenti, due risorse differenti)... altrimenti, ti faccio l'esempio :)

17Qwerty71
18-02-2006, 11:05
Prima chiarisci te, dove deve essere questo dialog? All'interno di un'altra finestra (come child), o come popup? Nel secondo caso basterebbe distruggere il primo dialog e crearne un'altro (due dialog differenti, due risorse differenti)... altrimenti, ti faccio l'esempio :)
Scusa se mi sono chiarito male, cmq sono dialog popup :)
Ma come faccio a far creare la seconda dialog nelle stesse coordinate dove è stata distrutta la prima?

kk3z
19-02-2006, 17:17
Uhm, in effetti è un po' complicato :) ecco un'altra soluzione che riprende quella dei tab (nel mio primo post):
1) Crei tutti i dialog che vuoi con le stesse dimensioni, possibilmente. Tutti devono avere lo stile WS_CHILD, e quello che vuoi mostrare per primo usa WS_VISIBLE (oppure, se vuoi scegliere il primo dialog a runtime, non usare questo stile). Non hai bisogno di altri stili.
2) Crei un dialog che possa contenere i dialog creati nel punto 1), con gli stili che ti pare
3) nell'initDialog di quest'ultimo dialog, fai un CreateDialog con tutti i dialog creati nel punto 1), la cui la finestra parent deve essere il dialog creato nel punto 2)
4) a questo punto, ogni volta che vuoi cambiare dialog nascondi l'ultimo dialog e mostri quello attuale (ShowWindow(...) )

EDIT: ah, gli handle dei dialog li puoi "memorizzare" come proprietà del dialog del punto 2) usando SetProp(...)

Esempio:
HINSTANCE currentInstance = GetModuleHandle(NULL);
HWND dialog1 = CreateDialog(currentInstance , MAKEINTRESOUCE(IDD_DIALOG1), hwnd, DialogOneProc);
HWND dialog2 = CreateDialog(currentInstance , MAKEINTRESOUCE(IDD_DIALOG2), hwnd, DialogTwoProc);

SetProp(hwnd, _T("DIALOG_ONE"), (HANDLE)dialog1);
SetProp(hwnd, _T("DIALOG_TWO"), (HANDLE)dialog2);

Quando li devi richiamare:
HWND dialog1 = (HWND)GetProp(hwnd, _T("DIALOG_ONE"));
HWND dialog2 = (HWND)GetProp(hwnd, _T("DIALOG_TWO"));

Ricordati di rimuoverli tutti (per esempio nel WM_DESTROY:
RemoveProp(hwnd, _T("DIALOG_ONE"));
RemoveProp(hwnd, _T("DIALOG_TWO"));

17Qwerty71
19-02-2006, 21:53
Praticamente io dovrei fare una dialog padre che poi conterrà una alla volta una dialog figlia? :confused:

Ho fatto una prova ma sembra non funzionare :(

SetProp e GetProp a cosa servono? :confused:



Grazie :)

kk3z
20-02-2006, 10:59
Praticamente io dovrei fare una dialog padre che poi conterrà una alla volta una dialog figlia? :confused:
Esatto, ma in realtà li contiene tutti, solo che uno solo alla volta è visibile.

SetProp e GetProp a cosa servono? :confused:
SetProp/GetProp/RemoveProp sono una serie di funzioni che memorizzano le variabili in una "lista" di proprietà (da qui Prop) associata alla finestra che usi come primo parametro (ogni finestra, qualsiasi finestra può avere una lista). Ogni elemento della lista è identificato da una stringa che è il secondo parametro. E' un po' come l'ID di una finestra, con cui puoi ricavare l'handle alla finestra che ha quell'ID con GetDlgItem().
Sono una sorta di variabili membro di una classe, però la classe è una finestra.

Mostrami il tuo codice, vediamo cosa c'è che non va.

17Qwerty71
21-02-2006, 17:37
allora, praticamente ho fatto due dialog (stesse dimensioni).
Ho scritto quel codice nel WM_INITDIALOG, vado a compilare il progetto e mi aprono milioni di stesse dialog :confused:
_T non me la riconosce :confused:

kk3z
21-02-2006, 21:51
Sei sicuro che uno solo dei dialog abbia lo stile WS_VISIBLE e che tutti abbiano WM_CHILD? Devono avere o solo WS_CHILD o WS_CHILD|WS_VISIBLE. Mostrami le risorse dei tuoi dialog.

Lascia perdere _T, serve per compilare le stringhe di caratteri sia con che senza UNICODE definito. E' diventata un'abitudine :D

17Qwerty71
21-02-2006, 22:25
Sei sicuro che uno solo dei dialog abbia lo stile WS_VISIBLE e che tutti abbiano WM_CHILD? Devono avere o solo WS_CHILD o WS_CHILD|WS_VISIBLE. Mostrami le risorse dei tuoi dialog.

Lascia perdere _T, serve per compilare le stringhe di caratteri sia con che senza UNICODE definito. E' diventata un'abitudine :D

Questi sono i resource delle due dialog (la prima è la principale)
// Finestra principale
DIALOGMAIN DIALOG 10, 10, 400, 250
STYLE WS_POPUPWINDOW|WS_MINIMIZEBOX|WS_VISIBLE|WS_CHILD
CAPTION "NetBriscola"
FONT 8, "MS Sans Serif"

BEGIN
CONTROL LOGOIMG, 300, "STATIC", SS_BITMAP, 130, 0, 0, 0
GROUPBOX "Server or Client", SERVERCLIENTBOX, 25, 50, 150, 50
RADIOBUTTON "Modalità Client", CLIENTRADIOBTN, 30, 65, 120, 12
RADIOBUTTON "Modalità Server", SERVERADIOBTN, 30, 80, 120, 12
RTEXT "Host:", HOSTEXT, 220, 76, 20, 10
EDITTEXT HOSTEDIT, 245, 75, 65, 12, WS_DISABLED
CTEXT "Inserisci il tuo nome:", INSERTNAMETEXT, 0, 115, 400, 12
EDITTEXT NAMEDIT, 170, 130, 60, 12
DEFPUSHBUTTON "Comincia la Briscola", GOGAMEBTN, 150, 160, 100, 14
END


// Finestra Client
DIALOGCLIENT DIALOG 10, 10, 400, 250
STYLE WS_POPUPWINDOW|WS_MINIMIZEBOX|WS_CHILD
CAPTION "NetBriscola"
FONT 8, "MS Sans Serif"

BEGIN
END

Nella procedure della principale (in WM_INITDIALOG), ci ho scritto questo:
HINSTANCE currentInstance = GetModuleHandle(NULL);
HWND dialog1 = CreateDialog(currentInstance , MAKEINTRESOURCE(DIALOGMAIN), hwndDlg, DlgMainProc);
HWND dialog2 = CreateDialog(currentInstance , MAKEINTRESOURCE(DIALOGCLIENT), hwndDlg, DlgClientProc);

SetProp(hwndDlg, "DIALOG_ONE", (HANDLE)dialog1);
SetProp(hwndDlg, "DIALOG_TWO", (HANDLE)dialog2);
Vado a compilare e quando eseguo il programma mi si aprono le dialog all'infinito :muro:

kk3z
22-02-2006, 12:00
Devono avere o solo WS_CHILD o WS_CHILD e WS_VISIBLE.
Non è chiaro?

WS_CHILD e WS_POPUPWINDOW non possono essere usati insieme. In una finestra child non c'è una title bar, quindi non c'è:
1) nè il caption (togli la riga con CAPTION), altrimenti è come se usassi WS_CAPTION implicitamente.
2) nè il pulsante di chiusura, nè il pulsante per minimizzare nè per massimizare, quindi anche WS_MINIMIZEBOX è inutile come WS_MAXIMIZEBOX, WS_SYSMENU, WS_CAPTION.

SOLO WS_CHILD e/o WS_VISIBLE.

kk3z
22-02-2006, 12:01
// Finestra principale
DIALOGMAIN DIALOG 10, 10, 400, 250
STYLE WS_VISIBLE|WS_CHILD //solo WS_CHILD e/o WS_VISIBLE
//CAPTION "NetBriscola" //nessun caption!
FONT 8, "MS Sans Serif"

BEGIN
CONTROL LOGOIMG, 300, "STATIC", SS_BITMAP, 130, 0, 0, 0
GROUPBOX "Server or Client", SERVERCLIENTBOX, 25, 50, 150, 50
RADIOBUTTON "Modalità Client", CLIENTRADIOBTN, 30, 65, 120, 12
RADIOBUTTON "Modalità Server", SERVERADIOBTN, 30, 80, 120, 12
RTEXT "Host:", HOSTEXT, 220, 76, 20, 10
EDITTEXT HOSTEDIT, 245, 75, 65, 12, WS_DISABLED
CTEXT "Inserisci il tuo nome:", INSERTNAMETEXT, 0, 115, 400, 12
EDITTEXT NAMEDIT, 170, 130, 60, 12
DEFPUSHBUTTON "Comincia la Briscola", GOGAMEBTN, 150, 160, 100, 14
END


// Finestra Client
DIALOGCLIENT DIALOG 10, 10, 400, 250
STYLE WS_CHILD //solo WS_CHILD e/o WS_VISIBLE
//CAPTION "NetBriscola" //nessun caption!
FONT 8, "MS Sans Serif"

BEGIN
END

Tutti gli altri stili mettili alla finestra che contiene queste dialog. Idem per il caption.

17Qwerty71
22-02-2006, 15:20
Ora funziona, almeno in parte :stordita:

Allora, ho definito queste tre dialog (la prima è quella che fa da contenitore):
// Finestra Principale
DIALOGMAIN DIALOG 10, 10, 400, 250
STYLE WS_POPUPWINDOW|WS_MINIMIZEBOX|WS_VISIBLE
CAPTION "NetBriscola (Developed by Davide Giri)"
FONT 8, "MS Sans Serif"

BEGIN
END


// Finestra Start
DIALOGSTART DIALOG 10, 10, 400, 250
STYLE WS_CHILD
FONT 8, "MS Sans Serif"

BEGIN
CONTROL LOGOIMG, 300, "STATIC", SS_BITMAP, 130, 0, 0, 0
GROUPBOX "Server or Client", SERVERCLIENTBOX, 25, 50, 150, 50
RADIOBUTTON "Modalità Client", CLIENTRADIOBTN, 30, 65, 120, 12
RADIOBUTTON "Modalità Server", SERVERADIOBTN, 30, 80, 120, 12
RTEXT "Host:", HOSTEXT, 220, 76, 20, 10
EDITTEXT HOSTEDIT, 245, 75, 65, 12, WS_DISABLED
CTEXT "Inserisci il tuo nome:", INSERTNAMETEXT, 0, 115, 400, 12
EDITTEXT NAMEDIT, 170, 130, 60, 12
DEFPUSHBUTTON "Comincia la Briscola", GOGAMEBTN, 150, 160, 100, 14
END


// Finestra Client
DIALOGCLIENT DIALOG 10, 10, 400, 250
STYLE WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
CTEXT "Testo Prova", 1010, 0, 0, 400, 12
END
Nella procedure della DIALOGMAIN (in WM_INITDIALOG) vi ho inserito queste righe:
HINSTANCE currentInstance = GetModuleHandle(NULL);
hwndDlgStart = CreateDialog(currentInstance , MAKEINTRESOURCE(DIALOGSTART), hwndDlg, DlgStartProc);
hwndDlgClient = CreateDialog(currentInstance , MAKEINTRESOURCE(DIALOGCLIENT), hwndDlg, DlgClientProc);

SetProp(hwndDlg, "DIALOGSTART", (HANDLE)hwndDlgStart);
SetProp(hwndDlg, "DIALOGCLIENT", (HANDLE)hwndDlgClient);
ShowWindow(hwndDlgStart, SW_SHOW);
Dove hwndDlgStart e hwndDlgClient sono due variabili globali definite in un foglio a parte.

Fin qui tutto bene, ovvero viene mostrata la DIALOGSTART.


Poi nella procedura della DIALOGSTART (DlgStartProc) in risposta alla pressione di un determinato bottone ho inserito queste righe:
HINSTANCE currentInstance = GetModuleHandle(NULL);
hwndDlgClient = CreateDialog(currentInstance , MAKEINTRESOURCE(DIALOGCLIENT), hwndDlg, DlgClientProc);
SetProp(hwndDlg, "DIALOGCLIENT", (HANDLE)hwndDlgClient);
ShowWindow(hwndDlgStart, SW_HIDE);
ShowWindow(hwndDlgClient, SW_SHOW);
Mi nasconde la DIALOGSTART ma invece di mostrarmi poi la DIALOGCLIENT mi mostra la DIALOGMAIN :muro:


Come mai poi le dialog figlie non vengono visulizzate dall'angolo superiore sinistro della dialog padre, ma un po' rientrate? :confused:


Grazie ;)

kk3z
22-02-2006, 15:47
Non ti è ancora chiaro cosa stai facendo effettivamente. E' come se creassi due pulsanti con la stessa dimensione, uno sopra l'altro, ma uno solo di loro è visibile. Quando devi scambiarli, non hai bisogno di crearli di nuovo, devi sono nascondere quello visibile e mostrare quello nascosto. Qui:
HINSTANCE currentInstance = GetModuleHandle(NULL);
hwndDlgClient = CreateDialog(currentInstance , MAKEINTRESOURCE(DIALOGCLIENT), hwndDlg, DlgClientProc);
SetProp(hwndDlg, "DIALOGCLIENT", (HANDLE)hwndDlgClient);
ShowWindow(hwndDlgStart, SW_HIDE);
ShowWindow(hwndDlgClient, SW_SHOW);
invece crei il dialog un'altra volta, ma tu l'hai già creato nel WM_INITDIALOG del dialog principale! Capisci cosa non devi fare?
Quando vuoi scambiarli, devi solo fare:
HWND dialogCheContieneGliAltri = .... //Se sei in uno dei dialog child, usa GetParent(), altrimenti l'hwnd della procedura in cui sei.

HWND dialogChild1 = (HWND)GetProp(dialogCheContieneGliAltri, "DIALOGUNO");
HWND dialogChild2 = (HWND)GetProp(dialogCheContieneGliAltri, "DIALOGDUE");

ShowWindow(dialogChild1, SW_HIDE);
ShowWindow(dialogChild2 , SW_SHOW);

kk3z
22-02-2006, 15:53
Come mai poi le dialog figlie non vengono visulizzate dall'angolo superiore sinistro della dialog padre, ma un po' rientrate? :confused:
Questo è perchè hai usato "DIALOGSTART DIALOG 10, 10, 400, 250 " quando dichiari il dialog. La posizione del dialog child è calcolata dall'inizio della client area, non dalla title bar!
Immaginati un pulsante al posto del dialog... il pulsante non viene mica creato sulla barra del titolo (sulla non-client area), ma sotto il titolo. Stessa cosa per il dialog.
Così probabilmente è ok:
DIALOGSTART DIALOG 0,0, 400, 250
...

17Qwerty71
22-02-2006, 16:40
Questo è perchè hai usato "DIALOGSTART DIALOG 10, 10, 400, 250 " quando dichiari il dialog. La posizione del dialog child è calcolata dall'inizio della client area, non dalla title bar!
Immaginati un pulsante al posto del dialog... il pulsante non viene mica creato sulla barra del titolo (sulla non-client area), ma sotto il titolo. Stessa cosa per il dialog.
Così probabilmente è ok:
DIALOGSTART DIALOG 0,0, 400, 250
...
Gia, avevo fatto un copia e incolla senza pensarci minimamente :doh:

Ora ho corretto in questo modo:

WM_INITDIALOG della Dialog contenitore
HINSTANCE currentInstance = GetModuleHandle(NULL);
HWND hwndDlgStart = CreateDialog(currentInstance , MAKEINTRESOURCE(DIALOGSTART), hwndDlg, DlgStartProc);
HWND hwndDlgClient = CreateDialog(currentInstance , MAKEINTRESOURCE(DIALOGCLIENT), hwndDlg, DlgClientProc);

SetProp(hwndDlg, "DIALOGSTART", (HANDLE)hwndDlgStart);
SetProp(hwndDlg, "DIALOGCLIENT", (HANDLE)hwndDlgClient);
ShowWindow(hwndDlgStart, SW_SHOW);

Nella procedure della Dialog Start dove deve essere mostrata la Dialog Client
HWND hwndDlgMain = GetParent(hwndDlg);
HWND hwndDlgStart = (HWND)GetProp(hwndDlgMain, "DIALOGSTART");
HWND hwndDlgClient = (HWND)GetProp(hwndDlgMain, "DIALOGCLIENT");
ShowWindow(hwndDlgStart, SW_HIDE);
ShowWindow(hwndDlgClient, SW_SHOW);

Le variabili che identificano gli handle delle tre dialog non sono più globali.

Ma rimane lo stesso problema :muro:

kk3z
22-02-2006, 18:30
E quale sarebbe il problema? Questo:
Mi nasconde la DIALOGSTART ma invece di mostrarmi poi la DIALOGCLIENT mi mostra la DIALOGMAIN
non ha senso, dialogmain è quello principale che deve essere sempre visibile...

17Qwerty71
22-02-2006, 19:19
E quale sarebbe il problema? Questo:

non ha senso, dialogmain è quello principale che deve essere sempre visibile...
si vabbè, intendevo dire che nella sua area non vi trovo la dialog client :)

kk3z
23-02-2006, 09:04
A me sembra tutto corretto... fai un po' di controlli, controlla che sia CreateDialog che GetProp non ritornino NULL... oppure metti qualcosa dentro il DIALOGCLIENT... non mi aiuta molto il tuo "non c'è la dialog client", purtroppo non ho tutto il tuo codice sotto il naso..

17Qwerty71
02-03-2006, 21:40
Sono riuscito :)

Un'ultima cosa: io dovrei eseguire delle istruzioni appena una dialog figlia viene messa in mostra. C'è un messaggio particolare che viene inviato quando la finestra viene mostrata?

kk3z
03-03-2006, 11:16
WM_SHOWWINDOW con wParam == TRUE quando viene mostrata, wParam == FALSE quando viene nascosta.

Puoi anche farlo direttamente quando usi ShowWindow, d'altronde hai già l'handle alla dialog...