我看了一份代码,但没看明白。
我知道大概步骤是这样:
1 首先定义消息:例如 define WM_MYMESSAGE (WM_USER+100) 2 在.H文件中,加入消息响应函数,如:         LONG OnMyMessage(WPARAM w,LPARAM l);     该函数有规定的格式:         LONG Function_Name(WPARAM w,LPARAM l); 3 加入消息响应宏,在响应该消息的类中,在消息响应块中,     BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)         //{{AFX_MSG_MAP(CAboutDlg)         ON_MESSAGE(WM_MYMESSAGE,OnMyMessage)         //}}AFX_MSG_MAP     END_MESSAGE_MAP() 4 在.CPP文件中,编辑消息响应函数,如下:     LONG CMyClass::OnMyMessage(WPARAM w,LPARAM l)     {     } 5 大功告成。但是我不知道这个   LONG CMyClass::OnMyMessage(WPARAM w,LPARAM l) 
是怎么写?
我贴个代码出来,请大家帮助我理解分析,人多加贴加分,分不用担心,我天天放分,放一个月都够分。

解决方案 »

  1.   

    //Gfxoutbarctrl.h
    #define WM_OUTBAR_NOTIFY WM_USER + 1
    #define NM_OB_ITEMCLICK 1
    #define NM_OB_ONLABELENDEDIT 2
    #define NM_OB_ONGROUPENDEDIT 3
    #define NM_OB_DRAGITEM 4
    #define NM_FOLDERCHANGE 5//Gfxoutbarctrl.cpp
    BEGIN_MESSAGE_MAP(CGfxOutBarCtrl, CWnd)
    ...
    ON_MESSAGE(WM_OUTBAR_NOTIFY, OnEndLabelEdit)
    END_MESSAGE_MAP()long CGfxOutBarCtrl::OnEndLabelEdit(WPARAM wParam, LPARAM lParam)
    {
    if (wParam == NM_OB_ONGROUPENDEDIT)
    {
    CGfxGroupEdit * pEdit = (CGfxGroupEdit *) lParam;
    OUTBAR_INFO ob;
    ob.index = pEdit->iIndex;
    ob.cText = pEdit->text; if (GetOwner()->SendMessage(WM_OUTBAR_NOTIFY, NM_OB_ONGROUPENDEDIT, (LPARAM) &ob))
    {
    SetFolderText(pEdit->iIndex, pEdit->text);
    CRect rc;
    GetFolderRect(pEdit->iIndex, rc);
    InvalidateRect(rc, false);
    }
    }
    if (wParam == NM_OB_ONLABELENDEDIT)
    {
    CGfxGroupEdit * pEdit = (CGfxGroupEdit *) lParam;
    OUTBAR_INFO ob;
    ob.index = pEdit->iIndex;
    ob.cText = pEdit->text; if (GetOwner()->SendMessage(WM_OUTBAR_NOTIFY, NM_OB_ONLABELENDEDIT, (LPARAM) &ob))
    {
    SetItemText(pEdit->iIndex, pEdit->text);
    CRect rc;
    GetInsideRect(rc);
    InvalidateRect(rc, true);
    }
    }
    return 0;
    }void CGfxOutBarCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
    ...这里我见到有SendMessage()//mainfrm.cpp
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ...
    ON_MESSAGE(WM_OUTBAR_NOTIFY, OnOutbarNotify)
    END_MESSAGE_MAP()long CMainFrame::OnOutbarNotify(WPARAM wParam, LPARAM lParam)
    switch (wParam)
    {
    case NM_OB_ITEMCLICK:
    // cast the lParam to an integer to get the clicked item
    {
    int item = (int) lParam;
    OnItemClick(curFolder,item); //curFolder is CMainFrame's member
    }
    return 0; case NM_OB_ONLABELENDEDIT:
    ...
    return 1; case NM_OB_ONGROUPENDEDIT:
    ...
    return 1; case NM_OB_DRAGITEM:
    ...
    return 1; case NM_FOLDERCHANGE:
    ...
    return 1;
    }
    return 0;
    }void CMainFrame::OnItemClick(int folder, int item)
    switch (folder)
    {
    case 0:
    switch (item)
    {
    case 0:
    m_pRightPaneFrame->SwitchToView(VIEW_HR);
    // m_pRightPaneFrame->m_pStatView->PostMessage(WM_PROCESSDATA,WM_STAT,(LPARAM)Folder);
    break;
    case 1:
    m_pRightPaneFrame->SwitchToView(VIEW_FINANCE);
    // m_pRightPaneFrame->m_pListCtrlView->PostMessage(WM_PROCESSDATA,WM_SEARCH,(LPARAM)Folder);
    break;
    case 2:
    m_pRightPaneFrame->SwitchToView(VIEW_REPORT);
    break;
    }
    break;
    case 1:
    break;
    case 2:
    break;
    }
    }就是这些代码,我不理解,请帮忙
      

  2.   

    怎么不理解?置于方法:
    http://www.csdn.net/develop/read_article.asp?id=15980
    可以看看。具体问题具体对待!
      

  3.   

    不明白一:
    LONG CMyClass::OnMyMessage(WPARAM w,LPARAM l) 两个参数不明白是什么意思。不明白二:
    》void CGfxOutBarCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
    》...这里我见到有SendMessage()
    是不是要在传统的信息处理函数里sendmessage才能使自己的message有机会给windows拿去在message链表中比较,并最终找到自定义消息对应的处理函数?
    (先在自己的映射表找,找到了OnEndLabelEdit(),这里由于不明白wparam, lparam,理解受了影响;然后windows又会到这个类的上一个基类的映射表中找此message,没有的话再上一级基类,例如是CFrameWnd,这里又找到了此message,又调用OnOutbarNotify(),这后面都能看明白,就是不知道前面那么多sendmessage是怎么设计的。)
      

  4.   

    The SendMessage member function calls the window procedure directly and does not return until that window procedure has processed the message. This is in contrast to the PostMessage member function, which places the message into the window’s message queue and returns immediately. 刚看到的。
      

  5.   

    说明一下,outlook bar上的button是没有资源可以预定义的。也就没有ID
      

  6.   

    又看到了一些东西,SendMessage和PostMessage有参数对应(WPARAM w,LPARAM l)
      

  7.   

    我在BCG论坛里问老外这个相关的问题,有个小鬼出来答我,我不是很明白。
    问:
    Now I describe my problem in detail.
    Usually we use CBCGPOutlookBarPane::AddButton(hBmp,lpszLabel,iIdCommand) to add a button to a pane, but now I want to dynamic add a button to a pane ,so I dont know which IdCommand the button will handle. In order to deal with the message of clicking the button, What should I do ?小鬼答:
    I myself am a novice, but i thin i can offer a bit of help here...if you creating one button dynamically...i.e.CBPCGPButton MyButton;MyButton.Create (_T("Button"), WS_VISIBLE | WS_CHILD|BS_CHECKBOX, CRect (0, 0, 0, 0), this, ID_INSERT_HR);define ID_INSERT_HR in your resource.hhandle the WM_COMMAND handler in i.e. your viewON_COMMAND(ID_INSERT_HR, OnInsertHR)add this in message map declration...to add multiple buttons.....
    UINT m_CtrlIDs;
    m_CtrlIDs=ID_INSERT_POINTER;
    for (int i = 0; i < m_BtnCountInPage ; i++ )
    {
    m_wndBtns [i].Create (_T("Button"), WS_VISIBLE | WS_CHILD|BS_CHECKBOX, CRect (0, 0, 0, 0), this, ++m_CtrlIDs);m_wndBtns [i].m_nFlatStyle = CBCGPButton::BUTTONSTYLE_FLAT;
    m_wndBtns [i].m_nAlignStyle = CBCGPButton::ALIGN_LEFT;
    m_wndBtns [i].m_bDrawFocus = FALSE;
    }i don't know y it is not displaying "plusplus" sign.. in loop it's "i plusplus" not i at the end..and in Create function it is "plusplus m_CtrlIDs" not m_CtrlIDs....cheersJust because someone doesn't love you the way you want them to, doesn't mean they don't love you with all they have.有谁帮解读一下,他可能省了好多话。
      

  8.   

    to skt32
    朋友,不要,不像你的作风:-( 
    (要也一下这贴吧,我好给分
    http://expert.csdn.net/Expert/topic/1758/1758426.xml?temp=.3113062 )
      

  9.   

    在下再说明清楚一下问题:
    我不清楚动态创建出来的button怎么才能处理它的点击? 因为cmdID没有事先制定(要不就不叫动态啦)。
    我看了一下CButton::Create 和我用的CBCGPOutlookBarPane::AddButton是差不多的,都要指定control ID(应该就是我说的cmdID).
      

  10.   

    日期:2001.12.08 三剑侠 重庆 
    主题:VC++中使用用户自定义消息及自定制窗口技巧 
    内容:Windows 应用程序所要做的每项工作几乎都是基于消息处理的, Windows 系统消息分为常用 Windows 消息,控件通知消息和命令。然而,有时我们需要定义自己的消息来通知程序什么事情发生了,这就是用户自定义消息。 ClassWizard 并没有提供增加用户自定义消息的功能,所以要使用用户自定义消息,必须手工编写代码。然后 ClassWizard 才可以象处理其它消息一样处理你自定义的消息。具体做法如下详解:    第一步:定义消息。一个消息实际上是开发 Windows95 应用程序时, Microsoft 推荐用户自定义消息至少是 WM_USER+100 ,因为很多新控件也要使用 WM_USER 消息。    第二步:实现消息处理函数。该函数使用 WPRAM 和 LPARAM 参数并返回 LPESULT 。    LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam){// TODO: 处理用户自定义消息 AfxMessageBox(" 处理用户自定义消息 "); return 0;}    第三步:在类头文件的 AFX_MSG 块中说明消息处理函数: 
       class CMainFrame:public CMDIFrameWnd{   ...   // 一般消息映射函数    protected:   // {{AFX_MSG(CMainFrame)   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);   afx_msg void OnTimer(UINT nIDEvent);   afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);   //}}AFX_MSG   DECLARE_MESSAGE_MAP()}
       第四步:在用户类的消息块中,使用 ON_MESSAGE 宏指令将消息映射到消息处理函数中。 
       BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)   //{{AFX_MSG_MAP(CMainFrame)   ON_WM_CREATE()   ON_WM_TIMER()   ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)   //}}AFX_MSG_MAPEND_MESSAGE_MAP()
       这样,一个用户自定义消息就可以使用了,如果用户需要一个整个系统唯一的消息,可以调用 SDK 函数 RegisterWindowMessage 并使用 ON_REGISTER_MESSAGE 宏指令取代 ON_MESSAGE 宏指令,其余步骤同上。    VC++ 为程序员提供了一套功能强大、方便快捷的编程工具,它可以帮你方便的生成窗口、菜单等用户界面,可惜就是做出来的东西都一样,没有一点个性。下面,就介绍一些方法,让我们可以按照自己的设计定制出更加符合自己程序风格的窗口。    一、如何在多文档界面下去掉开始的子窗口    在多文档界面程序中,程序刚启动的时候会自动打开一个新的子窗口,而一个实际的应用系统往往是由用户操作后再生成新的窗口。下面是如何去掉开始的子窗口。    首先在应用程序的 App 类里找到    BOOL CMyMDIApp::InitInstance() 下面有: 
    // Parse command line for standard shell commands, DDE, file open 
    CCommandLineInfo cmdInfo; 
    ParseCommandLine(cmdInfo);
       这是在处理命令行参数,在这几句话后面加一行:    cmdInfo.m_nShellCommand=CCommandLineInfo::FileNothing; 就可以了。再运行程序,就会发现程序并没有自动开启一个子窗口,而只剩下主框架窗口了。    二、修改窗口标题栏    在缺省情况下,窗口标题栏中显示的标题为程序名 + 当前文档的文件名。比如 " MyProgram - 文档 1 . t x t " ,那若要在标题栏显示一个自己定义的字符串,而不是程序名,可以通过在程序里调用 CWnd::SetWindowText() 方法来实现,而如果我们还想要后面的文档名自动显示,这么做就不行了,这时可以用资源编辑器编辑字符串表( StringTable )资源,在 StringTable 中双击 IDR-MAIN-FRAME 项, caption 中显示一字符串 xx\n\yy...... ,将第一个参数修改为用户自己希望见到的主窗口标题即可。    如果你不想让系统自动帮你把文档的文件名添加到标题栏中,需要在 CMainFram 的 PreCreateWindow 函数中删除 FWS_ADDTOTITLE 标志的窗口样式:    cs.style &= ~FWS_ADDTOTITLE ;    这样,程序运行起来,窗口标题就是 "MyProgram" 而没有后面的 "- 文档 1.txt" 这样的字符串了。    三、修改主框架窗口、子窗口及其显示风格    MFC 的 CWnd 类会在调用 CWnd::Create() 方法前先调用一下 PreCreateWindo() 方法,其参数是 CREATESTRUCT cs ,其中包括了创建窗口时各参数,例如大小,风格等等,我们可以通过重载这个成员函数来修改主窗口和子窗口的风格等属性。 PreCreateWindow 函数的原型为: Virtual BOOL PreCreateWindow ( CREATESTRUCT cs )。重载 PreCreateWindow 函数以后,则在创建窗口前可以修改 CREATESTRUCT 结构以替换缺省参数。 CREATESTRUCT 结构存放窗口特征,如窗口坐标、风格等,还可以定义新窗口风格。    若想修改主框架窗口,则可以在 MainFrm.cpp 的下列成员函数中加入待修改的内容。例如: 
       BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs)
    {
    // 通过修改 CREATESTRUCT 结构来修改窗口类或风格 
    cs.cx=450;
    cs.cy=300;
    // 定义新窗口的高度、宽度 
    // 定义新窗口风格为去掉主窗口名及最大化等按钮 
    cs.style=ws-POPWINDO;
    return CFrameWnd::PreCreateWindow(cs); }
       定制子窗口的操作与上述主窗口相同,可在 ChildFrame.cpp 中加入以下内容:    BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs)
    {
    // 通过修改 CREATESTRUCT 结构来修改窗口类或风格 
    return CMDIChildWnd::PreCreateWindow(cs);
    }  要修改视图窗口的显示性质,则可在视图文件 MyView.cpp 的下述成员函数中加入以下语句: 
       BOOL MyView::PreCreateWindow(CREATESTRUCT&cs)
    {
    // 在这里修改 cs 结构,改变 View 的风格。 
    cs.lpszClass=AfxRegisterWndClass(cs-HREDRAW|CS-VREDRAW,0,(HBRUSH))::GetStockObject(WHITE-BRUSH),0); 
    return CScrollView::PreCreateWindow(cs);
    }
       其中, cs 的参数 pszClass 用于存放 Windows 窗口类名称。要想注册 Windows 窗口类,则必须调用全局函数 AfxRegisterWndClass 。该函数原型为: 
       LPCTSTR AFXAPI AfxRegisterWndClass(UINTnClassStyle,HCURSOR hCursor=0,HBRUSH hbrBackground=0,HICON hIcon=0)
       上述各参数用于定义风格,其含义分别为光标资源句柄、背景资源句柄、图标资源句柄。上述增加的语句的作用是:改变窗口大小时重画窗口、不显示光标图标、设置白色背景。    四、窗口的滚动    MFC 中的 CScrollView 可以帮助你自动实现窗口滚动的决大部分功能,使用 CscrollView 时, ClassWizard 生成 OnInitialUpdate() 成员函数为: 
       void CMyScrollView::OnInitialUpdat()
    {
    CScrollView::OnIntialUpdate();
    CSize sizePage;
    sizePage.cs=sizePage.cy=400;
    SetScrollSizes(MM-TEXT,sizePage);
    }
       其中, cs 和 cy 分别为滚动窗口的水平、垂直分量,表明窗口的水平、垂直方向尺寸小于 400 像素单位时将出现水平方向滚动条和垂直方向滚动条。通过修改滚动尺寸,可改变出现滚动条的最小窗口。例如,若 sizePage.cx=600;sizePage.cy=800; ,则当窗口尺寸小于 600*800 时,就会出现滚动条。    五、窗口分割    该功能可将窗口分割成多个可滚动的帧,帧之间的边界称为分割条,可用分割条来调整每个帧的相对大小。要想增加窗口分割功能,则必须修改主窗口类。首先,在主窗口类的头文件 MainFrm.h 中添加以下代码: 
       CSplitterWnd m-SWnd;
    Virtual BOOL OnCreateClient (LPCREATESTRUCTcs,CcreateContext *pContext);
       再在 MainFrm.cpp 中添加成员函数 OnCreateClient 的定义: 
       BOOL CmainFrame::OnCreateCline(LPCREATESTRUCTcs,CcreateContext *p Context)

    return m-SWnd.Creat(this,2,2,Csize(20,20),pContext);
    }
       新的 CSplitterWnd 类对象 m-SWnd 用于创建和管理分割窗口,该窗口中可以包含一个或多个帧。首次创建主窗口时,将调用成员函数 OnCreateClient 。在缺省情况下,该函数创建一个填充主框窗口客户区的视图窗口。覆盖该函数后,将调用 CsplitterWnd 的成员函数 Create 来创建分割窗口。其中,第一个参数用于指定分割的父窗口(主窗口);第二个参数指定垂直方向上的帧个数为 2 ;第三个参数指定水平方向上的帧的个数;第四个参数用于设置每个帧的最小尺寸;第五个参数传递描述信息。上述分割窗口的每个帧都是由视图类对象管理的,当用户在某一帧内显示文档和图形时,必须在其它帧中重新绘制,从而在多个帧中均显示相同的内容。为此,必须调用显示文档类的 UpdateALLView 成员函数来更新其它帧。此时,只需加入 pdoc- > UpdataALLView(NULL) 即可。 
     
      

  11.   

    LRESULT CMainFrame::OnOutbarNotify(WPARAM wParam, LPARAM lParam) 
    { // wParam 存放消息类型, 见下面的详述
    // lParam 存放一个 XT_OUTBAR_INFO 类型的结构指针// 1。取消息类型 和 OUTBAR INFO 结构指针
    int nBarAction = (int)wParam; 
    // Cast the lParam to a XT_OUTBAR_INFO* struct pointer. 
    XT_OUTBAR_INFO* pOBInfo = (XT_OUTBAR_INFO*)lParam; 
    ASSERT(pOBInfo); // 2. 根据消息类型做你自己的处理
    switch (nBarAction) 

    case OBN_XT_ITEMCLICK: // 单击了一个ITEM, 也就是你说的BUTTON
    // 你想干啥,就自己写吧。
    // 比如切换你的TABWND,SwitchView();
    TRACE2( "Item selected: %d, Name: %s.\n", pOBInfo->nIndex, pOBInfo->lpszText); 
    break; case OBN_XT_FOLDERCHANGE: // 夹子改变了, 就是那个包容好几个ITEM的东东拉
    // 你想干啥,就自己写吧。
    TRACE2( "Folder selected: %d, Name: %s.\n", pOBInfo->nIndex, pOBInfo->lpszText); 
    break; case OBN_XT_ONLABELENDEDIT: // 编辑ITEM名称
    TRACE2( "Item edited: %d, New name: %s.\n", pOBInfo->nIndex, pOBInfo->lpszText); 
    break; case OBN_XT_ONGROUPENDEDIT: // 编辑组(夹子)的名称
    TRACE2( "Folder edited: %d, New name: %s.\n", pOBInfo->nIndex, pOBInfo->lpszText); 
    break; case OBN_XT_DRAGITEM: // 拖动ITEM
    TRACE3( "Dragging From: %d, To: %d, Name: %s.\n", pOBInfo->nDragFrom, pOBInfo->nDragTo, pOBInfo->lpszText); 
    break; case OBN_XT_ITEMHOVER: // 鼠标经过ITEM
    TRACE2( "Hovering Item: %d, Name: %s.\n", pOBInfo->nIndex, pOBInfo->lpszText); 
    break; case OBN_XT_DELETEITEM: // 删除ITEMif (!m_bDestroy && AfxMessageBox(_T("Are you sure you want to remove this folder shortcut?"), 
    MB_ICONWARNING|MB_YESNO) == IDNO) 

    // The user selected No, return FALSE to abort the action. 
    return FALSE; 

    TRACE2( "Item deleted: %d, Name: %s.\n", pOBInfo->nIndex, pOBInfo->lpszText); 
    break; case OBN_XT_DELETEFOLDER: // 删除夹子
    if (!m_bDestroy && AfxMessageBox(_T("Are you sure you want to remove the specified folder?"), 
    MB_ICONWARNING|MB_YESNO) == IDNO) 

    // The user selected No, return FALSE to abort the action. 
    return FALSE; 

    TRACE2( "Folder deleted: %d, Name: %s.\n", pOBInfo->nIndex, pOBInfo->lpszText); 
    break; 
    } return TRUE; 
    } 应该明白了吧?
      

  12.   

    to skt32 
    我已选定用BCG的库做界面了,不能再改用其他的,像Xtreme
      

  13.   

    BCG的OUTLOOKBAR和这些O***BAR是一脉相传的
    我只是给你释放一下还不行,你吧代码发过来吧
      

  14.   

    to skt32
    我还是不知道怎么做。我详细说一下我的理解:
    首先在发送者的类中定义“自定义消息”,然后在接收者中定义消息映射函数,
    现在发送者是:CBCGPOutlookBar或者CBCGPOutlookBarPane(后者实质是一个toolbar)
    现在接受者是:CFrameWnd如果要定义自定义消息,是否就要从CBCGPOutlookBarPane派生一个自己的类,然后定义自己的消息。
    然后在CFrameWnd加消息映射函数的声明和定义。但是如果像上面就样做,还是不能工作吧,因为好像没有sendmessage,postmessage,我想总应该将谁的OnLButtonxxx(不记得具体名)改写一下,然后sendmessage连带button的index出去才ok吧。and then我不知道了,靠你们帮一下忙了,怎么改?
    (我见ukyoking给我的代码是这样做的,但是我用的不是ukyoking的outlookbar类)
      

  15.   

    BCG 6.21
    vccode可以下载。这是BCG关于他的CBCGPButton(可以替换掉CButton)论述:
    If you want to handle Windows notification messages, such as BN_CLICKED, sent by a button control to its parent (usually a class derived from CDialog), add to the CDialog-derived object a message-map entry and message-handler member function for each message. The notifications sent by a CBCGPButton object are the same as those sent by a CButton object.
    我看了之后想,可否在CBCGPOutlookBarPane中识别这个Windows notification messages,然后sendmessage给CFrameWnd来处理?
    (具体怎么做,我不熟,还是要靠各位)
      

  16.   

    http://www.vckbase.com/tools/viewtools.asp?id=76BCG 6.21 pro》我看了之后想,可否在CBCGPOutlookBarPane中识别这个Windows notification messages,然后sendmessage给CFrameWnd来处理?
    说明一下,CBCGPButton在CBCGPOutlookBarPane里,CBCGPOutlookBarPane又在CBCGPOutlookBar里。CBCGPOutlookBar当然是CFrameWnd的成员变量。
      

  17.   

    把你的FrameWnd框架类的.h和.cpp贴出来吧
      

  18.   

    TMD,最讨厌这个winXp我敲几十下按钮它不应。我下周就删了他,TMD我最讨厌我用的东西比我“智能”,下星期就删了它。http://bjms10.163.net/cgi/ldmsapp/Frame.rar?sid=TAuPlmCqdwIAiAFV&mid=BM7jCgi6oNx77ruphFq6&part=2&funcid=readpart&msglevel=0&filename=Frame.rar上面是我的CFrameWnd类,和主View类的代码,有需要的朋友帮我看一下。
      

  19.   

    //resource.h中
    #define ID_CMD_BASE       200//MainFrame.h中
    添加类的消息映射函数       afx_msg void       OnOutlookButton( UINT uiCmdID );//MainFrame.cpp中
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
           //{{AFX_MSG_MAP(CMainFrame)
           ON_WM_CREATE()
           //}}AFX_MSG_MAP
           ON_REGISTERED_MESSAGE(BCGM_TOOLBARMENU, OnToolbarContextMenu)
           ON_COMMAND_RANGE(ID_CMD_BASE+1, ID_CMD_BASE+50, OnOutlookButton) //新增
    END_MESSAGE_MAP()afx_msg void CMainFrame::       OnOutlookButton( UINT uiCmdID ) 
    {
    switch(uiCmdID) ... case...
    }