PDA

Visualizza versione completa : [HELP] prob con i dialoghi!


tobia54
17-06-2003, 05.50.47
Salve a tutti!
Sono nuovo, colgo l'occasione del mio primo :cool: thread per salutarvi!

vado al sodo....

Sto scrivendo un prog per impararmi a programmare per win!
Il programma gestisce le ordinazioni di un ipotetico ristorante.
Sulla schermata principale ci sono i tavoli(bottoni).
Cliccando su un tavolo appare in una DialogBox l'elenco delle ordinazioni con l'ora e una serie di operazioni che si possono effettuare.
Sto programmando in c++ con il compilatore della borland bcc55.

Il mio problema e' il seguente:
se uso il prog con 5/6 ordini per tavolo tutto funziona correttamente,
ma come gli ordini diventano 8/9 a lungo andare le DialogBox non vengono piu' disegnate correttamente,il menu diventa nero facendo apparire le voci solo al passaggio del mouse, le icone non vengono visualizzate e cosi' via.
Se riduco il prog a icona e lo riapro la schermata principale e' visualizzata correttamente ma le DialogBox no! e cosi' il menu'(nero)!
Inoltre pur chiudendo il prog lo stesso problema si presenta con iExplor,Word,.....!!!!
Qualcuno sa darmi qualche indizio?
Non riesco a capire cosa succede!
grazie mille

P8257 WebMaster
17-06-2003, 10.33.18
Ciao,
Può dipendere praticamente da tuto .. dall'architettura del sorgente.. sarebbe utile se postassi almeno il coidce che si occupa di visualizzare le dialog.

Probabilmente viene dimensionata qualche variabile o vettore a grandezze superiori rispetto alla memoria allocata e questo influenza (nel caso specifico) i metodi di visualizzazione comuni.

Tali metodi conservano quindi condizioni di overflow che si ripresentano in altri applicativi nella sessione corrente.

Bye :cool:

tobia54
17-06-2003, 16.54.12
Posto la funzione che viene chiamata da WM_INITDIALOG:
(abbastanza disordinata! :( spero ci capiate qualcosa!)

bool Init_Dialog(HWND hWndDlg,UINT message,WPARAM wParam,LPARAM lParam) {
//it_MG punta all'ordine del tavolo!!! VARIABILE GLOBALE

bool ris = false;

ctrl.erase(ctrl.begin(),ctrl.end());
vLB.erase(vLB.begin(),vLB.end());
mis.erase(mis.begin(),mis.end());

string NTavolo; //Numero del Tavolo
//Output nome tavolo
int ntavolo = (*it_MG).first;
if(ntavolo <= 3) {
if(ntavolo==0) {
NTavolo= " Cassa ";
}
if(ntavolo == 1) {
NTavolo = " Bar ";
}
if(ntavolo == 2) {
NTavolo = " Cucina ";
}
if(ntavolo == 3) {
NTavolo = "Asporto";
}
CreateWindow(TEXT("static"),TEXT(NTavolo.c_str()), WS_VISIBLE | WS_CHILD | SS_LEFT ,30,20,60,30,hWndDlg,(HMENU)IDC_STATIC,(HINSTANCE) GetWindowLong(hWndDlg,GWL_HINSTANCE),NULL);
}
else {
ntavolo -=3; //per offset tra nome tavolo e numerazione array
NTavolo = "Tavolo "+ converti(ntavolo);
CreateWindow(TEXT("static"),TEXT(NTavolo.c_str()), WS_VISIBLE | WS_CHILD | SS_LEFT ,30,20,70,30,hWndDlg,(HMENU)IDC_STATIC,(HINSTANCE) GetWindowLong(hWndDlg,GWL_HINSTANCE),NULL);

}

string idMenu;
string Numero; //quantita'
string con; //con ingredienti
string senza; //senza ingredienti
string riga; //riga da inserire nella ListBox dell'ordine
string nome; //nome del prodotto
string prezzo; //prezzo del singolo

vector<voce> vv; //vettore appoggio per un ordine
vector<int> controlli; //vettore con gli id dei controlli,viene inserito in ctrl

int k = 5000; //id dei controlli(partono da 5000)
int szOrd; //size ord
int szVord; //size vo
int indice = 0; //indice per l'inserimento nella ListBox e il recupero

//variabili per disegnare le varie istanze degli ordini
int x,y,h,l; //h=altezza,l=larghezza;
int xb; //x-bottoni;
x = 220;
y = 25;
h = 150;
l = 230;

//Totali
double TO = 0; //Totale Ordine
double TT = 0; //Totale Tavolo
string aTO,aTT; //appoggio per la conversione double->string

//testo dei vari ordini:
string oraArrivo = ""; //ora di arrivo ordine
string ToA = "delle ore ";
string V = "";
string ordine ="";
string o="Ordine: ";
int NO = 1; //Numero Ordine

//prelevo gli ordini dalla mappa:
vo.erase(vo.begin(),vo.end());
vo = (*it_MG).second;
szVord = vo.size();


if(szVord > 0) {
ris = true;
}
else {
return ris;
}

//stampo gli ordini sulla finsetra:
for(int i = 0;i<szVord;i++) {
vv = vo[i].get_ordine();
TO = vo[i].totale();
TT += TO;
aTO = converti(TO);//double -> string

//inizializzo il nome della sotto-finestra del singolo ordine
ordine = o + converti(NO);
NO++;
//e l'ora in cui l'ordine e' pervenuto
oraArrivo = vo[i].get_ora();
V = ToA + oraArrivo;

//disegno la sotto-finestra per l'ordine
CreateWindow(TEXT("button"),TEXT(ordine.c_str()), WS_VISIBLE | WS_CHILD | SS_LEFT | BS_GROUPBOX,10,x,530,250,hWndDlg,(HMENU)IDC_STATIC ,(HINSTANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE),N ULL);
x+=20;
CreateWindow(TEXT("static"),TEXT(V.c_str()),WS_VISIBLE | WS_CHILD | SS_LEFT, 20,x,200,30,hWndDlg,(HMENU)IDC_STATIC,(HINSTANCE)G etWindowLong(hWndDlg,GWL_HINSTANCE),NULL);
ordine = "";
V = "";
x = x+30;
CreateWindow(TEXT("static"),TEXT("Totale Ordine:"), WS_VISIBLE | WS_CHILD | SS_LEFT,y,x,110,30,hWndDlg,(HMENU)IDC_STATIC,(HINS TANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE),NULL);
y = 130;
CreateWindow(TEXT("listbox"),NULL,WS_VISIBLE | WS_CHILD | WS_BORDER,y,x-4,50,20,hWndDlg,(HMENU) k,(HINSTANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE), NULL);
SendDlgItemMessage(hWndDlg,k,LB_ADDSTRING,0,(LPARA M)aTO.c_str());//visualizza il totale dell'ordine
x=x+25;
y=25;
controlli.push_back(k);
k++;
CreateWindow(TEXT("listbox"),NULL,LBS_STANDARD | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER,y,x,l,h,hWndDlg,(HMENU)k,(HINSTANCE)GetW indowLong(hWndDlg,GWL_HINSTANCE),NULL);
y = 270;
xb = x;
controlli.push_back(k);
k++;
CreateWindow(TEXT("button"),TEXT("Aggiungi voce"),BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,y,xb,110,30,hWndDlg,(HMENU) k,(HINSTANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE), NULL);
xb=xb+40;
controlli.push_back(k);
k++;
CreateWindow(TEXT("button"),TEXT("Modifica voce"),BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,y,xb,110,30,hWndDlg,(HMENU) k,(HINSTANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE), NULL);
xb=xb+40;
controlli.push_back(k);
k++;
CreateWindow(TEXT("button"),TEXT("Cancella voce"),BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,y,xb,110,30,hWndDlg,(HMENU) k,(HINSTANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE), NULL);
xb=x;
y = 400;
controlli.push_back(k);
k++;
CreateWindow(TEXT("button"),TEXT("Stampa voce"),BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,y,xb,110,30,hWndDlg,(HMENU) k,(HINSTANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE), NULL);
xb=xb+40;
controlli.push_back(k);
k++;
CreateWindow(TEXT("button"),TEXT("Cancella Ordine"),BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,y,xb,110,30,hWndDlg,(HMENU) k,(HINSTANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE), NULL);
xb=xb+40;
controlli.push_back(k);
k++;
CreateWindow(TEXT("button"),TEXT("Stampa Ordine"),BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD,y,xb,110,30,hWndDlg,(HMENU) k,(HINSTANCE)GetWindowLong(hWndDlg,GWL_HINSTANCE), NULL);
controlli.push_back(k);
k++;

ctrl.push_back(controlli);
x = x+200;
xb = x;
y=25;

szOrd = vv.size();
//stampo le voci dell'ordine:
for(int kk = 0; kk < szOrd; kk++) {
idMenu=vv[kk].id;
Numero = vv[kk].get_numero();
prezzo = MENU.get_prezzo(idMenu);
//con = vv[k].con;
//senza = vv[k].senza;
nome = MENU.get_nome(idMenu);
riga = ordina(Numero,nome,prezzo);
//riga = Numero+" "+nome+" "+prezzo;
mis.insert(M_Value(kk,idMenu));
SendDlgItemMessage(hWndDlg,controlli[1],LB_INSERTSTRING,(WPARAM)kk,(LPARAM)riga.c_str());
}
vLB.push_back(mis);
mis.erase(mis.begin(),mis.end());
controlli.erase(controlli.begin(),controlli.end()) ;
}
//visualizzo il totale del tavolo
aTT =converti(TT);
SendDlgItemMessage(hWndDlg,IDC_TOTALE_TAVOLO,LB_AD DSTRING,0,(LPARAM)aTT.c_str());
return ris;
}

Ho provato ad eliminare dal Dialogo il colore di sfondo, le scroll bar,le icone, lasciando "l'essenziale" ma il problema rimane!!
grazie mille per l'aiuto

P8257 WebMaster
17-06-2003, 17.20.43
cazz.. ripostala col tag CODE... almeno mantiene le tabulazioni...

Bye :cool:

tobia54
17-06-2003, 18.10.52
Originariamente inviato da P8257 WebMaster
cazz.. ripostala col tag CODE... almeno mantiene le tabulazioni...

Bye :cool:

Pure te c'hai ragione!!! :inn:
ho editato! :D

ps:
sto continuando a cercare il prob, hai ragione, più ci sono ordini su un dialogo prima si verifica il prob!!
continuo a cercare!
grazie mille!

pholcus
17-06-2003, 20.53.27
Ma lo fa solo sul tuo PC o anche su altri?

tobia54
17-06-2003, 21.28.02
anche su altri! :(

P8257 WebMaster
18-06-2003, 13.11.16
Mmmm.. una bella gatta da pelare ..
hai provato ad aumentare le dimensioni della dialog .. ?

Un alro test interessante sarebbe provare a far creare una dialog per ogni singola ordinazione .. per verificare se il problema è correlato alla visualizzazione o se al raggiungimento di un numero di ordinazioni preciso si verifica qualche overflow...

Bye :cool:

tobia54
18-06-2003, 16.32.50
Ho provato a far girare il prog su un portatile con win98 (io sto usando xp), il problema si verifica come provo ad aprire il Dialogo!! :(
Le dimensioni del Dialogo sono 290,280 e mi da anche un prob con la scroll bar(non scende oltre l'ottava ordinazione!) e' possibile che i due problemi siano correlati? NB: se commento il codice della scroll bar il problema si presenta ugualmente!(spero ti dica qualcosa! :D, io sto impazzendo! :wall: )
Continuo a cercare, come trovo qualcosa ti faccio sapere!!!
Grazie

tobia54
18-06-2003, 16.40.14
e' possibile che il prob sia in questa funzione?


HWND RicreaWindow(HWND hwnd,LPCTSTR IDD,DLGPROC dlg) {
HWND hWnd=GetParent(hwnd);
EndDialog(hwnd,true);
DialogBox(hInst,IDD,hWnd,dlg);
}


La chiamo ogni volta che si modifica un ordine per ridisegnare l'intero Dialogo!
Ad esempio:


case IDC_AGGIUNGI_VOCE:
DialogBox(hInst,(LPCTSTR)ID_AGGIUNGI_VOCE,hWndDlg, (DLGPROC)AggiungiVoce);
RicreaWindow(hWndDlg,(LPCTSTR)IDD_TAVOLO,(DLGPROC) Tavolo);
return true;
break;

tobia54
19-06-2003, 03.01.49
Altro indizio, usando GetLastError() dopo il problema mi da error 6,
handle non valido, il che mi fa pensare che sia proprio la mia "cara" funzione RicreaWindow a creare prob,non so!! :crying:

Continuo a postare quello che trovo,spero prima o poi di darvi la soluzione!

ps:
ma perche' ho preso ing informatica????????? asd

LoryOne
19-06-2003, 09.08.09
Originariamente inviato da tobia54

ps:
ma perche' ho preso ing informatica????????? asd

Perchè nella vita se ne fanno tanti di sbagli :D :D :D

Il problema della gestione degli handle hwnd è particolarmente rilevante nel subclassing delle finestre.

Può darsi che tu abbia centrato l'obiettivo.

Ciao :)

P8257 WebMaster
19-06-2003, 12.07.42
Originariamente inviato da LoryOne

Può darsi che tu abbia centrato l'obiettivo.

Ciao :)

.. Lo credo anch'io .. la questione mi interessa, sto facendo delle prove anch'io...

Bye :cool:

tobia54
19-06-2003, 16.49.20
grazie per l'aiuto!

Inizio a pensare che il prob sia nella chiamata
EndDialog(hwnd,true)!
Quello che sto cercando di capire e':
Questa funzione ritorna true alla WinProc principale ma ,se io chiamo subito dopo DialogBox
per ricreare la finestra, true dove va a finire?
Viene forse salvato in qualche "stack" di win che si "satura" (gergo chitarresco! :))?
Dovrei allora fare in modo che ritorni il controllo alla WinProc per farle gestire il valore di ritorno e poi ricreare il Dialogo?
Le mie sono solo illazioni!
La verita' e' che non ho idea! ghghgh

LoryOne
19-06-2003, 17.36.18
L'handle non è altro che un numero (long) identificativo della finestra.
Quando questa viene chiusa (non nascosta), l'handle viene automaticamente distrutto (destroyed)
Qualunque chiamata alle API di Windows (che esse siano in VB, in Delphi, o in C++) che apporti una qualsiasi modifica alle proprietà di una finestra, deve necessariamente fare riferimento al suo handle (hWnd significa HandleWindow).
Particolare rilevanza ha il DC (Device Context) per quanto riguarda il contesto grafico all'interno della finestra e quindi alla creazione/modifica in run-time degli oggetti in essa contenuti.

Se una finestra (ma anche un messagebox o un qualunque altro oggetto identificabile in modo univoco dal suo handle) viene scaricata dalla memoria, la sua "ricreazione" causarà la creazione di un nuovo handle di valore differente dall'originario.

In linea generale, è buona norma controllare che l'handle che viene passato ad una funzione che agisce in qualche modo su una finestra sia effettivamente quello che identifica la finestra in questione.
L'utilizzo di una variabile pubblica può esserti di aiuto.

L'handle è univoco e non avrai mai più oggetti che condividono lo stesso handle.

Ciao :)

P8257 WebMaster
19-06-2003, 18.44.46
Qualsiasi valore, se non gestito o non memorizzato in un'entità specifica, viene perso .. il suo destino sta quindi al comportamento e all'architettura del linguaggio stesso...

Se fossimo in ambiente Java (o .net) non avresti di che preoccuparti perchè il "garbage collector" darebbe una bella spazzata alla memoria .. per quanto riguarda C o C++ invece, ci devi pensare tu .. in questo caso però non vedo come un buleano possa arrivare a saturare (chitarristicamente parlando ;)) un buffer .. però non è da escludere .. al limite fallo andare su una variabile.

Farò anch'io alcuni tentativi con una cosa simile, lo spunto di Lory mi ha fatto venire in mente che...

Bye :cool:

tobia54
20-06-2003, 03.20.44
che .....? :)
fammi sapere!

P8257 WebMaster
20-06-2003, 10.16.45
tobia54 ha scritto:
che .....? :)
fammi sapere!

Si si .. arrivo arrivo .. :) preferisco verificare prima di sparare eventuali boiate .. :D

Bye :cool:

tobia54
21-06-2003, 20.21.22
Sto impazzendo! :)

Allora altri indizzi...
Ho cambiato la funzione RicreaWindow sostituendo EndDialog con DestroyWindow e le cose sembrano funzionare.
Il prob si e' spostato a quando il controllo torna alla finestra principale, rilevo infatti l'errore 1400, window handle non valido, se riapro il dialogo e lo richiudo subito dopo l'errore diventa l'87,parametro non valido!
(e cosi' via ciclicamente 1400,87,1400,87,...)
Per il resto tutto sembra funzionare!
Questi errori li catturo subito dopo la chiamata DialogBox(...) nella WinProc principale.

Mi viene da pensare quindi che DestroyWindow non risolve il prob ma lo aggira, avendo un comportamento più "brutale" fa in modo che non vada in overflow alcun buffer!!
A me cmq piu' che risolvere mi interessa capire! :)
Non ho capito! -.-'

LoryOne
23-06-2003, 10.21.16
L'interfaccia è SDI o MDI ?

tobia54
24-06-2003, 17.06.16
SDI

P8257 WebMaster
27-06-2003, 01.01.16
Non ho dimenticato .. ancora un pochino di pazienza, raccolgo documentazione.

Bye :cool:

tobia54
27-06-2003, 05.15.26
aspetto! :)

P8257 WebMaster
08-07-2003, 10.30.05
Eccomi qua,
dunque, innanzitutto chiedo scusa a "Tobia54" per l'allucinante ritardo con cui rispondo a questo thread ..

Personalmente ho eseguito diverse prove e tentativi simili alla tua traccia scrivendo semplici interfacce di gestione con contatori simili ai tuoi numeri di tavolo e alle tue ordinazioni .. mio malgrado però (certe volte le cose funzionano...) non ho sperimentato e potuto riprodurre la strana condizione di visualizzazione che hai citato nel thread. Ho fatto quindi una ricerca e provato alcune combinazioni alternative per creare e gestire gli handlers delle finestre .. la cosa che mi viene spontaneo pensare in primis è che si tratti di una gestione errata degli stessi handlers o qualche overflow interno dovuto alla grandezza della finestra, alle sue proprietà o alla memoria allocata che essa richiede.

L'unico test che mi resta da effettuare (e che farò probabilmente oggi) è tentare di sovraccaricare "artificialmente" la memoria senza scaricarla all'apertra o chiusura delle finestre .. sono pignolo su questa teoria .. ;) .. ti chiedo ancora scusa per l'enorme ritardo con cui scrivo questa risposta e spero che tu nel frattemop sia giunto ad una soluzione migliore ella mia .. :)

Bye :cool: