关于WM_PAINT(OnPaint)及WM_TIMER的小问题

 MSDN上面关于WM_TIMER有这么一段话: The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue. TIMER消息是一个低优先级的消息。只有当没有其他高优先级的消息的时候,才会被发送 好,你在onpaint函数里面如果不调用CPaintDC dc(this),而且你也没有调用基类的OnPaint,那么窗口的InvalidRect始终存在,也就是系统会不断地发送WM_PAINT消息给你的窗口,那么你的WM_TIMER消息永远不会被Dispatch,SO,你会发现ONTIMER只被调用了一次。 验证这一点很简单,你把SetTimer第三个参数给一个回调函数,这个函数会被调用很多次,说明很多个Timer消息已经被产生。只是你刚才不dispatch而已

 

来源:http://zhuidaniu.com/blogs/231

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的 MFC 绘图小游戏示例: 1. 创建新的 MFC 应用程序项目。 2. 在资源视图中添加一个 Dialog,命名为 "GameDialog",并添加一个按钮 "Start"。 3. 打开 "GameDialog.h" 文件,在类定义中添加以下变量: ``` private: bool m_bPlaying; CRect m_rectClient; CPoint m_ptBallPos; CPoint m_ptBallDir; int m_nBallRadius; ``` 4. 在 "GameDialog.cpp" 中添加以下代码: ``` BOOL CGameDialog::OnInitDialog() { CDialogEx::OnInitDialog(); // 初始化游戏变量 m_bPlaying = false; m_nBallRadius = 20; m_ptBallPos = CPoint(m_rectClient.Width() / 2, m_rectClient.Height() / 2); m_ptBallDir = CPoint(1, 1); return TRUE; } void CGameDialog::OnPaint() { CPaintDC dc(this); // 绘制游戏界面 dc.FillSolidRect(m_rectClient, RGB(255, 255, 255)); // 白色背景 dc.Ellipse(m_ptBallPos.x - m_nBallRadius, m_ptBallPos.y - m_nBallRadius, m_ptBallPos.x + m_nBallRadius, m_ptBallPos.y + m_nBallRadius); // 球 if (!m_bPlaying) { // 绘制游戏提示 CString strText = _T("点击 Start 开始游戏!"); dc.SetTextColor(RGB(0, 0, 255)); // 蓝色字体 dc.SetBkMode(TRANSPARENT); // 透明背景 dc.DrawText(strText, m_rectClient, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } } void CGameDialog::OnTimer(UINT_PTR nIDEvent) { if (nIDEvent == 1) { // 更新球的位置 m_ptBallPos += m_ptBallDir; if (m_ptBallPos.x - m_nBallRadius < 0 || m_ptBallPos.x + m_nBallRadius > m_rectClient.Width()) { m_ptBallDir.x *= -1; } if (m_ptBallPos.y - m_nBallRadius < 0 || m_ptBallPos.y + m_nBallRadius > m_rectClient.Height()) { m_ptBallDir.y *= -1; } // 重绘游戏界面 Invalidate(); } CDialogEx::OnTimer(nIDEvent); } void CGameDialog::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); // 更新客户区大小 m_rectClient = CRect(0, 0, cx, cy); } void CGameDialog::OnStartButtonClicked() { if (!m_bPlaying) { // 开始游戏 m_bPlaying = true; SetTimer(1, 16, NULL); // 每 16ms 更新一次球的位置 } } ``` 5. 在 "GameDialog.h" 中添加以下消息映射: ``` afx_msg void OnPaint(); afx_msg void OnTimer(UINT_PTR nIDEvent); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnStartButtonClicked(); ``` 6. 在 "GameDialog.cpp" 中添加以下消息映射: ``` BEGIN_MESSAGE_MAP(CGameDialog, CDialogEx) ON_WM_PAINT() ON_WM_TIMER() ON_WM_SIZE() ON_BN_CLICKED(IDC_START_BUTTON, &CGameDialog::OnStartButtonClicked) END_MESSAGE_MAP() ``` 7. 在 "GameDialog.rc" 中添加一个按钮,命名为 "StartButton",并将其 ID 设置为 "IDC_START_BUTTON"。 8. 编译并运行程序,点击 "Start" 按钮即可开始游戏。 9. 你可以根据自己的需求来扩展这个小游戏,例如添加更多的物体、增加碰撞检测等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值