vc怎么屏蔽别人开发的软件里的菜单项,我是在用solidworks,然后在里面加一个插件,现在项目需要屏蔽sw里原有的一些菜单项。
但是比较头疼的是它有自定义菜单和快捷键等功能。
菜单项可以改名字和改位置。
我在加载插件时删了自定义菜单。但是又有问题,如果用户不先加载插件,先改了菜单,那我还是白做了。
不知道描述的够不够清楚,这玩意做的真郁闷

解决方案 »

  1.   

    http://www.vckbase.com/document/viewdoc/?id=628
    把它搞明白,处理你的问题不难。
      

  2.   

    我能想到的有两种方法,应该可以搞定你的那个问题.
    1.动态取得那个弹出菜单的句柄.然后把菜单干掉.可通过取句柄或安装勾子.
    2.用OllyDbg反汇编你那个插件.根据导入库中导入的PopuMenu,检索插件中调用的位置.如果是不想弹出的地方,直接nop掉.
      

  3.   


    恩。我现在在cad软件solidworks下做个插件(支持mfc)。然后想把某些菜单项给屏蔽掉。如文件下面的新建等。。具体不管我这么做是为了什么先。呵呵
    先不管自定义了菜单了。我现在让菜单项灰掉,可是我怎么搞都出不来。
      HWND hwnd=FindWindow(NULL,"SolidWorks 2007");
      //HWND hwnd=GetActiveWindow();
      HMENU hmenu=GetMenu(hwnd);
     
      CFrameWnd *pFrameWnd=(CFrameWnd*)AfxGetMainWnd();
      pFrameWnd->m_bAutoMenuEnable=FALSE;
     
      hmenu=GetSubMenu(hmenu,0);  BOOL ret=EnableMenuItem(hmenu,0,MF_BYPOSITION|MF_GRAYED);
    最后一句返回的是-1。总是不能成功。
    难道插件形式的话CFrameWnd这样用有错吗?
      

  4.   

    可以试试重设窗口的WindowProc,然后响应WM_INITMENUPOPUP消息来处理。
      

  5.   

    我在加载菜单的时候hook它
    g_menuHook=SetWindowsHookEx(WH_CALLWNDPROC,MenuHookProc, AfxGetInstanceHandle(),   0);   
    然后实现钩子,但程序直接退出运行了。这个钩子有什么问题吗?怎么写好?一个进程里写2个钩子应该也没有关系的吧?
    对钩子不是很懂~谢谢
    WNDPROC lpOldWndProc;
    HHOOK g_menuHook;LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)       
    {       
    LRESULT  ret=CallWindowProc(lpOldWndProc, hwnd, uMsg,wParam,lParam);   
    if(uMsg == WM_INITMENUPOPUP)   
    {   
    HMENU hmenu=GetMenu(hwnd);
    hmenu=GetSubMenu(hmenu,0);
    if(!EnableMenuItem(hmenu,0,MF_BYPOSITION   |   MF_DISABLED)) 
    AfxMessageBox(_T("disable menu item failed"));
    }
    return ret;
    }
    LRESULT CALLBACK MenuHookProc(int nCode,WPARAM wParam, LPARAM lParam)
    {
    CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam;

    HWND hwnd=FindWindow(NULL,"SolidWorks 2007");
    ((CFrameWnd*)AfxGetMainWnd())->m_bAutoMenuEnable=FALSE;
    lpOldWndProc=(WNDPROC)GetWindowLong(hwnd,GWL_WNDPROC);
    SetWindowLong(hwnd,GWL_WNDPROC,(long)WinProc);
    return CallNextHookEx(g_menuHook,nCode,wParam,lParam);
    }
      

  6.   

    Hook函数中要判断当前窗口是不是目标窗口,设置窗口函数只需要执行一次,重复了会出问题。
    Hook函数中不能用AfxGetMainWnd。
      

  7.   

    LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)       
    {       
    if(uMsg == WM_INITMENUPOPUP)   
    {   
    HMENU hmenu=GetMenu(hwnd);
    hmenu=GetSubMenu(hmenu,0);
    if(!EnableMenuItem(hmenu,0,MF_BYPOSITION   |   MF_DISABLED)) 
    AfxMessageBox(_T("disable menu item failed"));
    }

    return CallWindowProc(lpOldWndProc, hwnd, uMsg,wParam,lParam);
    }
    LRESULT CALLBACK MenuHookProc(int nCode,WPARAM wParam, LPARAM lParam)
    {
    CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam;

    HWND hwnd=FindWindow(NULL,"SolidWorks 2007");
    if(hwnd)
    {
    lpOldWndProc=(WNDPROC)GetWindowLong(hwnd,GWL_WNDPROC);
    SetWindowLong(hwnd,GWL_WNDPROC,(long)WinProc);
    }
    return CallNextHookEx(g_menuHook,nCode,wParam,lParam);
    }
    怎么判断当前窗口是不是目标窗口?小弟不才。我这里找"SolidWorks 2007"这个窗口应该不会重复设置窗口函数吧?
    改成这样了。还是不行的呀。跟了下代码
    if(uMsg == WM_INITMENUPOPUP)   这里就直接跳到return了。这是为什么?它没做这步?
      

  8.   

    wm_initmenu
    wm_initmenupopenablemenuitem
      

  9.   

    SetWindowsHookEx之后,各个窗口的消息都会调用你的Hook函数,在Hook函数中要判断本次收到的消息是不是发给"SolidWorks 2007"这个窗口的,如果不是则不要处理。因为发给窗口的消息很多,所以要加个判断,只替换一次WNDPROC,不要重复。
    在WinProc中,要调用原WNDPROC函数来处理消息,你的代码只是做一些附加处理。
    另外还有一点忘了说,很多软件的主菜单不是真正的窗口菜单,是利用ControlBar做上去的,你可以用SPY++看一下,如果菜单栏是一个窗口,就是这种情况,这种情况不能按窗口菜单的方式来处理。
      

  10.   

    晕。。图片怎么放啊想把spy++的图片放上来的,我看不来。这个插入图片只能插网上的么。cnzdgs老大,我这样if(hwnd)。。这样子判断不能达到你说的判断是不是发给"SolidWorks 2007"这个窗口吗?
    还有
    “在WinProc中,要调用原WNDPROC函数来处理消息,你的代码只是做一些附加处理。”我还得调用哪些啊?就是想让菜单灰掉。您不给别人写代码的,就稍微写两句让我更加理解点吧。
    实在搞得郁闷
      

  11.   

    因为发给窗口的消息很多,所以要加个判断,只替换一次WNDPROC,不要重复。这里FindWindow"SolidWorks 2007"会执行多次?
      

  12.   

    调用SetWindowsHookEx就是让系统把所有窗口消息都先发给你设置的Hook函数,所以Hook函数会被调用很多次。
    每次Hook函数被调用时都执行这个FindWindow,只要目标窗口存在,返回的hwnd就是不等于0的,所以if(hwnd)里面的代码每次都会执行。
    你可以在WinProc中先不做处理,直接调用原WNDPROC函数,然后返回,等到其它问题都解决之后再加代码。
      

  13.   

    菜单是个很复杂的东西.
    他有很多很多种而且没有统一的规范
    对于ToolbarWin32 可以枚举到句柄给他发hide消息
    对于标准弹出菜单,可以Hook TrackPopupMenu来屏蔽
    对于一些com菜单第三方菜单.. 没办法
      

  14.   

    你能贴段代码上来吗?
    对于ToolbarWin32 可以枚举到句柄给他发hide消息 
    对于标准弹出菜单,可以Hook TrackPopupMenu来屏蔽 
    这两
      

  15.   

    TrackPopupMenu这个是右键弹出菜单吧?
    我要的是下拉的菜单呢
      

  16.   

    你先确定要屏蔽的菜单到底是个什么东西,是不是GetMenu能拿到的,是真的菜单吗,还是别人做的一般窗口
      

  17.   

    恩。GetMenu是可以拿到句柄的。我在上面删除了菜单项。可以的
      

  18.   

    那么可以响应WM_INITMENU或是WM_INITMENUPOPUP消息,wparam是菜单句柄,禁止你要禁止的项。
      

  19.   


    LRESULT CALLBACK MenuHookProc(int nCode,WPARAM wParam, LPARAM lParam)
    {
    HWND hwnd=FindWindow(NULL,"SolidWorks 2007");
    if(hwnd)
    {
    lpOldWndProc=(WNDPROC)GetWindowLong(hwnd,GWL_WNDPROC);
    SetWindowLong(hwnd,GWL_WNDPROC,(long)WinProc);
    return 1;
    }
    return CallNextHookEx(g_menuHook,nCode,wParam,lParam);
    }我怎么解决个问题啊“SetWindowsHookEx之后,各个窗口的消息都会调用你的Hook函数,在Hook函数中要判断本次收到的消息是不是发给"SolidWorks 2007"这个窗口的,如果不是则不要处理。因为发给窗口的消息很多,所以要加个判断,只替换一次WNDPROC,不要重复。”
    g_menuHook=SetWindowsHookEx(WH_CALLWNDPROC,MenuHookProc, AfxGetInstanceHandle(),GetCurrentProcessId());   
     WNDPROC lpOldWndProc;
     HHOOK g_menuHook;LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)       
    {       
    LRESULT ret=CallWindowProc(lpOldWndProc, hwnd, uMsg,wParam,lParam);
    if(uMsg == WM_INITMENUPOPUP)   
    {   
               CMenu menu;
    HMENU hmenu;
    UINT menuItemID;

    hMenu = (HMENU) wParam;
    menu.Attach(hMenu);

    menuItemID =  menu.GetMenuItemID(0);
    menu.EnableMenuItem(menuItemID,MF_GRAYED|MF_DISABLED);

            menu.Detach();

    }

    return ret;
    }
    一运行连带其他程序全部挂了。替换窗口函数的时候怎么确定我要的那个窗口而不会去替换其他的窗口啊?
      

  20.   


    错了
    改成这样后一点没反应了
    g_menuHook=SetWindowsHookEx(WH_CALLWNDPROC,MenuHookProc, AfxGetInstanceHandle(),GetCurrentProcessId());   
    一下都挂了是我把最后的getcurrentprocessid改成0了
      

  21.   

    为了使用户一定加载你的插件,用插件替换原有的程序,在插件中再运行原程序(shellexecute)。此时要注意,因为插件运行的早,原程序此时尚未初始化,好多句柄尚不存在,所以,插件的初始化必须进行延时。关于菜单的问题,使用vc以资源方式打开原程序,如果幸运的话,你可以直接在资源编辑器中编辑菜单,或者直接把菜单项删除。如果原程序的某些资源在DLL里面,这个方法就不行了。如果你的运气够好,上面的一步没问题,那么就可以进行下面的步骤了。使用资源编辑器添加菜单,设置ID(不要和已存在的重复),一定记住ID号哦。然后,再使用消息钩子拦截ID,在钩子函数里面实现你的新功能就行了。以前我用上面的方法试过添加菜单,原程序是VC自动生成的文档视图程序,对MFC4和MFC6生成的程序,其消息拦截方式不一样,如果这个方法在这里不好用,继续用你现在的方法——使用插件动态添加菜单。试试看吧,祝好运。
      

  22.   

    呵呵谢谢yafizyh,使用“vc以资源方式打开原程序”,这个源程序是什么意思啊。LRESULT ret=CallWindowProc(lpOldWndProc, hwnd, uMsg,wParam,lParam);单步调试到这句怎么都过不去。是不是这里有问题
      

  23.   

    接上楼,如果需要实例,mail me [email protected] 希望可以给你一点启迪。
      

  24.   

    使用“vc以资源方式打开原程序”,这个源程序是什么意思啊。 
    -------------------------------------------------------就是原来的应用程序,.exe。
      

  25.   

    有可能不做这个WM_INITMENUPOPUP吗
    我把改成这样
    LRESULT CALLBACK WinProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)       
    {       
    if(uMsg == WM_INITMENUPOPUP)   
    {   
    CMenu menu;
    HMENU hMenu;
    UINT menuItemID;

    hMenu = (HMENU) wParam;
    menu.Attach(hMenu);

    menuItemID =  menu.GetMenuItemID(0);
    menu.EnableMenuItem(menuItemID,MF_GRAYED|MF_DISABLED);

            menu.Detach();
    }
    LRESULT ret=CallWindowProc(lpOldWndProc, hwnd, uMsg,wParam,lParam);
    return ret;
    }
    if里面都不进去