Hmm znowu bedzie dluugi post ale co tam....... wkleje teraz jak wyglada u mnie obsluga WM_INITMENUPOPUP:
void handle_InitPopup(WPARAM wParam, LPARAM lParam)
{
if((BOOL) HIWORD(lParam)) //Nie ruszamy menu systemowego okna
return;
HMENU sub = (HMENU) wParam;
ilosc = GetMenuItemCount(sub);
//Allokacja tablicy itemów
MenuItem *menuItems = (MenuItem *)calloc(ilosc,sizeof(MenuItem));
MenuItem tmp;
MENUITEMINFO mi; //do pobrania info o menu
mi.cbSize = sizeof(MENUITEMINFO);
mi.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID | MIIM_STATE;
mi.dwTypeData = "";
mi.dwItemData = 0;
for(int i=0;i<ilosc;i++)
{
GetMenuItemInfo(sub,i,TRUE,&mi);
menuItems[i].ID = mi.wID;
GetMenuString(sub,menuItems[i].ID,&menuItems[i].Caption,256,MF_BYCOMMAND);
mi.fType = mi.fType | MFT_OWNERDRAW;
//mi.dwItemData=(DWORD)malloc(sizeof(MenuItem)); //dziala i bez tego... :|
menuItems[i].isSep = mi.fType&MFT_SEPARATOR; //Sprawdzanie czy item jest separatorem
menuItems[i].isGrayed = mi.fState&MFS_GRAYED;
tmp.isSep = mi.fType&MFT_SEPARATOR;
tmp.isGrayed = mi.fState&MFS_GRAYED;
mi.dwItemData= (DWORD)&menuItems[i];
SetMenuItemInfo(sub,i,TRUE,&mi);
}
// free(menuItems); - usuniete, bo powoduje wykrzaczanie sie programu - czemu [???]
}
menuItems nie jest globalna.. jest tylko wewnatrz tej funkcji... ja rozumiem to tak: po rozwinieciu popupa tworzona jest dynamicznie tablica o rozmiarze rownym ilosci itemow w popupie. Potem w petli tablica jest wypelniana informacjami o kazdym itemie, a jednoczesnie do itemData jest przypisywany wskaznik do elementu tablicy odpowiadajacego temu itemowi. Tablica menuItems nie jest pozniej juz nigdzie uzywana: odwoluje sie potem tylko do itemData dla kazdego popupa, ale usunac jej nie moge bo nie bedzie to dzialac.....
w zasadzie nie rozwiązujesz problemu bo menuItems jest tablicą globalną, więc inicjacja (i obsługa) głównego menu i jego submenu odbywa się na tej samej tablicy (twoich) item'ów (tyle, że dane są nieaktualne).
Dlaczego nie moze odbywac sie na tej samej tablicy? Wiec jesli dobrze rozumiem, to odwolanie to itemData jest w istocie odwolaniem do elementu tablicy? Ja to rozumialem tak, ze jesli juz raz zainicjuje itemData, to jest to zapamietane i niepotrzebne sa juz dane, ktorymi to itemData inicjowalem - wiec inicjacje innego popupa moge znow przeprowadzic na tej samej tablicy... a itemData dla itemow zainicjowanych wczesniej pozostana aktualne jesli ten item juz byl raz inicjowany .... czy myle sie [???]
Wedlug mnie jesli tak zrobie, to nigdy zaden item nie powinien byc inicjowany nieaktualna informacja, poniewaz zawsze jest przetwarzane tylko te submenu, ktore jest aktualnie rozwijane i tylko itemy nalezace do niego sa inicjowane - to, co bylo inicjowane wczesniej nie jest zmieniane. Po zwinieciu submenu tez sie nic nie dzieje - dopoki znowu nie klikne na popupa......
Wiem za zamotalem teraz dosc mocno, ale jesli gdzies sie myle w moich rozwazaniach to mnie popraw ;)
A z drugiej strony, jesli rzeczywiscie pisze tu teraz glupoty, to na jakiej zasadzie u mnie to moglo zadzialac? :| Generalnie chodzi tu o to, czy jesli raz zainicjuje itemData, to moge usunac te dane, ktorymi inicjowalem te pole... czy nie?
No ale zalozmy, ze chce to zrobic tak jak proponujesz - jezeli wstawie w petli ten kod:
mi.dwItemData=(DWORD)malloc(sizeof(MenuItem));
zamiast mojej inicjalizacji wskaznikiem, to w ogole sie to nie sprawdza - no i ciagle nie rozumiem, na jakiej zasadzie taki zapis ma oznaczac przypisanie dla itema konkretnej instancji MenuItem [???]
A moze ja robie to nie tak jak trzeba? Ale gdzie w takim razie mam pzreprowadzic ta inicjalizacje jesli nie w petli dla kazdego itema w popupie po kolei?
Oczywiście trzeba pamiętać o zwalnianiu pamięci przy usuwaniu itemów i nie dopuścić do wielokrotnego inicjowania wcześniej zainicjowanych itemów.
No zgoda, ale jak mam wykryc, kiedy itemy sa usuwane? :|
WinXP: pasek znika po zaznaczeniu i odznaczeniu (brak odmalowania) - to po rozwinięciu sub menu.
WinMe: itemy w submenu są rysowane tak jakby na separatorze - po prawej stronie widać kreseczkę ) Ogólnie, trochę muli... a może wydaje mi się.
Nie wiem co sie dzieje, tez mam WinXP i u mnie dziala :| Ktora czesc kodu mam wrzucic, zeby mozna bylo popatrzec co jest nie tak? :| :|