用记事本记录程序的所有消息

发表于:2007-07-01来源:作者:点击数: 标签:
终于实现了向记事本里发送消息:这里是所有的源码!做了一个简单的例子,这个程序运行时,所有的消息都将发送到记事本里去: 而且消息已经格式化!这样可以看到所有的消息,在以后的程序学习中很有帮助!至少目前明白了几个重要的程序调试方法!在TRACE()里




  终于实现了向记事本里发送消息:这里是所有的源码!做了一个简单的例子,这个程序运行时,所有的消息都将发送到记事本里去:
而且消息已经格式化!这样可以看到所有的消息,在以后的程序学习中很有帮助!至少目前明白了几个重要的程序调试方法!在TRACE()里是一个好方法,但离开了集成环境就不好用了,可能会用MessageBox(),但这样会使程序停止而不得不去响应这个对话框(枚举窗口里差点死机的,所以不是好方法)。这为学习多线程编程提供了好方法,那就是一个在IDE里调试,而另一个用记事本来处理消息,真是个好主意!
这里是一个很简单的例子,拿来讨论一下:
///////////////////////////////////////////////////////////////////////////////////////////
// exam006.cpp : 定义应用程序的类行为。
#include "stdafx.h"
#include "exam006.h"
#include "exam006Dlg.h"
#include ".exam006.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// Cexam006App
BEGIN_MESSAGE_MAP(Cexam006App, CWinApp)
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
// Cexam006App 构造
Cexam006App::Cexam006App()
{
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的一个 Cexam006App 对象
Cexam006App theApp;
// Cexam006App 初始化
BOOL Cexam006App::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControls()。否则,将无法创建窗口。
InitCommonControls();
CWinApp::InitInstance();
AfxEnableControlContainer();
// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
Cexam006Dlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用“确定”来关闭
//对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用“取消”来关闭
//对话框的代码
}

// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}

BOOL Cexam006App::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if(HWND m_whnd=::FindWindow("notepad",NULL))
{
TRACE(_T("发现记事本窗口!开始消息发送! "));
    ::EnumChildWindows(m_whnd,(WNDENUMPROC)EnumChildProc,(LPARAM)pMsg);
}else{
TRACE(_T("没有发现记事本窗口! "));
}
return CWinApp::PreTranslateMessage(pMsg);
}
//消息回调函数的实现
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam){
TRACE(_T("找到窗口!"));
MSG *p_msg=(MSG *)lParam;
CString m_str;
char c;
//格式化消息,因为我们只想知道消息的内容是什么,而不用记事本来响应这些消息,否则可能使记事本直接响应消息,那就是一个程序操作两窗口了!
m_str.Format("[Message]whnd:%ld,lParam:%ld,wParam:%ld,time:%ld,x=%d,y=%d,WM_ID:%d ",
p_msg->hwnd,
p_msg->lParam,
p_msg->wParam,
p_msg->time,
p_msg->pt.x,
p_msg->pt.y,
p_msg->message
);
//将消息以字符的形式都转发给记事本!这样记事本里就记录了所有的消息!!!
for(int i=0;i<=m_str.GetLength();i++){
c=m_str.GetAt(i);
::PostMessage(hwnd,WM_CHAR,(WPARAM)c,NULL);
}
return (BOOL)hwnd;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// exam006.h : PROJECT_NAME 应用程序的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
#error 在包含用于 PCH 的此文件之前包含“stdafx.h”
#endif
#include "resource.h" // 主符号
//全局函数
//消息回调函数的声明
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam);
// Cexam006App:
// 有关此类的实现,请参阅 exam006.cpp
//
class Cexam006App : public CWinApp
{
public:
Cexam006App();

// 重写
public:
virtual BOOL InitInstance();

// 实现
//重写PreTranslateMessage函数可在应用程序得到消息之前先过滤一遍消息,而这里只是将消息以字符的形式发给记事本!在记事本里显示消息的内容!
DECLARE_MESSAGE_MAP()
virtual BOOL PreTranslateMessage(MSG* pMsg);
};
extern Cexam006App theApp;
/////////////////////////////////////////////////////////////////////////////////////////////
  主程序就是一个对话框,什么都没做,因为对话框不响应WM_CHAR(只是给出一个报警声),所以对话框自己有些问题!(但这不是主要的,因为它的所以消息确实发到了记事里了,我们可以观察和学习这些消息!甚至还可以把所有的消息都发到记事本里,这样所有的操作对记事本都有效,包括快捷键和关闭窗口的消息,很有意思吧!)还是那句话,对以后的学习很有帮助的!

自己也是刚学习MFC,希望得到大家的帮助!
e-mail:WuCountry@126.com

原文转自:http://www.ltesting.net