Ir ao conteúdo
  • Cadastre-se

[C/C++11 - win32] - fazer a class menu


Cambalinho

Posts recomendados

eu estou a criar 1 class menu mas com algum problemas com o ciclo de mensagens :(

class Menu{private:    static int intID;    int ID=0;    bool primeiromenu=false;    HMENU MenuHandle=NULL;    HMENU hMenu=NULL;    int menuposition=0;    string strCaption="";    static LRESULT CALLBACK MenuSubclassProc( HWND hwnd, UINT uMsg, WPARAM wParam,  LPARAM lParam)    {       Menu *wnd = 0;        // retrieve associated Window instance        wnd = reinterpret_cast<Menu *>(GetWindowLong(hwnd, GWL_USERDATA));        if(uMsg==WM_MENUCOMMAND)            wnd->MenuClick();        return DefWindowProc(hwnd, uMsg, wParam, lParam);    }    public:    event(MenuClick) = []() {;};    Menu(string caption="&Menu",HMENU subtmenu=NULL, HWND MainHWND=WindowMain)    {        intID=intID+1;        ID=intID;        if(caption!="-")            caption=(string)caption + " " + to_string(ID);        strCaption=caption;        if(GetMenu(MainHWND)==NULL)            hMenu = CreateMenu();        else            hMenu =GetMenu(MainHWND);        if (subtmenu==NULL)        {            HMENU hSubMenu=CreatePopupMenu() ;            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, caption.c_str());            MenuHandle=hSubMenu;//my error was here            SetMenu(MainHWND, hMenu);            menuposition=GetMenuItemCount(hMenu)-1;            primeiromenu=true;        }        else        {            if(caption=="-")                AppendMenu(subtmenu, MF_SEPARATOR, ID, caption.c_str());            else                AppendMenu(subtmenu, MF_STRING, ID, caption.c_str());            MenuHandle=subtmenu;            menuposition=GetMenuItemCount(subtmenu)-1;            SetMenu(MainHWND, hMenu);        }            MENUINFO  mi;            mi.cbSize=sizeof(MENUINFO );            if(primeiromenu==true)                SetMenuInfo(GetMenu(WindowMain),&mi);            else                GetMenuInfo(MenuHandle,&mi);            mi.fMask=MIM_STYLE;            mi.dwStyle =MNS_NOTIFYBYPOS;            if(primeiromenu==true)                SetMenuInfo(GetMenu(WindowMain),&mi);            else                SetMenuInfo(MenuHandle,&mi);        SetWindowLong(MainHWND,GWL_WNDPROC,(LONG)MenuSubclassProc);        SetWindowLong(MainHWND,GWL_USERDATA,(LONG)this);    }    void Show(HWND mainshowed)    {        LPPOINT x;        GetCursorPos(x);        SetForegroundWindow(mainshowed);        TrackPopupMenu(MenuHandle,NULL,x->x,x->y,0,mainshowed,NULL);        PostMessage(mainshowed, WM_NULL, 0, 0);    }    int getmenuposition()    {        return menuposition;    }    property<string> Caption    {        Get(string)        {            return strCaption;        },        Set(string text)        {            MENUITEMINFO mi;            mi.cbSize=sizeof(MENUITEMINFO);            if(primeiromenu==true)                GetMenuItemInfo(GetMenu(WindowMain),menuposition,true,&mi);            else                GetMenuItemInfo(MenuHandle,menuposition,true,&mi);            mi.fMask=MIIM_STRING;            mi.dwTypeData =(LPTSTR)text.c_str();            if(primeiromenu==true)                SetMenuItemInfo(GetMenu(WindowMain),menuposition,true,&mi);            else                SetMenuItemInfo(MenuHandle,menuposition,true,&mi);        }    };    operator int()    {        return ID;    }    operator HMENU()    {        return MenuHandle;    }    void Destroy()    {        DestroyMenu(MenuHandle);    }};int Menu::intID=0;//no procedimento das mensagens do form tenho:case WM_MENUCOMMAND:                {                    SendMessage((HWND)lParam , WM_COMMAND, wParam, lParam);                }                break;                case WM_COMMAND:                {                    SendMessage((HWND)lParam , WM_COMMAND, wParam, lParam);                }                break;

o problema é que o  procedimento do menu nao retorna ao do form :( alguem me pode explicar o que estou fazendo mal?

Link para o comentário
Compartilhar em outros sites

Você está criando a janela do zero?

Com WinMain, atribuindo WNDCLASS, RegisterClass, etc..?

sim. tenho tudo numa class form. e mais 1 procedimento para o loop das mensagens.

o erro que tenho é mesmo com SetWindowLong(), porque chama o MenuSubclassProc() mas nao volta ao procedimento de mensagens do form. outra coisa: MainHWND é o HWND do form, penso que isto esta errado tambem. mas aceito ideias

Link para o comentário
Compartilhar em outros sites

No case você está tentando processar a mensagem WM_MENUCOMMAND. Tente processar WM_COMMAND que é a mensagem para eventos do menu.

Uma ideia que talvez deixe o projeto mais simples na criação de menus, é o uso de recursos. Já tentou usar recursos?

Mas eu acho que, já que você está usando as APIs diretamente, você devia programar C.

C++ deixa o projeto complexo, além de não ter grande vantagem. Se for para programar em C++, acho melhor usar alguma biblioteca POO como o MFC que encapsula as APIs.

Link para o comentário
Compartilhar em outros sites

No case você está tentando processar a mensagem WM_MENUCOMMAND. Tente processar WM_COMMAND que é a mensagem para eventos do menu.

Uma ideia que talvez deixe o projeto mais simples na criação de menus, é o uso de recursos. Já tentou usar recursos?

Mas eu acho que, já que você está usando as APIs diretamente, você devia programar C.

C++ deixa o projeto complexo, além de não ter grande vantagem. Se for para programar em C++, acho melhor usar alguma biblioteca POO como o MFC que encapsula as APIs.

esquece o MFC lol

sim eu posso alterar isso. mas estou a usar essa mensagem porque modifiquei os menus para isso ;)

eu quero meter o processamento das mensagens na class ;)

Link para o comentário
Compartilhar em outros sites

Ok, não tenho mais nenhuma sugestão.

Vamos aguardar, talvez alguém ajude.

eu entendi a tua sugestao do MFC e eu ja dei conta dessa linguagem complicada.. eu prefiro simplificar as minhas cenas ;)

mas tenho de ver como vou corrigir aquele erro :(

o problema é os menus usarem HMENU em vez de HWND. senao estava resolvido de outra forma

Link para o comentário
Compartilhar em outros sites

Eu acho que se você quisesse simplificar, considerando esse código, poderia evitar POO. Mas se você domina C++, ok. Só sugeri uma lib tipo MFC considerando um projeto POO.

 

A forma mais simplificada de criar menu é com recurso (rc file). Não há necessidade de handle HMENU, basta criar o script e passar o nome do menu para lpszMenuName. Aí basta tratar a mensagem WM_COMMAND de WindowProc.

 

Mas da forma que está aí, fica difícil ajudar.

Link para o comentário
Compartilhar em outros sites

Eu acho que se você quisesse simplificar, considerando esse código, poderia evitar POO. Mas se você domina C++, ok. Só sugeri uma lib tipo MFC considerando um projeto POO.

 

A forma mais simplificada de criar menu é com recurso (rc file). Não há necessidade de handle HMENU, basta criar o script e passar o nome do menu para lpszMenuName. Aí basta tratar a mensagem WM_COMMAND de WindowProc.

 

Mas da forma que está aí, fica difícil ajudar.

imagina isto:

1 - crias 1 objecto do menu;

2 - esse objecto pode alterar a opções do menu(texto, atalhos, cor de texto e muito mais);

3 - esse objecto, com lambdas, podes fazer os 'eventos'.

quero inserir tudo nessa class. mas a parte dos 'eventos' esta complicada :(

('eventos' -  falo das mensagens)

PS: para fazer 1 form e mostrar, só preciso de criar 1 variavel do tipo form. nao é simplificado? ;)

PS: posso ocultar a cor de fundo do form, permitindo as formas do form. nao é simplificado? ;)

Link para o comentário
Compartilhar em outros sites

Prefiro usar resource e simplesmente passar o nome do menu para lpszMenuName.

Fica mais fácil gerenciar o objeto e até traduzir se o programador quiser.

Você usaria/usa essa sua classe em um projeto profissional com milhares de linhas de código?

sim ;)

sabes porque?

olha isto:

Menu menu1, menu2, menu3("oi",menu2), menu4("hello",menu2);

o resto é só propriedades amigo. então nao usavas?

nao sei de destes conta: mas objecto do Menu cria o menu e mostra-o. o menu3 e menu4 indico(2º parametro) o sitio onde vão ficar amigo ;)

Link para o comentário
Compartilhar em outros sites

Já deu uma olhada no gerenciador de eventos da biblioteca Boost C++?

http://en.highscore.de/cpp/boost/eventhandling.html

 

Talvez você encontre tudo o que necessita. 

lamento mas nao :(

 

tenho outra idea para isso, ao criar os menus, ja os preparo  para serem trabalhados na mensagem WM_MENUCOMMAND:

//put the this on dwItemData            MENUITEMINFO  s;            GetMenuItemInfo (hMenu,intID, true, &s);            s.cbSize=sizeof(MENUITEMINFO );            s.fMask=MIIM_DATA;            s.dwItemData=(ULONG_PTR)this;            SetMenuItemInfo (hMenu,intID, true, &s);            //change the menu for use the WM_MENUCOMMAND            MENUINFO mnInfo;            GetMenuInfo(hMenu,&mnInfo);            mnInfo.cbSize=sizeof(MENUINFO);            mnInfo.fMask=MIM_STYLE;            mnInfo.dwStyle=MNS_NOTIFYBYPOS;            SetMenuInfo(hMenu,&mnInfo);

mas nao estou a captar o 'this' correctamente.. alguem me pode dizer o que fiz de errado?

case WM_MENUCOMMAND:                {                    BOOL fResult = FALSE;                    MENUITEMINFO menuInfo = { 0 };                    menuInfo.cbSize = sizeof(MENUITEMINFO);                    menuInfo.fMask = MIIM_ID | MIIM_DATA;                    fResult = GetMenuItemInfo((HMENU)lParam,(UINT) wParam, TRUE, &menuInfo );                    if (fResult!=0)                    {                        UINT myId = menuInfo.wID; // this is item ID                        ULONG_PTR myData = menuInfo.dwItemData; // item data (like 'this' pointer')                        CREATESTRUCT *p = (CREATESTRUCT *)menuInfo.dwItemData;                        Menu *menu = (Menu *)p->lpCreateParams;                        //if(mMenu->MenuClick==NULL) break;                        //mMenu->MenuClick();//it's a lambda function variable                    }                }                break;
Link para o comentário
Compartilhar em outros sites

  • mês depois...

eu resolvi esse erro:

Menu(string caption, Menu *submenu=NULL, HWND MainHWND=WindowMain, bool systmenu=false) //WindowMain is then 1st form handle(WHND window) that is created    {        //calculate the ID        intID=intID+1;        ID=intID;        Mainwindow=MainHWND;        //calculate the caption //i'm changing these too        strCaption=caption;        if (strCaption=="")            strCaption=(string)caption + " " + to_string(ID);        //getting the menu bar handle if the submenu is null        mnuBar = GetMenu(Mainwindow);        if(mnuBar==NULL)            mnuBar = CreateMenu();        if(systmenu==true)            mnuBar=GetSystemMenu(Mainwindow,false);        //creates the popup menu for add the new items        if (submenu==NULL && systmenu==true )        {            AppendMenu(mnuBar, MF_STRING, ID, strCaption.c_str());            MenuHandle=mnuBar;//is where the submenu is created            SetMenu(MainHWND, mnuBar);            menuposition=GetMenuItemCount(mnuBar)-1;            ispopup=false;            MenuPopup=mnuBar;            primeiromenu=false;        }        else if (submenu==NULL)        {            HMENU hSubMenu=CreatePopupMenu() ;            AppendMenu(mnuBar, MF_STRING | MF_POPUP, (UINT)hSubMenu, strCaption.c_str());            MenuHandle=hSubMenu;//is where the submenu is created            SetMenu(MainHWND, mnuBar);            menuposition=GetMenuItemCount(mnuBar)-1;            ispopup=true;            MenuPopup=GetMenu(MainHWND);            primeiromenu=true;        }        else        {            //creates a separator            if(strCaption=="-")            {                AppendMenu((HMENU)submenu, MF_SEPARATOR, ID, strCaption.c_str());                MenuHandle=(HMENU)submenu;                SetMenu(MainHWND, GetMenu(MainHWND));//update the menu                ispopup=false;            }            //change the subitem to be a popup menu            else if(submenu->ispopup==false)            {                HMENU hSubMenu=CreatePopupMenu();                ModifyMenu(submenu->MenuHandle,submenu->menuposition,MF_BYPOSITION| MF_POPUP|MF_STRING,(UINT_PTR)hSubMenu, submenu->strCaption.c_str());                submenu->MenuHandle=hSubMenu;//is where the submenu is created                AppendMenu(submenu->MenuHandle, MF_STRING, ID, strCaption.c_str());                SetMenu(MainHWND, GetMenu(MainHWND));                menuposition=GetMenuItemCount(submenu->MenuHandle)-1;                MenuHandle=hSubMenu;                SetMenu(MainHWND, GetMenu(MainHWND));                MenuPopup=submenu->MenuPopup;                submenu->ispopup=true;            }            //add a new item on subtmenu popup menu            else if(submenu!=NULL)            {                AppendMenu((HMENU)submenu->MenuHandle, MF_STRING, ID, strCaption.c_str());                MenuHandle=(HMENU)submenu->MenuHandle;//the menu handle is the popup menu handle... instead the item menu handle                 menuposition=GetMenuItemCount((HMENU)submenu->MenuHandle)-1;//calculate the menu position                SetMenu(MainHWND, GetMenu(MainHWND));//update the menu                ispopup=false;            }        }        MENUINFO mnInfo;        mnInfo.cbSize=sizeof(MENUINFO);        mnInfo.fMask=MIM_STYLE;        if(systmenu==false)            GetMenuInfo(GetMenu(MainHWND),&mnInfo);        else            GetMenuInfo(GetSystemMenu(MainHWND,false),&mnInfo);        mnInfo.cbSize=sizeof(MENUINFO);        mnInfo.fMask=MIM_STYLE;        mnInfo.dwStyle=MNS_NOTIFYBYPOS;        if(systmenu==false)            SetMenuInfo(GetMenu(MainHWND),&mnInfo);        //put the this on dwItemData        HMENU hMenu = NULL;        if(primeiromenu)            hMenu = GetMenu(MainHWND);        else if(ispopup)            hMenu = (HMENU)submenu->MenuHandle;        else if(systmenu==true)            hMenu=GetSystemMenu(MainHWND,false);        else            hMenu = MenuHandle;        MENUITEMINFO  s;        s.cbSize=sizeof(MENUITEMINFO );        s.fMask=MIIM_DATA;        GetMenuItemInfo (hMenu,menuposition, true, &s);        s.cbSize=sizeof(MENUITEMINFO );        s.fMask=MIIM_DATA;        s.dwItemData=(ULONG_PTR)this;        SetMenuItemInfo (hMenu,menuposition, true, &s);    }//no window procedure do form:case WM_MENUCOMMAND:                {                    MENUITEMINFO menuInfo;                    menuInfo.cbSize = sizeof(MENUITEMINFO);                    menuInfo.fMask=MIIM_DATA;                    GetMenuItemInfo((HMENU)lParam,(UINT) wParam, true, &menuInfo );//true means by position                    Menu *mMenu = (Menu *) menuInfo.dwItemData;                    mMenu->MenuClick();                }                break;

agora estou a fazer para o menu do system(o icon da janela):

case WM_INITMENUPOPUP:                {                    menuhandle=(HMENU)wParam;                    return 0;                }                break;                case WM_SYSCOMMAND:                {                    if (menuhandle!=NULL)                    {                        int menuitemcount=GetMenuItemCount(menuhandle)-1;                        int i=0;                        for(i=0; i<menuitemcount; i++)                        {                            if(GetMenuState(menuhandle,i,MF_BYPOSITION) == MF_HILITE)                            {                                menuposition=(UINT)i;                                break;                            }                        }                        SetWindowText(HandleWindow, to_string(i).c_str());                        MENUITEMINFO menuInfo;                        menuInfo.cbSize = sizeof(MENUITEMINFO);                        menuInfo.fMask=MIIM_DATA;                        GetMenuItemInfo(menuhandle,(UINT) menuposition, true, &menuInfo );//true means by position                        Menu *mMenu = (Menu *) menuInfo.dwItemData;                        if (mMenu!=NULL)                        {                            mMenu->MenuClick();                            menuhandle=NULL;                            menuposition=0;                        }                    }                    return DefWindowProc(HandleWindow, msg, wParam, lParam);                }                break;

algo se passa com o ciclo for, eu recebo sempre o mesmo resultado. o GetMenuState() nao é para me indicar se o rato esta por cima do item do menu?

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!