利用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;
}

说明:

MERGE_MES_HEADER是一个参数类,每一个要使用这个工具类的都需要自己派生一个参数类。
参数类需要完成的任务有:
1. 执行函数。
2. 是否是同一消息的ID。

这个参数类由以下部分组成:
1. pfnCallBack。回调函数,真正要执行的函数。
2. Clone()。这是一个虚函数,因为这个参数需要存起来,使用这个函数可以实现参数复制。
3. IsSameMes()。这是一个虚函数,在CFepMergeMessage调用这个函数时,已经为其判断了类型。重写这个函数判断传入的参数是否为同一参数。
这三个变量/虚函数在派生类中一定要进行复制或重写。

使用时很简单,生命一个参数对象,调用CFepMergeMessage::Excute(const MERGE_MES_HEADER*)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值