用Windows消息循环实现消息延迟和合并

最初的解决方法是为计算消息设定时间间隔:当一个计算消息到达时,开始计时,在一定时间间隔内,接受到的计算消息一概不处理。由于时间间隔没法给定,也没法进行预算。时间间隔设置长了,如果两次操作过快,就会漏算;设置时间短了,又无法解决计算此数过多的问题。所以这个解决方法只能算是延缓了问题,而不能算是解决问题。

后来,不知道什么时候灵机一动,想到了下面的方法,完美的解决了问题。这对于我这个菜鸟来说,还是有纪念意义的。

我的解决思想是:制作一个合并消息的类。利用Window消息循环,当消息到达时,并不立即处理,只是将参数存起来。如果是第一个消息,则向自己Post一个处理消息。当Post的处理消息到达时采取真正的调用应该调用的函数。

后来,要求使用这种功能的模块增加,我就将它实现为能容纳多个需要合并消息的工具类。代码如下:

//****************************************************************************
// D L G C S O F T W A R E C O.
//****************************************************************************
// Filename: FepMergeMessage.h
// Project: FEP V4 6.0
// Module:
// Programmer: Ma Nan
// Version: Version 1.00
// Revision Date: 2006/12/04
//****************************************************************************
// Description: Declaration of class CFepMergeMessage
//****************************************************************************
// Revision history:
// 2006/12/04 - First implementation
//****************************************************************************
// Bugs: ........
//****************************************************************************
// @doc
//****************************************************************************
// FepMergeMessage.h: interface for the CFepMergeMessage class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FEPMERGEMESSAGE_H__D60309AA_9DA0_4474_9DC0_EDFF72E7165C__INCLUDED_)
#define AFX_FEPMERGEMESSAGE_H__D60309AA_9DA0_4474_9DC0_EDFF72E7165C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class MERGE_MES_HEADER;
typedef void (*MergeMesCallBack)(const MERGE_MES_HEADER* lpMergMes);
class MERGE_MES_HEADER : public CObject
{
 DECLARE_DYNAMIC(MERGE_MES_HEADER);
 MergeMesCallBack pfnCallBack;
 virtual MERGE_MES_HEADER* Clone() const = 0;
 virtual BOOL IsSameMes(const MERGE_MES_HEADER* pMes) const = 0;
};
//****************************************************************************
// @class CFepMergeMessage |
// CFepMergeMessage is used to
//
// @base CDialog
//****************************************************************************
// @ex
// This shows how to call CFepMergeMessage : |
//
//
//
//****************************************************************************
// @prog
// Ma Nan
// @revs
// 2006/12/04 - First implementation
//****************************************************************************
// @todo
//****************************************************************************
class CFepMergeMessage : public CDialog
{
 public:
  CFepMergeMessage();
  virtual ~CFepMergeMessage();
  static BOOL Excute(const MERGE_MES_HEADER* pParam);
 protected:
  //create the dialog to deal the message
  BOOL Create();
 protected:
  afx_msg LRESULT OnMergeMessage(WPARAM wParam, LPARAM lParam);
  afx_msg LRESULT OnProcessMessage(WPARAM wParam, LPARAM lParam);
  DECLARE_MESSAGE_MAP()
 protected:
  CArray<MERGE_MES_HEADER*, MERGE_MES_HEADER*> m_rgMessage;
  BOOL m_bMessagePosted;
};
#endif // !defined(AFX_FEPMERGEMESSAGE_H__D60309AA_9DA0_4474_9DC0_EDFF72E7165C__INCLUDED_)
/////////////////////////////
//FepMergeMessage.cpp
////////////////////////////
#include "StdAfx.h"
#include "FepMergeMessage.h"
#include "../Include/FepPtr.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define WM_MERGE_MESSAGE WM_USER + 100
#define WM_PROCESS_MESSAGE WM_USER + 200
//////////////////////////////////////////////////////////////////////////
//struct MERGE_MES_HEADER
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(MERGE_MES_HEADER, CObject)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
static CFepPtr<CFepMergeMessage> pDlgMergeMessage(NULL);
CFepMergeMessage::CFepMergeMessage()
{
 m_bMessagePosted = FALSE;
 Create();
}
CFepMergeMessage::~CFepMergeMessage()
{
 for(int i=0; i<m_rgMessage.GetSize(); ++i)
 {
  delete m_rgMessage.GetAt(i);
 }
 m_rgMessage.RemoveAll();
}
BEGIN_MESSAGE_MAP(CFepMergeMessage, CDialog)
 ON_MESSAGE(WM_MERGE_MESSAGE, OnMergeMessage)
 ON_MESSAGE(WM_PROCESS_MESSAGE, OnProcessMessage)
END_MESSAGE_MAP()
//****************************************************************************
// Function CFepMergeMessage::Create
// @mfunc
// @rdesc TRUE if the function succeeds; otherwise, FALSE.(BOOL)
// @xref <c CFepMergeMessage >
//****************************************************************************
// @prog
// Ma Nan
// @revs
// 2006/12/04 First implementation
//****************************************************************************
// @todo
//
//****************************************************************************
BOOL CFepMergeMessage::Create()
{
 if(GetSafeHwnd() != NULL)
 {
  return TRUE;
 }
 DWORD dwDlgTempl[100];
 ZeroMemory(dwDlgTempl, sizeof(DWORD)*100);
 DLGTEMPLATE* pDlgTmp = (DLGTEMPLATE*)dwDlgTempl;
 pDlgTmp->style = WS_POPUP | DS_CONTROL;
 pDlgTmp->cx = 1;
 pDlgTmp->cy = 1;
 return CDialog::CreateIndirect(pDlgTmp);
}
//****************************************************************************
// Function CFepMergeMessage::Excute
// @mfunc
// @rdesc TRUE if the function succeeds; otherwise, FALSE.(BOOL)
// @parm const MERGE_MES_HEADER* | pParam | a pointer to const MERGE_MES_HEADER
// @xref <c CFepMergeMessage >
//****************************************************************************
// @prog
// Ma Nan
// @revs
// 2006/12/04 First implementation
//****************************************************************************
// @todo
//
//****************************************************************************
BOOL CFepMergeMessage::Excute(const MERGE_MES_HEADER* pParam)
{
 // dlgMergeMes.SendMessage(WM_MERGE_MESSAGE, (WPARAM)pParam, 0);
 if(pDlgMergeMessage.m_pPtr == NULL)
 {
  pDlgMergeMessage.m_pPtr = new CFepMergeMessage;
 }
 if(pDlgMergeMessage->GetSafeHwnd() == NULL)
 {
  return FALSE;
 }
 pDlgMergeMessage->SendMessage(WM_MERGE_MESSAGE, (WPARAM)pParam, 0);
 return TRUE;
}
//****************************************************************************
// Function CFepMergeMessage::OnMergeMessage
// @mfunc
// @rdesc (LRESULT)
// @parm WPARAM | wParam |
// @parm | LPARAM |
// @xref <c CFepMergeMessage >
//****************************************************************************
// @prog
// Ma Nan
// @revs
// 2006/12/04 First implementation
//****************************************************************************
// @todo
//
//****************************************************************************
LRESULT CFepMergeMessage::OnMergeMessage(WPARAM wParam, LPARAM)
{
 const MERGE_MES_HEADER* pNewMes = (const MERGE_MES_HEADER*)wParam;
 for(int i=0; i<m_rgMessage.GetSize(); ++i)
 {
  MERGE_MES_HEADER* pMes = m_rgMessage.GetAt(i);
  if(pNewMes->IsKindOf(pMes->GetRuntimeClass()) && pNewMes->IsSameMes(pMes))
  {
   delete pMes;
   m_rgMessage.RemoveAt(i);
   --i;
  }
 }
 m_rgMessage.Add(pNewMes->Clone());
 if(!m_bMessagePosted)
 {
  PostMessage(WM_PROCESS_MESSAGE, 0, 0);
  m_bMessagePosted = TRUE;
 }
 return 0L;
}
//****************************************************************************
// Function CFepMergeMessage::OnProcessMessage
// @mfunc
// @rdesc (LRESULT)
// @parm | WPARAM |
// @parm | LPARAM |
// @xref <c CFepMergeMessage >
//****************************************************************************
// @prog
// Ma Nan
// @revs
// 2006/12/04 First implementation
//****************************************************************************
// @todo
//
//****************************************************************************
LRESULT CFepMergeMessage::OnProcessMessage(WPARAM, LPARAM)
{
 while(m_rgMessage.GetSize() > 0)
 {
  MERGE_MES_HEADER* pHeader = m_rgMessage.GetAt(0);
  pHeader->pfnCallBack(pHeader);
  delete pHeader;
  m_rgMessage.RemoveAt(0);
 }
 m_bMessagePosted = FALSE;
 return 0L;
}

时间: 2025-01-20 12:59:03

用Windows消息循环实现消息延迟和合并的相关文章

深入探讨MFC消息循环和消息泵

首先,应该清楚MFC的消息循环(::GetMessage,::PeekMessage),消息泵(CWinThread::PumpMessage)和MFC的消息在窗口之间的路由是两件不同的事情.在MFC的应用程序中(应用程序类基于CWinThread继承),必须要有一个消息循环,他的作用是从应用程序的消息队列中读取消息,并把它派送出去(::DispatchMessage).而消息路由是指消息派送出去之后,系统(USER32.DLL)把消息投递到哪个窗口,以及以后消息在窗口之间的传递是怎样的.  消

c++-消息循环和消息映射在C++ 6.0中的区别是什么?

问题描述 消息循环和消息映射在C++ 6.0中的区别是什么? 消息循环和消息映射在C++ 6.0中的区别是什么?是否可以理解,消息循环只有一个消息处理函数,而消息映射就是很多函数?好像消息循环更简单啊? 解决方案 参考:http://blog.csdn.net/ocean2006/article/details/5498265 解决方案二: 消息循环就是不停的接收消息并进行处理,消息映射的意思就是对于某条消息到来后,系统会调用哪个函数(也就是这个消息对应的消息处理函数)来响应这条消息 解决方案三

揭开.NET消息循环的神秘面纱

循环 曾经在Win32平台下奋战的程序员们想必记得,为了弄清楚"消息循环"的概念,度过多少不眠之夜.尽管如今在应用程序代码的编写过程中,我们已经不再需要它,但是深刻理解Windows平台内部的消息流转机制依然必要.. 在早年直接用Win32/Win16 API写程序的时代,消息循环是我们必须搞懂的第一个观念.现在,不管你用是Windows上面的哪一套Application Framework(MFC.VCL.VB..NET Framework),甚至Unix.Linux.MacOSX上

模态窗口其实就是在当前窗口调用系统的消息循环,响应用户的操作,将相关的消息发送到对应的窗口(转)

  上周准备在公司内部转岗,面了3个部门windows客户端相关的工作,最终拿到3个Offer,主要涉及C++和Windows两大块内容,C++的题目基本都答上了,Windows一直都是我的弱项,在这里记录一下Windows相关的题目.有些答不上的问题就没列出来,还有些问题忘了,下面的答案有些大部分是我自己的理解,有些是直接从网上copy的,有问题大家可以讨论. 1:GetMessage和PeekMessage的区别? GetMessage:获取消息队列中的一个消息,存入MSG中,并从消息队列中

眼见为实(2):介绍Windows的窗口、消息、子类化和超类化

眼见为实(2):介绍Windows的窗口.消息.子类化和超类化 这篇文章本来只是想介绍一下子类化和超类化这两个比较"生僻"的名词.为了叙述的完整性而讨论了Windows的窗口和消息,也简要讨论了进程和线程.子类化(Subclassing)和超类化(Superclassing)是伴随Windows窗口机制而产生的两个复用代码的方法.不要把"子类化.超类化"与面向对象语言中的派生类.基类混淆起来."子类化.超类化"中的"类"是指W

windows编程怎样让消息盒子撤销后屏幕继续出现动画?

问题描述 windows编程怎样让消息盒子撤销后屏幕继续出现动画? 1.我想让消息盒子撤消后出现画线那个动画,就是for循环那个,结果消息盒子撤销不了... 2.后来我用了一个随机数,一半的概率是我屏幕的动画,一半的概率是出现消息盒子,但是事实情况是是出现动画的时候消息盒子也出现了,然后还撤销不了,这怎么破 else{ //如果此应用程序没有接受到消息,不断循环,全速画线 //调用TLines(TLines.cpp)对象的Draw(),做最主要的事情 int r = rand() % 100;

MFC中消息循环处理的几个函数之间的区别

Windows编程中一个比较原始的问题就是消息循环,现在很少有人关心这些了; 我个人对消息循环比较感兴趣,对底层的很多细节想深入了解! 以下说明几个消息循环中的常用函数进行对比 1 PostMessage 与 SendMessage 函数对比 SendMessage把消息直接发送到窗口,并调用此窗口的相应消息处理函数,等消息处理函数结束后SendMessage才返回!SendMessage发送的消息不进入系统的消息队列;SendMessage函数有返回值 PostMessage将消息发送到与创建

WinMain函数 注册窗口类 消息循环

#include <windows.h>#pragma comment(lib,"winmm.lib")//为了要播放声音,必须导入这个库 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)/* HINSTANCE 类型的含义为实

C#开发WINDOWS应用程序时消息的处理

window|程序 WINDOWS应用程序是靠消息驱动的,在VC中我们通过CLASSWIZARD可以为某窗口类添加消息处理函数,CLASSWIZARD将为你添加消息映射,对于WINDOWS消息,生成的消息处理函数重载了基类的虚拟方法.而在C#中如何处理消息呢?本文针对VS.NET BETA1环境下的C#简单地介绍WINDOWS消息以及自定义消息的处理方法. 示例代码下载 17K 一.生成一个名为MSGApplication的工程 工程的建立方法请参考:C#学习笔记之一 二.处理WM_PAINT消