Newsgroup: it.comp.lang.c++
Titolo: Cancellare gli item di un menu con DeleteMenu

Devo sostituire in un programma, a runtime, il menu di risorsa con un menu
realizzato con CMenu.
Per togliere il menu precedente utilizzo questo metodo:
CMenu *pMenu = GetMenu();
for(int i =0; i <= int(pMenu->GetMenuItemCount( ));i++)
     pMenu->DeleteMenu(i,MF_BYPOSITION);
Ci sono soluzioni migliori?
Però delle 10 voci di menu me ne toglie solo la metà, non capisco il perchè.
Avete qualche idea?
Ciao
Terenzio



...


     pMenu->DeleteMenu(i,MF_BYPOSITION);
...e fallirebbe ancora, perche` ogni DeleteMenu
implicitamente "rinumera" tutto.  Supponi che gli
item siano all'inizio A, B, C...; cancelli lo zeresimo,
questo lascia B, C, ...; poi incrementi i e vai a
cancellare l'1-esimo -- che ora e` _C_ -- B non
lo cancella piu` nessuno!!!  Esattamente come
nel loop iniziale.
Per cancellare, conoscendone i numeri-indice, elementi
da una struttura dati che si "autoriordina" (e ce ne
sono tante, tipo gli std::vector<> dello standard C++),
il trucco e` farlo DALL'ALTO VERSO IL BASSO:
    for(i=maxindex-1; i>=0; --i)
        cancella i-esimo elemento;
In questo modo, la cancellazione di un item non tocca
minimamente i numeri-indice degli item ancora da
cancellare.
Alex

...


 
Io userei il while invece del for e come condizione metterei proprio la
funzione GetMenuItemCount ed inoltre il DeleteMenu lo userei sempre con la
posizione 0 visto che tanto cancellando la prima posizione, tutti gli altri
elementi vengono "shiftati" di una posizione.
Quindi si potrebbe scrivere cosi':
CMenu *pMenu = GetMenu();
while (GetMenuItemCount())
     pMenu->DeleteMenu(0, MF_BYPOSITION);
Ciao.
-- 
Jo Parrello - OWL/C++ Programmer (
jopa...@tin.it
)
http://space.tin.it/computer/giparrel

     pMenu->DeleteMenu(0, MF_BYPOSITION);
tali da renderlo interessante e degno di considerazione nonostante
tutti gli evidenti svantaggi che presenta.
Alex

 tutti gli evidenti svantaggi che presenta.
Noto con piacere che hai una buona base di Assembler alle spalle,
altrimenti non ti sarebbe uscito un algoritmo ottimizzato sia per
dimensione che per velocita' (quindi e' valsa la pena stuzzicarti!!). Il
tuo codice e' ottimo, anche se, per sicurezza, andrebbe valutato il valore
di ritorno del metodo DeleteMenu. A tal proposito essendo il tuo un
semplice for, quindi a priori si sa gia' quanti cicli  eseguira', anche se
il valore di ritorno di DeleteMenu e' zero, il ciclo va avanti, magari
senza cancellare neanche un item. Il mio invece va in loop, poiche' il
valore corrente e' valutato nel while e siccome rimane sempre quello...,
lascio ai posteri l'ardua sentenza. Come vedi basta cambiare una linea e
scegliere un altro tipo di approccio per mandare a scatafascio il lavoro di
una vita. Chissa', se dovremmo un giorno vedere un programma che va in
loop, ci ricorderemo del tipo di algoritmo, appositamente sbagliato, da me
proposto, e sapremo forse qual'e' la causa. Inoltre tengo a ribadirlo, non
basta scegliere il linguaggio giusto per creare programmi molto piccoli,
serve anche il tipo di approccio usato e una buona base di conoscenza
dell'Assembler, che seppure improponibile in ambito Windows, lo era
efficacemente in ambito Dos. E siccome Win95 e' un DOS travestito, vale la
pena valutare i vantaggi e gli svantaggi di questa soluzione.
Bye.


pena valutare i vantaggi e gli svantaggi di questa soluzione.
Visto che io programmo normalmente in Windows NT, che del DOS
non ha proprio nulla (se non un buon emulatore incorporato, che non
uso), non si capisce davvero cosa c'entrino gli internals di Win95
(putacaso i miei programmi scritti per NT tendono a funzionare bene
anche in 95 e 98 -- il mercato, mi dicono, lo esige -- quindi si aggirano
certi costrutti testando su che sistema si gira... ma non sono certo quelli
della libreria GDI32, se mai altri tipici di KERNEL32 eccetera).
Alex

 della libreria GDI32, se mai altri tipici di KERNEL32 eccetera).
Tu hai la fortuna di programmare in WinNT dove i blocchi di sistema si
contano sulla punta delle dita. In Win95, e te lo posso garantire, il
sistema diventa instabile anche per una fesseria. Un esempio su tutti,
usando le funzioni standard dell'API, vai a crearti un pennello con
CreateSolidBrush e dimenticati di cancellarlo con DeleteObject. Una volta
finita l'applicazione Win95 non rilascia automaticamente la risorsa, con il
risultato che se questa applicazione viene eseguita per un bel po' di volte
Windows diventa instabile un po' alla volta: cominciano a "saltare" le
icone sul desktop, messaggi di memoria insufficiente ed altre diavolerie.
Tu mi dirai che te ne frega della standard API, usa un framework come MFC e
OWL cosi' eviterai di dover distruggere manualmente un oggetto GDI. Questo
e' vero le classi specifiche per questi due framework hanno questa
possibilita', ma io, per motivi di debugging, voglio vedere anche l'effetto
che fa il mancato rilascio delle risorse GDI. E ti posso garantire che
spesso mi pento di questa necessita', poiche' tutto il sistema diventa
instabile e il compilatore non risponde proprio piu'! Ma e' utile, perche'
porti il sistema ad un punto estremo, e li' capisci che persino MFC e OWL
non sopportano la mancanza delle risorse. Ecco perche' andrebbe, in fase di
debugging, valutato il valore di ritorno di DeleteMenu, poiche' come tutte
le funzioni di Windows non e' che funzionino sempre. E non solo perche' si
passano argomenti errati, e' proprio che non funzionano in certi casi.
Ciao.
