MFC中自由使用自定义消息

消息映射、循环机制是Windows程序运行的基本方式。VC++ MFC 中有许多现成的消息句柄,可当我们需要完成其它的任务,需要自定义消息,就遇到了一些困难。在MFC ClassWizard中不允许添加用户自定义消息,所以我们必须在程序中添加相应代码,以便可以象处理其它消息一样处理自定义消息。

  通常的做法是采取以下步骤:

  第一步:定义消息。

  推荐用户自定义消息至少是WM_USER+100,因为很多新控件也要使用WM_USER消息。

#define WM_MY_MESSAGE (WM_USER+100)

  第二步:实现消息处理函数。该函数使用WPRAM和LPARAM参数并返回LPESULT。

LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
// TODO: 处理用户自定义消息

...
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_MAP

END_MESSAGE_MAP()

  如果用户需要一个定义整个系统唯一的消息,可以调用SDK函数RegisterWindowMessage定义消息:

static UINT WM_MY_MESSAGE=RegisterWindowMessage("User");

  并使用ON_REGISTERED_MESSAGE宏指令取代ON_MESSAGE宏指令,其余步骤同上。

  当需要使用自定义消息时,可以在相应类中的函数中调用函数PostMessage或SendMessage发送消息PoseMessage(WM_MY_MESSAGE,O,O); 如果向其他进程发送消息可通过如下方法发送消息:

DWORD result;
SendMessageTimeout(wnd
->m_hWnd, // 目标窗口

WM_MY_MESSAGE, // 消息
0// WPARAM
0// LPARAM
SMTO_ABORTIFHUNG |
SMTO_NORMAL,
TIMEOUT_INTERVAL,
&result);

  以避免其它进程如果被阻塞而造成系统死等状态。

  可是如果需要向其它类(如主框架、子窗口、视类、对话框、状态条、工具条或其他控件等)发送消息时,上述方法显得无能为力,而在编程过程中往往需要获取其它类中的某个识别信号,MFC框架给我们造成了种种限制,但是可以通过获取某个类的指针而向这个类发送消息,而自定义消息的各种动作则在这个类中定义,这样就可以自由自在的向其它类发送消息了。

  下面举的例子叙述了向视类和框架类发送消息的方法:

  在主框架类中向视类发送消息:

  视类中定义消息:

ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //定义消息映射

  视类定义消息处理函数:

// 消息处理函数
LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
// TODO: 处理用户自定义消息

...
return 0
;
}

//发送消息的测试函数
void  CMainFrame::OnTest()
{
CView 
* active = GetActiveView();//获取当前视类指针

if(active != NULL)
active
->PostMessage(WM_MY_MESSAGE,0,0
);
}

  在其它类中向视类发送消息:

//发送消息的测试函数
void  CMainFrame::OnTest()
{
CMDIFrameWnd 
*
pFrame;
CMDIChildWnd 
*
pChild;
CView 
*
pView;
//获取主窗口指针

pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
// 获取子窗口指针

pChild = (CMDIChildWnd *) pFrame->GetActiveFrame();
//获取视类指针

pView = pChild->GetActiveView();
if(pView !=
 NULL)
pView
->PostMessage(WM_MY_MESSAGE,0,0);//发送消息

}

  其余步骤同上。

  在视类中向主框架发送消息:

  首先在主框架中定义相关的消息,方法同上,然后在发送消息的函数中添加代码如下

//发送消息的测试函数
void  CMessageView::OnTest()
{
CFrameWnd 
* active = GetActiveFrame();//获取当前主窗口框架指针

if(active != this)
active
->PostMessage(WM_MY_MESSAGE,0,0
);
return 0
;
}

  在其它类中向不同的类发送消息可依次方法类推,这样我们的程序就可以的不受限制向其它类和进程发送消息,而避免了种种意想不到的风险。

  下面一个例子程序为多文档程序里在一对话框中向视类发送消息,详述了发送自定义消息的具体过程。

  实现步骤:

  第一步:在VC++中新建工程Message,所有ClassWizard步骤选项均为缺省,完成。

  第二步:在主菜单中添加测试菜单为调出对话框,在框架类中建立相应函数OnTest()

  第三步:在资源中建立对话框,通过ClassWizard添加新类TestDialog,添加测试按钮,在对话框类中建立相应函数OnDialogTest()

//通过对话框按钮发送消息的函数
void  TestDialog::OnDialogTest()
{
CMDIFrameWnd 
*
pFrame;
CMDIChildWnd 
*
pChild;
CView 
*
pView;
//获取主窗口指针

pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
// 获取子窗口指针

pChild = (CMDIChildWnd *) pFrame->GetActiveFrame();
//获取视类指针

pView = pChild->GetActiveView();
if(active !=
 NULL)
active
->PostMessage(WM_MY_MESSAGE,0,0);//发送消息

}

  在Message.h头文件中添加如下语句:

static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");

  第四步:在视类中添加自定义消息:

  在头文件MessageView.h中添加消息映射

protected :
//
{{AFX_MSG(CMessageView)
//}}AFX_MSG

afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); //此行为添加代码
DECLARE_MESSAGE_MAP()
在视类文件MessageView.cpp中的消息映射中添加自定义消息映射
BEGIN_MESSAGE_MAP(CMessageView, CView)
//
{{AFX_MSG_MAP(CMessageView)
//
}}AFX_MSG_MAP
// Standard printing commands

ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //此行添加代码定义唯一消息
END_MESSAGE_MAP()

  添加相应的0消息处理函数

LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
CRect rect;
GetClientRect(
&
rect);
InvalidateRect(
&
rect);
test
=!
test;
return 0
;
}

  在MessageView.h中添加布尔变量 public:BOOL test;

  在视类构造函数中初始化 test变量:test=FALSE;

  修改CMessageView::OnDraw()函数

void CMessageView::OnDraw(CDC*  pDC)
{
CMessageDoc
* pDoc =
 GetDocument();
ASSERT_VALID(pDoc);
// 以下程序显示消息响应效果

if(test)
pDC
->TextOut(0,0,"消息响应!"
);
}

  第五步:显示测试对话框

  在MainFrame类中包含对话框头文件:

#include "TestDialog.h" ;
OnTest()函数中添加代码
void
 CMainFrame::OnTest()
{
TestDialog dialog;
dialog.DoModal();
}

  运行程序,在测试菜单打开对话框,点击测试按钮即可看到结果。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用 MFC 实现小球自由落体的步骤: 1. 创建一个 MFC 应用程序,选择 "单文档" 选项。 2. 在应用程序视图添加一个自定义视图类,例如 CMyView。 3. 在 CMyView 添加以下代码: ``` class CMyView : public CView { public: CMyView(); virtual ~CMyView(); virtual void OnDraw(CDC* pDC); virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint); afx_msg void OnTimer(UINT_PTR nIDEvent); protected: CRect m_rcClient; CPoint m_ptBall; int m_nBallRadius; double m_dBallSpeed; double m_dBallAcceleration; double m_dBallEnergyLoss; double m_dBallVelocity; double m_dBallPosition; double m_dBallTime; void DrawBall(CDC* pDC); void UpdateBall(); void ResetBall(); DECLARE_MESSAGE_MAP() }; CMyView::CMyView() { m_nBallRadius = 20; m_dBallSpeed = 0.0; m_dBallAcceleration = 9.8; m_dBallEnergyLoss = 0.8; m_dBallVelocity = 0.0; m_dBallPosition = 0.0; m_dBallTime = 0.0; SetTimer(1, 10, NULL); } CMyView::~CMyView() { KillTimer(1); } void CMyView::OnDraw(CDC* pDC) { GetClientRect(&m_rcClient); DrawBall(pDC); } void CMyView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { Invalidate(); } void CMyView::OnTimer(UINT_PTR nIDEvent) { UpdateBall(); CView::OnTimer(nIDEvent); } void CMyView::DrawBall(CDC* pDC) { CBrush brush(RGB(255, 0, 0)); pDC->SelectObject(&brush); pDC->Ellipse(m_ptBall.x - m_nBallRadius, m_ptBall.y - m_nBallRadius, m_ptBall.x + m_nBallRadius, m_ptBall.y + m_nBallRadius); } void CMyView::UpdateBall() { double dTimeDelta = 0.01; m_dBallVelocity = m_dBallSpeed + m_dBallAcceleration * m_dBallTime; m_dBallPosition = m_nBallRadius + 0.5 * m_dBallAcceleration * m_dBallTime * m_dBallTime; if (m_dBallPosition >= (m_rcClient.bottom - m_nBallRadius)) { m_dBallPosition = m_rcClient.bottom - m_nBallRadius; m_dBallVelocity = -m_dBallVelocity * m_dBallEnergyLoss; } m_dBallTime += dTimeDelta; m_dBallSpeed = m_dBallVelocity; m_ptBall.y = static_cast<int>(m_dBallPosition); } void CMyView::ResetBall() { m_ptBall.x = m_rcClient.right / 2; m_ptBall.y = m_nBallRadius; m_dBallSpeed = 0.0; m_dBallVelocity = 0.0; m_dBallPosition = 0.0; m_dBallTime = 0.0; } BEGIN_MESSAGE_MAP(CMyView, CView) ON_WM_TIMER() END_MESSAGE_MAP() ``` 4. 在 CMainFrame 添加以下代码: ``` class CMainFrame : public CFrameWnd { public: CMainFrame(); virtual ~CMainFrame(); protected: CMyView m_view; DECLARE_MESSAGE_MAP() }; CMainFrame::CMainFrame() { Create(NULL, _T("Free Fall Ball"), WS_OVERLAPPEDWINDOW, CRect(0, 0, 640, 480)); SetMenu(NULL); m_view.ResetBall(); SetWindowText(_T("Free Fall Ball")); SetIcon(LoadIcon(NULL, IDI_APPLICATION), TRUE); SetIcon(LoadIcon(NULL, IDI_APPLICATION), FALSE); } CMainFrame::~CMainFrame() { } BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) END_MESSAGE_MAP() ``` 5. 在 InitInstance 添加以下代码: ``` BOOL CMyApp::InitInstance() { AfxEnableControlContainer(); CMainFrame* pFrame = new CMainFrame; m_pMainWnd = pFrame; pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL); pFrame->SetWindowText(_T("Free Fall Ball")); pFrame->SetIcon(LoadIcon(NULL, IDI_APPLICATION), TRUE); pFrame->SetIcon(LoadIcon(NULL, IDI_APPLICATION), FALSE); pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE; } ``` 6. 运行程序,你将看到一个小球在窗口自由落体。 注意:此处代码仅供参考,实现自由落体的具体方法可能会因不同框架或环境而异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值