hn4u @ Last updated 21/11/04 22:42
Go to my homepage at http://4u.jcisio.com
Full version available at http://4u.jcisio.com/r/article342.htm

Không rõ

Tự vẽ một menu

Trong File, bấm New để tạo một project mới.Chọn MFC Application Wizard (exe). Trong tên project, đánh OwnerdrawMenu và bấm OK. Bước tiếp  chọn Single Document.Sau đó bấm Finish.

Bây giờ tạo dữ liệu của menu.Chỉ cần dùng một lớp đơn giản, là thành viên của CString, lưu giữ các mục của menu.Bấm chuột phải vào OwnerdrawMenu classes trong cửa sổ ClasView, chọn New Class.Chọn Generic Class..Trong phần Name, đánh CMyMenuData.Cuối cùng bấm OK

Thêm một giá trị toàn cục thuộc CString gọi là m_strCaption.Kế tiếp , chúng ta tạo một lớp menu.Bấm chuột phải OwnerdrawMenu classes trong ClassView, chọn New Class, Chọn Generic Class. trong mục Name đánh CMyMenu.Trong mục Base Classes, đánh CMenu  trong phần Derived From và chọn public trong listbox As.

Lớp menu của chúng ta đã được tạo.chúng ta sẽ thêm 3 hàm và một số câu include và 2 biến thành viên trong tập tin header CMyMenu

Mã lệnh (C++)
#include MyMenuData.h
#include <vector>
using namespace std;

public:
void ChangeToOwnerDraw(CMyMenu* pMyMenu);
virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );
virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
private:
vector<CMyMenu*> rgpMyMenu;
vector<CMyMenuData*> rgpMyMenuData;


void CMyMenu::ChangeToOwnerDraw(CMyMenu *pMyMenu)
{
CString str;
CMyMenu* pMenu;
CMyMenuData* pMenuData;
int iMenuCount = pMyMenu->GetMenuItemCount();
UINT nID; //use to hold the identifier of the menu items
for (int i=0; i<iMenuCount; i++)
{
pMyMenu->GetMenuString(i, str, MF_BYPOSITION);
pMenu = 0;
pMenuData = 0;
pMenuData = new CMyMenuData;
pMenuData->m_strCaption = str;
rgpMyMenuData.push_back(pMenuData);

if (pMyMenu->GetSubMenu(i))
{
pMyMenu->ModifyMenu(i,
MF_BYPOSITION | MF_OWNERDRAW,
0,
(LPCTSTR)pMenuData);
pMenu = new CMyMenu;
rgpMyMenu.push_back(pMenu);
HMENU hMenu = pMyMenu->GetSubMenu(i)->GetSafeHmenu();
pMenu->Attach(hMenu);
ChangeToOwnerDraw(pMenu);
}
else
{
nID = pMyMenu->GetMenuItemID(i);
pMyMenu->ModifyMenu(i,
MF_BYPOSITION | MF_OWNERDRAW,
(UINT)nID,
(LPCTSTR)pMenuData);
}
}
}

void CMyMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
CMyMenuData* pMyMenuData =
(CMyMenuData*)lpMeasureItemStruct->itemData;
CString str = pMyMenuData->m_strCaption;
lpMeasureItemStruct->itemHeight = 23;0
lpMeasureItemStruct->itemWidth = str.GetLength()*7;
}

void CMyMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
pDC->FillSolidRect(&lpDrawItemStruct->rcItem,
RGB(255,150,0));

if ((lpDrawItemStruct->itemState & ODS_SELECTED) &&
(lpDrawItemStruct->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem,
RGB(0,150,255));
}

CMyMenuData* pMyMenuData =
(CMyMenuData*)lpDrawItemStruct->itemData;

CString str = pMyMenuData->m_strCaption;
pDC->TextOut(lpDrawItemStruct->rcItem.left,
lpDrawItemStruct->rcItem.top, str);
}

CMyMenu::~CMyMenu()
{
int iCount = rgpMyMenu.size();
for (int i=0; i<iCount; i++)
{
rgpMyMenu[i]->Detach();
delete rgpMyMenu[i];
rgpMyMenu[i] = 0;
}
iCount = rgpMyMenuData.size();
for (i=0; i<iCount; i++)
{
delete rgpMyMenuData[i];
rgpMyMenuData[i] = 0;
}
}

Bây giờ chúng ta sử dụng lớp CMyMenu trong lớp CMainFrame.Thêm vào trong MainFrm.h.

Mã lệnh (C++)
#include MyMenu.h
private:
CMyMenu* pMyMenu;

Dưới cùng của hàm CMainFrame::OnCreate, nhưng trước dòng return 0;, thêm các dòng mã sau:

Mã lệnh (C++)
pMyMenu = new CMyMenu;
HMENU hMenu = ::GetMenu(GetSafeHwnd());
pMyMenu->Attach(hMenu);
SetMenu(pMyMenu);
pMyMenu->ChangeToOwnerDraw(pMyMenu);

Chúng ta cũng thêm một message handler trong OnDestory.Bấm phải của CMainFrame trong ClassView, chọn Add Windows Message Handler.. Thêm WM_DESTORY handler.Đoạn mã của OnDestroy như sau:

Mã lệnh (C++)
void CMainFrame::OnDestroy()
{
CFrameWnd::OnDestroy();

if (pMyMenu)
{
pMyMenu->Detach();
delete pMyMenu;
pMyMenu = 0;
}
}

Bấm F7 để chạy thử đoạn code trên.


hainam4u @ Last updated 21/11/04 22:42
Go to my homepage at http://4u.jcisio.com