MFC有關菜單的編程實現

本節學習了菜單編程方面的內容,包括靜態菜單操作和動態菜單操作兩大塊。

靜態菜單操作包括標記菜單,默認菜單,圖形菜單的實現原理及具體實現,快捷彈出菜單的實現方式及其命令響應函數的添加。

動態菜單操作主要包括:如何讓程序運行時產生新的子菜單和菜單項,以及如何手工地爲這些新產生的菜單項命令添加消息響應處理函數。

本節還實現瞭如何在頂層窗口,即框架類窗口中截獲對菜單命令的處理。

通過這節還應該瞭解Windows中消息的分類,以及菜單命令消息的路由過程,進一步熟悉Cstring類的應用。

 

靜態菜單操作

//1.標記菜單(2種方法)

       //GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION| MF_CHECKED);     //通過菜單項的索引設置一個標記菜單

       //GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND| MF_CHECKED);  //通過菜單項的標識設置一個標記菜單

 

       //2.默認菜單

       //GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);      //通過菜單項的索引設置一個默認菜單,最後一個參數爲TRUE

       //GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN,FALSE);   //通過菜單項的標識設置一個默認菜單最後一個參數爲FALSE

       //GetMenu()->GetSubMenu(0)->SetDefaultItem(5,TRUE);  //設置打印菜單項時索引時5,不是4,因爲分隔欄在子菜單中是佔據索引位置的

       //一個子菜單隻能有一個默認菜單項

 

       //3.圖形標記菜單

 

       /*CStringstr;

       str.Format("x=%d,y=%d",GetSystemMetrics(SM_CXMENUCHECK),GetSystemMetrics(SM_CYMENUCHECK));

       //CString類的Format函數可以按照一定的格式把內容格式化,然後將結果保存到CString類型的字符串對象中

       //GetSystemMetrics()函數可以取得窗口上各種資源的尺寸,根據參數決定

       //根據取得的尺寸信息可知,位圖大小應該是13*13;

       MessageBox(str);*/

 

       //m_bitmap.LoadBitmap(IDB_BITMAP1);

       //GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,&m_bitmap);//運行程序發現不顯示位圖,

       //原因在於位圖太大,只是顯示了位圖左上角的一小部分內容。

 

       //4.禁用菜單項

   //GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION |MF_DISABLED | MF_GRAYED);

       //GetMenu()->GetSubMenu(0)->EnableMenuItem(ID_FILE_OPEN,MF_BYCOMMAND| MF_DISABLED | MF_GRAYED);

       //在構造函數中修改成員變量才能使這行代碼起作用m_bAutoMenuEnable= FALSE;

       //MF_DISABLED| MF_GRAYED這兩個標誌一起使用

 

   //5.移除和裝載菜單

       //SetMenu(NULL);//移除

   //裝載

       //CMenumenu;

   //menu.LoadMenu(IDR_MAINFRAME);

       //SetMenu(&menu);  

       //menu是個局部變量,在程序運行時,點擊“打印預覽”,關閉“打印預覽”,再關閉程序,程序會報錯

       //解決辦法是把menu定義爲CMainFram類的成員變量

       //還可以用Detach函數把菜單句柄與這個菜單對象分離

       //menu.Detach();

 

 

       return0;

}

 

       //m_bAutoMenuEnable= FALSE;  

       //一旦在CMainFrame類的構造函數中把成員變量m_bAutoMenuEnable =FALSE;後,就不需要對ON_UPDATE_COMMAND_UI

       //或ON_COMMAND消息進行響應處理了,CMenu類的EnableMenuItem函數將能正常工作。

       //但是在Menu程序編輯子菜單下的幾個菜單項不在以灰色顯示了,因爲m_bAutoMenuEnable= FALSE後,

       //MFC就不在利用它的菜單命令更新機制去判斷哪個菜單可以使用,哪個菜單不能夠使用,所以其也就不能根據菜單項的狀態以不同的外觀

       //來顯示。而菜單能否使用這些判斷操作,就需要我們自己去完成了

       //說實話,命令更新機制講的不清楚啊!不明白啊!

 

//6.MFC菜單命令更新機制

//在消息映射中添加ON_UPDATE_COMMAND_UI宏來捕獲CN_UPDATE_COMMAND_UI消息

void CMainFrame::OnUpdateEditCut(CCmdUI*pCmdUI)

{

       //TODO: Add your command update UI handler code here

       //pCmdUI->Enable();//在這樣的消息中帶有一個指向CCmdUI對象的指針,可以用它調用相應的功能函數

       //在工具欄中剪切的標識和菜單欄中的剪切標識是一樣,所以兩者都被啓用了。

       if(2== pCmdUI->m_nIndex) //判斷當前是否是新建菜單項,實際中無需判斷,MFC調用菜單命令更新函數時,已經確定了特定的菜單項。

              pCmdUI->Enable();  

}

 

void CMainFrame::OnUpdateFileNew(CCmdUI*pCmdUI)

{

       //TODO: Add your command update UI handler code here

       //if(ID_FILE_NEW== pCmdUI->m_nID)  //根據標識判斷,工具欄中,菜單欄中的剪切都被禁用

       if(0== pCmdUI->m_nIndex)    //根據索引判斷,工具欄中的剪切不被禁用,兩者索引不同!

              pCmdUI->Enable(FALSE);

}

//如果要在程序中設置某個菜單項的狀態,首先通過ClassWizard爲這個菜單項添加ON_UPDATE_COMMAND_UI消息響應函數,然後再這個

//函數中進行狀態的設置即可!

 

void CMainFrame::OnShow()

{

       //TODO: Add your command handler code here

       MessageBox("Mainshow");

}

 

//動態菜單操作

       //1.添加菜單項目

       /*CMenumenu;

       menu.CreateMenu();//創建一個菜單,然後將其與一個CMenu對象相關聯起來。

       GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"Test");  //添加菜單項

       menu.Detach();//將菜單句柄與菜單對象之間的關聯斷開*/

 

       //2.插入菜單項目

       /*CMenumenu;

       menu.CreateMenu();//創建一個菜單,然後將其與一個CMenu對象相關聯起來。

       GetMenu()->InsertMenu(2,MF_POPUP|MF_BYPOSITION, (UINT)menu.m_hMenu,"Test");

       menu.AppendMenu(MF_STRING,IDM_HELLO,"Hello");

       menu.AppendMenu(MF_STRING,112,"Bye");

       menu.AppendMenu(MF_STRING,113,"Mybole");

       menu.Detach();

       GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,114,"Welcome");

       GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,MF_STRING| MF_BYCOMMAND,115,"VC編程");

       //3.刪除菜單

       GetMenu()->DeleteMenu(1,MF_BYPOSITION);

       GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION);*/

 

//4.動態添加的菜單項的命令響應

void CMainFrame::OnHello()

{

       MessageBox("Hello");

}

 

ON_COMMAND(IDM_HELLO,OnHello)

afx_msg void OnHello();

 

//5.電話本示例程序

void CMenu2View::OnChar(UINT nChar, UINTnRepCnt, UINT nFlags)

{

       CClientDCdc(this);

       if(0x0d== nChar)

       {

              if(0== ++m_nIndex)

              {

                     m_menu.CreatePopupMenu();

                     GetParent()->GetMenu()->AppendMenu(MF_POPUP,(UINT)m_menu.m_hMenu,"phoneBook");//菜單是框架類窗口的,要用GetParent()

                     //取到框架窗口的指針

           GetParent()->DrawMenuBar();//取得框架窗口的指針,然後重繪菜單欄,纔會在按下回車鍵後顯示先添加的菜單!

                     //在CMainFrame中不需要這樣做,是因爲代碼是在OnCreate中添加的,窗口還未創建完成

                     //而此時窗口已經創建完成

              }

              m_menu.AppendMenu(MF_STRING,IDM_PHONE1+ m_nIndex,m_strLine.Left(m_strLine.Find(' ')));//取得輸入的內容空格以前的內容,添加到菜單項中

              m_strArray.Add(m_strLine);//m_strArray是定義的一個CStringArray的集合類

              //MFC爲我們提供了一些非常有用的集合類,這些集合類類似於數組的功能,但他們可以很方便的動態增加和刪除元素。

              m_strLine.Empty();//在按下回車鍵後,清空字符串的內容,再次輸入時顯示的就是新輸入的,不會在先前的後面輸出了

              Invalidate();//讓窗口的整個客戶區無效,這樣,當下一條WM_PAINT消息發生時,窗口就會被更新。不然再次輸入的內容

              //會再先前輸入的內容上面顯示。默認參數是TRUE,在窗口重繪時就會把窗口的背景擦除掉。爲FALSE時保留窗口的背景

       }

       else

       {

              m_strLine+= nChar;

              dc.TextOut(0,0,m_strLine);

       }

       CView::OnChar(nChar,nRepCnt, nFlags);

}

 

void CMenu2View::OnPhone1()

{

       //TODO: Add your command handler code here

       CClientDCdc(this);

       dc.TextOut(0,0,m_strArray.GetAt(0));

}

 

void CMenu2View::OnPhone2()

{

       //TODO: Add your command handler code here

       CClientDCdc(this);

       dc.TextOut(0,0,m_strArray.GetAt(1));

}

 

void CMenu2View::OnPhone3()

{

       //TODO: Add your command handler code here

       CClientDCdc(this);

       dc.TextOut(0,0,m_strArray.GetAt(2));

}

 

void CMenu2View::OnPhone4()

{

       //TODO: Add your command handler code here

       CClientDCdc(this);

       dc.TextOut(0,0,m_strArray.GetAt(3));

}

 

       ON_COMMAND(IDM_PHONE1,OnPhone1)   //這些代碼要放到註釋宏外面,如果放在裏面,在ClassWizard對話框中,在Message Maps選項卡下

       ON_COMMAND(IDM_PHONE2,OnPhone2)   //的Member functions列表中就會列出這些函數,放在外面就不會列出來。當ClassWizard發現

       ON_COMMAND(IDM_PHONE3,OnPhone3)   //菜單項已經被刪除了的時候,它就會把已爲該菜單項添加的消息映射宏也刪除了,這樣,消息映射宏

       ON_COMMAND(IDM_PHONE4,OnPhone4)   //的三個環節就斷了一環,程序就會出錯。

 

       afx_msgvoid OnPhone1();   //放在兩個註釋宏之間也沒有錯

       afx_msgvoid OnPhone2();   //但爲了區分這是自己手動添加的,可以把它們拿出來放在兩個AFX_MSG註釋宏之後。

       afx_msgvoid OnPhone3();

       afx_msgvoid OnPhone4();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章