Newsgroup: it.comp.lang.c++
Titolo: Aiuto.... problemi con UpdateCommandUI

Utilizzo il gestore CcmdUI per la gestione (enable/disable) dei menu e dei
buttons nella tool-bar, ma in una routine piuttosto impegnativa e lunga di
calcolo (in pratica un loop), non viene piu' gestito l'UpdateCcmdUI, cioe'
le voci dei menu vengono gestite, ma i buttons non cambiano di stato(
dovrebbero diventare disabilitati).
Mi e' stato detto che forse bisogna 'dispacciare i messaggi' ma non so come
fare.
Grazie.

Ciao Paolo,
non so se questo risolve i tuoi problemi, comunque riporto di seguito una
routine che svuota la coda dei messaggi, inviando questi alle opportune
finestre e poi ritorna, se vuoi la puoi chaimare tranquillamente in un loop.
void emptyQueue()
{
 MSG msg;
 while (::PeekMessage(&msg, null, 0, 0, PM_REMOVE | PM_NOYIELD))
 {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
}
ciao, Franco.
Franco Torrini - Software Engineer - 
f.to...@virtuart.it
VIRTUART - C.C.D. Creative Computer Design S.p.A.
Via di Quarto Annunziata, 80/b - 00189 Rome, Italy
Tel. 
+39 06 33076638
 - Fax. 
+39 06 33076670
Paolo wrote in message <01be0957$6f1674e0$5a030e82@stcncaoapca4>...


fare.
Se, come sembra, stai utilizzando le MFC, puoi provare a
chiamare il membro PumpMessage dell'oggetto application;
questo dovrebbe "dispacciare i messaggi".  PumpMessage
non e` documentata, ma puoi guardare gli header di MFC,
e anche i sorgenti, per i dettagli.
Tuttavia, mi pare che un loop del genere, senza dispatch di
messaggi, dovrebbe avere ben altri problemi, ben piu`
visibili; per esempio, se non arrivano i WM_REPAINT,
allora la tua finestra, se viene ad esempio coperta da
un'altra e poi nuovamente scoperta, non dovrebbe potersi
"ridipingere".  Lo osservi, questo sintomo clamoroso, o
no?  Se si`, allora forse puo` servirti garantire il dispatch
dei messaggi ogni tanto (garantisciti, mi raccomando, di
essere correttamente "rientrante", ad esempio nelle
funzioni che gestiscono il repaint/redraw; se il tuo loop
sta modificando una struttura dati, dalla quale il repaint
dipende, bisogna che il codice di paint possa saperlo da
un qualche opportuno flag, e prendere azioni alternative
in queste situazioni); se no, e` piu` probabile che sia
qualcosa d'altro.
Se vedi che e`, in effetti, un problema di mancato dispatch,
e per qualche ragione non puoi o non vuoi ristrutturare la
tua applicazione in modo da evitare simili "piantamenti"
eccessivi (dividendo il tuo grosso calcolo in "fettine" da
eseguire OnIdle, o delegandolo a un thread separato cosi`
da potere rimanere responsivo ai messaggi Windows nel
tuo thread principale), allora puoi almeno cercare di
fornire all'utente un feedback migliore e piu` chiaro
relativo al fatto che la tua applicazione e` "nel pallone
per calcoli in corso"; con opportuni override della gestione
di WM_SETCURSOR puoi ad esempio mostrare una
"clessidra che si volta ogni tanto", con override di
PreTranslateMessage dell'applicazione bloccare e
buttare via messaggi di mouse e tastiera.  Non e` una
grande soluzione, rispetto ad una applicazione che resta
normalmente responsiva alle azioni dell'utente anche
quando sta facendo calcoli impegnativi, ma comunque
e` meglio che niente.
Alex

finestre e poi ritorna, se vuoi la puoi chaimare tranquillamente in un loop.
Purtroppo, questa routine che riporti non ha tutte le varie
"raffinatezze" della PumpMessage dell'oggetto applicazione
di MFC (chiamate opportune di PreTranslateMessage, ecc),
per cui, usandola, si possono verificare varie "anomalie" in
MFC, per tutte quelle funzionalita` che dipendono da
PreTranslateMessage e soci.
Adesso che ci penso, la OnUpdateCommandMessage
mi pare che venga proprio chiamata come parte della
OnIdle, per cui, se la OnIdle non e` correttamente
"incastrata" al suo giusto posto del loop degli eventi
(e in questa routine non lo sarebbe), e` possibile che,
pur svuotando in effetti la coda dei messaggi, questa
non possa purtroppo servire per permettergli il corretto
aggiornamento dello stato enabled/disabled dei menu
item (ma, come ho gia` accennato, questo sarebbe solo
uno di tanti problemi se l'applicazione effettivamente non
dispatchasse messaggi).
Alex

Effettivamente si dovrebbe aggiungere la chiamata a PreTranslateMessage()
nella routine precedentemente descritta, per ottenere la gestione degli
acceleratori, comportamento di default, oltre che delle nostre
implementazioni.
Devo pero' aggiungere, se la OnUpdateCommandMessage() e' chiamata nella
OnIdle(), ed e' cosi', chiamare direttamente PumpMessage() non risolverebbe
il problema, dato che questa non chiama ne l'una ne l'altra. Run() e' la
funzione che si occupa della OnIdle(), ma non possiamo chiamarla
direttamente, in quanto questa ritornerebbe solo dopo aver ricevuto il
WM_QUIT.
Una soluzione, se ci interessa chiamare la OnIdle(), potrebbe essere
l'inserimento di quest'ultima nella "routine", insieme alla
PreTranslateMessage(), diciamo una cosa del genere:
void emptyQueue()
{
    MSG msg;
    while (::PeekMessage(&msg, null, 0, 0, PM_REMOVE | PM_NOYIELD))
    {
        if (!PreTranslateMessage(&msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    OnIdle();
}
ciao, Franco.
Franco Torrini - Software Engineer - 
f.to...@virtuart.it
VIRTUART - C.C.D. Creative Computer Design S.p.A.
Via di Quarto Annunziata, 80/b - 00189 Rome, Italy
Tel. 
+39 06 33076638
 - Fax. 
+39 06 33076670
Alex Martelli wrote in message ...
