友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
富士康小说网 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

深入浅出MFC第2版(PDF格式)-第60部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!





                        主窗口产生之际立刻会发出WM_CREATE,我们应该利用这时机把工具栏和状态列建立 



                        起来。为了拦截WM_CREATE,首先需在Message Map 中设定「映射项目」: 



                        BEGIN_MESSAGE_MAP(CMyMDIFrameWnd; CMDIFrameWnd) 

                                ON_WM_CREATE() 

                        END_MESSAGE_MAP() 



                        ON_ WM_CREATE 这个宏表示,只要WM_CREATE 发生,我的OnCreate 函数就应该被 



                        调用。下面是由AppWizard 产生的OnCreate 标准动作: 



                        int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 

                        { 

                            if (CMDIFrameWnd::OnCreate(lpCreateStruct) == …1) 

                                    return …1; 



                            if (!m_wndToolBar。Create(this) || 

                                    !m_wndToolBar。LoadToolBar(IDR_MAINFRAME)) 

                            { 

                                    TRACE0(〃Failed to create toolbarn〃); 

                                    return …1;      // fail to create 

                            } 



                            if (!m_wndStatusBar。Create(this) || 

                                    !m_wndStatusBar。SetIndicators(indicators; 

                                      sizeof(indicators)/sizeof(UINT))) 

                            { 

                                    TRACE0(〃Failed to create status barn〃); 

                                    return …1;      // fail to create 

                            } 



440 


…………………………………………………………Page 503……………………………………………………………

                                                 第7章    簡單而完整:MFC 骨幹程式 



        // TODO: Remove this if you don't want tool tips or a resizeable toolbar 

        m_wndToolBar。SetBarStyle(m_wndToolBar。GetBarStyle() | 

                CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); 



        // TODO: Delete these three lines if you don't want the toolbar to 

        //  be dockable 

        m_wndToolBar。EnableDocking(CBRS_ALIGN_ANY); 

        EnableDocking(CBRS_ALIGN_ANY); 

        DockControlBar(&m_wndToolBar); 



        return 0; 

    } 



 其中有四个动作与工具栏和状态列的产生及设定有关: 



   m_wndToolBar。Create(this) 表示要产生一个隶属于this       (也就是目前这个对象, 

 



  也就是主窗口)的工具栏。 



   m_wndToolBar。LoadToolBar(IDR_MAINFRAME) 将RC 档中的工具栏资源载 

 



  入。IDR_MAINFRAME 在RC 档中代表两种与工具栏有关的资源: 



    IDR_MAINFRAME BITMAP MOVEABLE PURE 〃RESTOOLBAR。BMP〃 



    IDR_MAINFRAME TOOLBAR DISCARDABLE  16; 15 

    BEGIN 

        BUTTON      ID_FILE_NEW 

        BUTTON      ID_FILE_OPEN 

        BUTTON      ID_FILE_SAVE 

            SEPARATOR 

        BUTTON      ID_EDIT_CUT 

        BUTTON      ID_EDIT_COPY 

        BUTTON      ID_EDIT_PASTE 

            SEPARATOR 

        BUTTON      ID_FILE_PRINT 

        BUTTON      ID_APP_ABOUT 

    END 



 LoadToolBar  函数一举取代了前一版的LoadBitmap + SetButtons 两个动作。 



 LoadToolBar  知道如何把BITMAP 资源和TOOLBAR 资源搭配起来,完成工具栏的 



 设定。当然啦,如果你不是使用VC++资源工具来编辑工具栏,BITMAP 资源和 



 TOOLBAR 资源就可能格数不符,那是不被允许的。TOOLBAR 资源中的各ID 值就 



                                                                                     441 


…………………………………………………………Page 504……………………………………………………………

                   第篇    湷觥 FC  程式設計 



                      是菜单项目的子集合,因为所谓工具栏就是把比较常用的菜单项目集合起来以按钮 



                     方式提供给使用者。 



                     m_wndStatusBar。Create(this) 表示要产生一个隶属于this 对象(也就是目前这个 



                     对象,也就是主窗口)的状态列。 



                     m_wndStatusBar。SetIndicators(;。。。)  的第一个参数是个数组;第二个参数是数组 



                     元素个数。所谓Indicator 是状态列最右侧的「指示窗口」,用来表示大写键、 



                     数字键等的On/Off 状态。AFXRES。H  中定义有七种indicators : 



                      #define ID_INDICATOR_EXT     0xE700  // extended selection indicator 

                      #define ID_INDICATOR_CAPS  0xE701  // cap lock indicator 

                      #define ID_INDICATOR_NUM     0xE702  // num lock indicator 

                      #define ID_INDICATOR_SCRL  0xE703  // scroll lock indicator 

                      #define ID_INDICATOR_OVR     0xE704  // overtype mode indicator 

                      #define ID_INDICATOR_REC     0xE705  // record mode indicator 

                      #define ID_INDICATOR_KANA  0xE706  // kana lock indicator 



                      本例使用其中三种: 



                         static UINT indicators '' = 

                          static UINT indicators '' = 

                         {{ 

                                 ID_SEPARATOR; // status line indicator 

                                  ID_SEPARATOR; // status line indicator 

                                 ID_INDICATOR_CAPS; 

                                  ID_INDICATOR_CAPS; 

                                 ID_INDICATOR_NUM; 

                                  ID_INDICATOR_NUM; 

                                 ID_INDICATOR_SCRL; 

                                  ID_INDICATOR_SCRL; 

                         }; 

                          }; 



               鼠标拖放(Drag and Drop) 



                     MFC 程序很容易拥有Drag and Drop 功能。意思是,你可以从Shell  (例如Windows 95 



                     的文件总管)中以鼠标拉动一个文件,拖到你的程序中,你的程序因而打开此文件并读 



                     其内容,将内容放到一个Document Frame 窗口中。甚至,使用者在Shell 中以鼠标对 



                     某个文件文件(你的应用程序的文件文件)快按两下,也能激活你这个程序,并自动完成开 



                     档,读档,显示等动作。 



442 


…………………………………………………………Page 505……………………………………………………………

                                             第7章    簡單而完整:MFC 骨幹程式 



在SDK 程序中要做到Drag and Drop ,并不算太难,这里简单提一下它的原理以及作 



法。当使用者从Shell 中拖放一个文件到程序A,Shell 就配置一块全域内存,填入被 



拖曳的文件名称(包含路径),然后发出WM_DROPFILES 传到程序A的消息队列。程 



式A取得此消息后,应该把内存的内容取出,再想办法开档读档。 



并不是张三和李四都可以收到WM_DROPFILES ,只有具备WS_EX_ACCEPTFILES  风格 



的窗口才能收到此一消息。欲让窗口具备此一风格,必须使用CreateWindowEx                        (而不 



是传统的CreateWindow),并指定第一个参数为WS_EX_ACCEPTFILES 。 



剩下的事情就简单了:想办法把内存中的文件名和其它信息取出(内存handle 放在 



WM_DROPFILES  消息的wParam  中)。这件事情有DragQueryFile 和DragQueryPoint 



两个API  函数可以帮助我们完成。 



SDK 的方法真的不难,但是MFC 程序更简单: 



    BOOL CScribbleApp::InitInstance() 

    { 

       。。。 

       // Enable drag/drop open 

       m_pMainWnd…》DragAcceptFiles(); 



       // Enable DDE Execute open 

       EnableShellOpen(); 

       RegisterShellFileTypes(TRUE); 

       。。。 

    } 



 这三个函数的用途如下: 

   

CWnd::DragAcceptFile(BOOL bAccept=TRUE); 参数TRUE 表示你的主窗口以 



  及每一个子窗口(文件窗口)都愿意接受来自Shell 的拖放文件。CFrameWnd  内 



  有一个OnDropFiles 成员函数,负责对WM_DROPFIELS  消息做出反应,它 



  会通知application 对象的OnOpenDocument   (此函数将在第8章介绍),并夹 



  带被拖放的文件的名称。 



                                                                               443 


…………………………………………………………Page 506……………………………………………………………

                第篇    湷觥 FC  程式設計 



                 CWinApp::EnableShellOpen(); 当使用者在Shell 中对着本程序的文件文件快按 



                  两下时,本程序能够打开文件并读内容。如果当时本程序已执行,Framework 



                  不会再执行起程序的另一副本,而只是以DDE             (Dynamic Data Exchange ,动态 



                  资料交换)通知程序把文件(文件)读进来。DDE 处理例程内建在CDocManager 



                  之中(第8章会谈到这个类别)。也由于DDE  的能力,你才能够很方便地把 



                  文件图标拖放到打印机图标上,将文件打印出来。 



                   通常此函数后面跟随着RegisterShellFileTypes 。 



                 CWinApp::RegisterShellFileTypes(); 此函数将向Shell 注册本程序的文件型 



                  态。有了这样的注册动作,使用者在Shell 的双击动作才有着力点。这个函数 



                  搜寻Document Template  串行中的每一种文件类型,然后把它加到系统所维护 



                  的registry (登录数据库)中。 



                  在传统的Windows 程序中,对Registry  的注册动作不外乎两种作法,一是准 



                  备一个。reg 档,由使用者利用Windows 提供的一个小工具regedit。exe ,将。reg 



                  合并到系统的Registry  中。第二种方法是利用::RegCreateKey 、::RegSetValue 



                  等Win32  函数,直接编辑Registry 。MFC 程序的作法最简单,只要调用 



                  CWinApp::RegisterShellFileTypes  即可。 



                 必须注意的是,如果某一种文件类型已经有其对应的应用程序(例如。txt 对应 



                 Notepad ,。bmp 对应PBrush ,。ppt 对应PowerPoint ,。xls 对应Excel ),那么你的程序 



                 就不能够横刀夺爱。如果本例Scribble 的文件档扩展名为。txt ,使用者在Shell 中双击 



                 这种文件,激活的将是Notepad 而不是Scribble。 



                 另一个要注意的是,拖放动作可以把任何类型的文件文件拉到你的窗口中,并不只限于你 



                 所注册的文件类型。你可以把。bmp 文件从Shell 拉到Scribble 窗口,Scribble 程序一样 



                 会读它并为它准备一个窗口。想当然耳,那会是个无言的结局: 



444 


…………………………………………………………Page 507……………………………………………………………

                                             第7章    簡單而完整:MFC 骨幹程式 



消息映射(Message Map) 



    每一个衍生自CCmdTarget 的类别都可以有自己的Message Map  以处理消息。首先你应 



    该在类别声明处加上DECLARE_MESSAGE_MAP 宏, 然后在。CPP 档中使用 



    BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP 两个宏,宏中间夹带的就是「讯 



    息与函数对映关系」的一笔笔记录。 



    你可以从图7…6 那个浓缩的Scribble 源代码中看到各类别的Message Map 。 



     本例CScribbleApp 类别接受四个WM_MAND 消息: 



        BEGIN_MESSAGE_MAP(CScribbleApp; CWinApp) 



          ON_MAND(ID_APP_ABOUT; OnAppAbout) 



          ON_MAND(ID_FILE_NEW; CWinApp::OnFileNew) 



          ON_MAND(ID_FILE_OPEN; CWinApp::OnFileOpen) 



          ON_MAND(ID_FILE_PRINT_SETUP; CWinApp::OnFilePrintSetup) 



        END_MESSAGE_MAP() 



    除了ID_APP_ABOUT 是由我们自己设计一个OnAppAbout 函数处理之,其它三个讯 



    息都交给CWinApp 成员函数去处理,因为那些动作十分制式,没什么好改写的。到底 



    有哪些制式动作呢?看下一节! 



                                                                           445 


…………………………………………………………Page 508……………………………………………………………

               第篇    湷觥 FC  程式設計 



        标准菜单File / Edit / View / Window / Help 



              仔细观察你所能搜集到的各种MDI 程序,你会发现它们几乎都有两组菜单。一组是当 



              没有任何子窗口(文件窗口)存在时出现(本例代码是IDR_MAINFRAME ): 



              另一组则是当有任何子窗口(文件窗口)存在时出现(本例代码是IDR_SCRIBTYPE ): 



446 


…………………………………………………………Page 509……………………………………………………………

                                            第7章    簡單而完整:MFC 骨幹程式 



前者多半只有【File 】、【View 】、【Help 】等选项,后者就复杂了,程序所有的功能都 



在上面。本例的IDR_MAINFRAME 和IDR_SCRIBTYPE 就代表RC 档中的两组菜单。 



当使用者打开一份文件文件,程序应该把主窗口上的菜单换掉,这个动作在SDK 程序中 



由程序员负责,在MFC 程序中则由Framework 代劳了。 



拉下这些菜单仔细瞧瞧,你会发现Framework 真的已经为我们做了不少琐事。凡是菜单 



项目会引起对话框的,像是Open 对话框、Save As 对话框、Print 对话框、Print Setup 对 



话盒、Find 对话框、Replace 对话框,都已经恭候差遣;Edit 菜单上的每一项功能都已 



经可以应用在由CEditView 掌控的文字编辑器上;File 菜单最下方记录着最近使用过的 



 (所谓LRU )四个文件名称(个数可在Appwizard  中更改),以方便再开启;View 选 



单允许你把工具栏和状态列设为可见或隐藏;Window 菜单提供重新排列子窗口图标的 



能力,以及对子窗口的排列管理,包括卡片式(Cascade )或拼贴式(Tile )。 



下表是预设之菜单命令项及其处理例程的摘要整理。最后一个字段「是否预有关联」如 



果是Yes ,意指只要你的程序菜单中有此命令项,当它被选按,自然就会引发命令处理 



例程,应用程序不需要在任何类别的Message Map 中拦截此命令消息。但如果是No , 



表示你必须在应用程序中拦截此消息。 



 菜单内容           命令项ID                     预设的处理函数           预有关联 



 File 



New                 ID_FILE_NEW           CWinApp::OnFileNew         No 



 Open               ID_FILE_OPEN          CWinApp::OnFileOpen        No 



 Close              ID_FILE_CLOSE         CDocument::OnFileClose     Yes 



 Save               ID_FILE_SAVE          CDocument::OnFileSave      Yes 



 Save As            ID_FILE_SAVEAS        CDocument::OnFileSaveAs    Yes 



Print               ID_FILE_PRINT         CView::OnFilePrint         No 



Print Pre&view      ID_FILE_PRINT_PREVIEW CView::OnFilePrintPreview  No 



Print Setup         ID_FILE_PRINT_SETUP   CWinApp::OnFilePrintSetup  No 



 〃Recent File Name〃 ID_FILE_MRU_FILE1~4   CWinApp::OnOpenRecentFile  Yes 



                                                                             447 


…………………………………………………………Page 510……………………………………………………………

                    第篇    湷觥 FC  程式設計 



                     菜单内容           命令项ID                      预设的处理函数           预有关联 



                    Exit                  ID_APP_EXIT               CWinApp::OnFileExit           Yes 



                    Edit 



                    Undo                  ID_EDIT_UNDO              None 



                    Cut                   ID_EDIT_CUT               None 



                    Copy                  ID_EDIT_COPY              None 



                    Paste                 ID_EDIT_PASTE             None 



                    View 



                    Toolbar               ID_VIEW_TOOLBAR           FrameWnd::OnBarCheck          Yes 



                    Status Bar            ID_VIEW_STATUS_BAR        FrameWnd::OnBarCheck          Yes 



                             (         ) 

                    Window    MDI only 



                    New Window            ID_WINDOW_NEW             MDIFrameWnd::OnWindowNew      Yes 



                    Cascade               ID_WINDOW_CASCADE         MDIFrameWnd::OnWindowCmd      Yes 



                    Tile                  ID_WINDOW_TILE_HORZ       MDIFrameWnd::OnWindowCmd      Yes 



 
返回目录 上一页 下一页 回到顶部 9 10
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!