这算是一个演示程序吧,想不到上下文菜单也是採用ON_COMMAND宏来进行消息映射,在这里,我发现一个问题:从CWnd派生的类ON_UPDATE_COMMAND_UI_RANGE似乎没有效果,不知道应该再加点什么,可是从CFrameWnd派生出来问题就不会发生,真是奇怪……
看看从CWnd派生出来的效果:
contextMenuDemo.h
#pragma once
class CMyApp : public CWinApp {
virtual BOOL InitInstance();
};
class CMainWindow : public CWnd {
public:
CMainWindow();
protected:
int m_nShape;
void PostNcDestroy();
int OnCreate(LPCREATESTRUCT lpCreateStruct);
void OnPaint();
void OnContextMenu(CWnd* pWnd, CPoint point);
void OnShape(UINT nID);
void OnUpdateShape(CCmdUI* pCmdUI);
DECLARE_MESSAGE_MAP()
};
contextMenuDemo.cpp:
#include <afxwin.h>
#include "contextMenuDemo.h"
#include "resource.h"
CMyApp myApp;
BOOL CMyApp::InitInstance() {
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMainWindow, CWnd)
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_CONTEXTMENU()
ON_COMMAND_RANGE(ID_SHAPE_RECT, ID_SHAPE_CIRCLE, OnShape)
ON_UPDATE_COMMAND_UI_RANGE(ID_SHAPE_RECT, ID_SHAPE_CIRCLE, OnUpdateShape)
END_MESSAGE_MAP()
CMainWindow::CMainWindow() {
CString strWndClass = AfxRegisterWndClass(0,
AfxGetApp()->LoadStandardCursor(IDC_ARROW),
(HBRUSH)(COLOR_WINDOW + 1),
AfxGetApp()->LoadStandardIcon(IDI_WINLOGO));
CreateEx(0,
strWndClass,
_T("玩玩了"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL);
m_nShape = ID_SHAPE_RECT;
}
void CMainWindow::PostNcDestroy() {
delete this;
}
int CMainWindow::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if(CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
void CMainWindow::OnContextMenu(CWnd* pWnd, CPoint point) {
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CPoint pt = point;
ScreenToClient(&pt);
CRect rc;
GetClientRect(&rc);
CMenu* pMenu = menu.GetSubMenu(0);
if(rc.PtInRect(pt)) {
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x,
point.y, AfxGetMainWnd());
return;
}
CWnd::OnContextMenu(pWnd, point);
}
void CMainWindow::OnShape(UINT nID) {
m_nShape = nID;
Invalidate();
}
void CMainWindow::OnPaint() {
CPaintDC dc(this);
switch(m_nShape) {
case ID_SHAPE_RECT:
dc.Rectangle(100, 100, 500, 500);
break;
case ID_SHAPE_CIRCLE:
dc.Ellipse(100, 100, 500, 500);
break;
}
}
void CMainWindow::OnUpdateShape(CCmdUI* pCmdUI) {
pCmdUI->SetCheck(pCmdUI->m_nID == m_nShape);
}
执行效果没有太大的问题,就是SetCheck没有效果……
我们从CFrameWnd派生出来的话,问题就好了:
头文件:
#pragma once
class CMyApp : public CWinApp {
virtual BOOL InitInstance();
};
class CMainWindow : public CFrameWnd {
public:
CMainWindow();
protected:
int m_nShape;
//void PostNcDestroy();
//int OnCreate(LPCREATESTRUCT lpCreateStruct);
void OnPaint();
void OnContextMenu(CWnd* pWnd, CPoint point);
void OnShape(UINT nID);
void OnUpdateShape(CCmdUI* pCmdUI);
DECLARE_MESSAGE_MAP()
};
实现文件:
#include <afxwin.h>
#include "contextMenuDemo.h"
#include "resource.h"
CMyApp myApp;
BOOL CMyApp::InitInstance() {
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_CONTEXTMENU()
ON_COMMAND_RANGE(ID_SHAPE_RECT, ID_SHAPE_CIRCLE, OnShape)
ON_UPDATE_COMMAND_UI_RANGE(ID_SHAPE_RECT, ID_SHAPE_CIRCLE, OnUpdateShape)
END_MESSAGE_MAP()
CMainWindow::CMainWindow() {
Create(NULL, _T("玩玩"));
m_nShape = ID_SHAPE_RECT;
}
void CMainWindow::OnContextMenu(CWnd* pWnd, CPoint point) {
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CPoint pt = point;
ScreenToClient(&pt);
CRect rc;
GetClientRect(&rc);
CMenu* pMenu = menu.GetSubMenu(0);
if(rc.PtInRect(pt)) {
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x,
point.y, AfxGetMainWnd());
return;
}
CWnd::OnContextMenu(pWnd, point);
}
void CMainWindow::OnShape(UINT nID) {
m_nShape = nID;
Invalidate();
}
void CMainWindow::OnPaint() {
CPaintDC dc(this);
switch(m_nShape) {
case ID_SHAPE_RECT:
dc.Rectangle(100, 100, 500, 500);
break;
case ID_SHAPE_CIRCLE:
dc.Ellipse(100, 100, 500, 500);
break;
}
}
void CMainWindow::OnUpdateShape(CCmdUI* pCmdUI) {
pCmdUI->SetCheck(pCmdUI->m_nID == m_nShape);
}