我用WH_JOURNALRECORD记录键盘操作,然后用WH_JOURNALPLAYBACK回放,但回放的时候所有的鼠标和键盘都被屏蔽,我想在回放过程中可以进行回放终止操作,请问各位专家有没有办法可以解决?
解决方案 »
- LVS_EX_CHECKBOXES属性的CListCtrl怎样使得点击一项时自动改变对应项的复选框状态?
- 如何通过插件方式取到office模板文件的全路径???
- 如何用C++语言实现对本地网络流量的监控
- ****************新手问题,winsock能发送但是接收服务断就出现10053的错误*********
- 我用VS2005写了一个书上的例子为什么过不去呀!
- 请问如何处理lrc歌词文件?
- 如何让 atl activex 获得网页的内容?在线等待,来者有分!
- 请教大家:如何构造一个颜色表ColorTable啊?求指导
- 我也想去上海混混,请各位大哥大姐给点建议
- 如何访问资源文件中的HTML
- 有关globalAlloc分配失败
- 摩根
BOOL InstallOperationsDisplayHook(HWND,HINSTANCE);
BOOL UnInstallOperationsHook();
BOOL UnInstallOperationsDisplayHook();
BOOL CheckOperationsRecordHookHandle();
BOOL CheckOperationsDisplayHookHandle();
LRESULT CALLBACK JournalPlaybackProc(int,WPARAM,LPARAM);
LRESULT CALLBACK JournalRecordProc(int,WPARAM,LPARAM);
LPCTSTR GetMsgName(UINT);
void FreeMsgList();/*****************HOOKService.h***********************/
{
if (!UnInstallOperationsDisplayHook())
return FALSE; if (CheckOperationsRecordHookHandle())
return TRUE; g_AppInstance = hInst; g_Dlg_Hwnd = hWnd; FreeMsgList(); g_hHookOperationsRecord = ::SetWindowsHookEx(WH_JOURNALRECORD,
JournalRecordProc,
g_AppInstance,
0); return g_hHookOperationsRecord ? TRUE : FALSE;
}BOOL InstallOperationsDisplayHook(HWND hWnd,HINSTANCE hInst)
{
if (!UnInstallOperationsHook())
return FALSE; if (CheckOperationsDisplayHookHandle())
return TRUE; g_AppInstance = hInst; g_Dlg_Hwnd = hWnd; g_pMsgListPrev = g_pMsgMovePtr = g_pMsgListLast = NULL; RetTime = 0; g_hHookOperationsDisplay = ::SetWindowsHookEx(WH_JOURNALPLAYBACK,
JournalPlaybackProc,
g_AppInstance,
0); return g_hHookOperationsDisplay ? TRUE : FALSE;
}LRESULT CALLBACK JournalRecordProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if (nCode < 0)
return ::CallNextHookEx(g_hHookOperationsRecord,nCode,wParam,lParam);
if (nCode == HC_ACTION)
{
MsgList* pTmpMsgList = new MsgList;
pTmpMsgList->Event.hwnd = ((LPEVENTMSG)lParam)->hwnd;
pTmpMsgList->Event.message = ((LPEVENTMSG)lParam)->message;
pTmpMsgList->Event.paramH = ((LPEVENTMSG)lParam)->paramH;
pTmpMsgList->Event.paramL = ((LPEVENTMSG)lParam)->paramL;
pTmpMsgList->Event.time = ((LPEVENTMSG)lParam)->time;
if (!g_pMsgMovePtr)
{
if (!g_pMsgListHeader)
g_pMsgListPrev = g_pMsgListHeader = g_pMsgMovePtr = pTmpMsgList;
}
else
{
g_pMsgListLast = pTmpMsgList;/*将新消息作为最后的消息*/
g_pMsgListPrev = g_pMsgMovePtr;/*保存上次的消息*/
g_pMsgMovePtr->lpNext = pTmpMsgList;/*将新消息挂到消息列表*/
g_pMsgMovePtr = pTmpMsgList;/*将实时指针指向最后的消息*/
}
::PostMessage(g_Dlg_Hwnd,WM_PASSDATA,wParam,(LPARAM)pTmpMsgList);
} return ::CallNextHookEx(g_hHookOperationsRecord,nCode,wParam,lParam);
}LRESULT CALLBACK JournalPlaybackProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if (nCode < 0)
return ::CallNextHookEx(g_hHookOperationsDisplay,nCode,wParam,lParam); if (!g_pMsgMovePtr)
{
if (!g_pMsgListHeader)
{
return UnInstallOperationsDisplayHook();
}
g_pMsgMovePtr = g_pMsgListHeader;
g_pMsgListPrev = g_pMsgListHeader;
} switch (nCode)
{
case HC_GETNEXT:
/*********************************************************************
*The hook procedure must copy the current mouse or keyboard message *
*to the EVENTMSG structure pointed to by the lParam parameter. *
*********************************************************************/
{
LPEVENTMSG lpEvent = (LPEVENTMSG)lParam;
if (g_pMsgMovePtr && g_pMsgListPrev && lpEvent)
{
lpEvent->message = g_pMsgListPrev->Event.message;
lpEvent->paramL = g_pMsgListPrev->Event.paramL;
lpEvent->paramH = g_pMsgListPrev->Event.paramH;
lpEvent->time = g_pMsgListPrev->Event.time;
lpEvent->hwnd = g_pMsgListPrev->Event.hwnd;
RetTime = g_pMsgMovePtr->Event.time - g_pMsgListPrev->Event.time; if (g_pMsgMovePtr != g_pMsgListPrev)
{
g_pMsgListPrev = g_pMsgMovePtr;
}
}
if (RetTime < 0)
RetTime = 1;
return RetTime;
}
case HC_SKIP:
/*****************************************************************************
*The hook procedure must prepare to copy the next mouse or keyboard message *
*to the EVENTMSG structure pointed to by lParam. *
*Upon receiving the HC_GETNEXT code, *
*the hook procedure must copy the message to the structure. *
*****************************************************************************/
{
if (!g_pMsgMovePtr->lpNext)
{
return UnInstallOperationsDisplayHook();
} if (g_pMsgListPrev != g_pMsgMovePtr)
g_pMsgListPrev = g_pMsgMovePtr; g_pMsgMovePtr = g_pMsgMovePtr->lpNext;
return 0;
}
default:
break;
}
return ::CallNextHookEx(g_hHookOperationsDisplay,nCode,wParam,lParam);
}BOOL CheckOperationsRecordHookHandle()
{
return g_hHookOperationsRecord ? TRUE : FALSE;
}BOOL CheckOperationsDisplayHookHandle()
{
return g_hHookOperationsDisplay ? TRUE : FALSE;
}BOOL UnInstallOperationsHook()
{
if (!g_hHookOperationsRecord)
return TRUE; BOOL IsUnInstallSuccess = ::UnhookWindowsHookEx(g_hHookOperationsRecord); g_hHookOperationsRecord = NULL; return IsUnInstallSuccess;
}BOOL UnInstallOperationsDisplayHook()
{
if (!g_hHookOperationsDisplay)
return TRUE; BOOL IsUnInstallSuccess = ::UnhookWindowsHookEx(g_hHookOperationsDisplay); g_hHookOperationsDisplay = NULL; return IsUnInstallSuccess;
}LPCTSTR GetMsgName(UINT nCode)
{
for(int i=0,nCount=sizeof(messages)/sizeof(MsgStruct);i<nCount;++i)
{
if(messages[i].nCode == nCode)
return messages[i].pszText;
}
return "Sorry,I Don't Know.";
}void FreeMsgList()
{
delete g_pMsgListHeader;
g_pMsgMovePtr = NULL;
g_pMsgListHeader = NULL;
g_pMsgListLast = NULL;
g_pMsgListPrev = NULL;
RetTime = 0;
}/*****************HOOKService.cpp***********************/
#pragma once#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // 从 Windows 标头中排除不常使用的资料
#endif// 如果您必须使用下列所指定的平台之前的平台,则修改下面的定义。
// 有关不同平台的相应值的最新信息,请参考 MSDN。
#ifndef WINVER //允许使用 Windows 95 和 Windows NT 4 或更高版本的特定功能。
#define WINVER 0x0400 //为 Windows98 和 Windows 2000 及更新版本改变为适当的值。
#endif#ifndef _WIN32_WINNT // 允许使用 Windows NT 4 或更高版本的特定功能。
#define _WIN32_WINNT 0x0400 //为 Windows98 和 Windows 2000 及更新版本改变为适当的值。
#endif#ifndef _WIN32_WINDOWS // 允许使用 Windows 98 或更高版本的特定功能。
#define _WIN32_WINDOWS 0x0410 //为 Windows Me 及更新版本改变为适当的值。
#endif#ifndef _WIN32_IE //允许使用 IE 4.0 或更高版本的特定功能。
#define _WIN32_IE 0x0400 //为 IE 5.0 及更新版本改变为适当的值。
#endif#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的
....
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>// Windows 公共控件的 MFC 支持
#endif // _AFX_NO_AFXCMN_SUPPORT
#define WM_PASSDATA WM_USER+1982
#include <vector>
using namespace std;
#include <windowsx.h>
#include <winable.h>struct MsgStruct
{
UINT nCode;
LPCTSTR pszText;
};struct MsgList
{
public:
MsgList()
{
memset(&Event,0,sizeof(EVENTMSG));
lpNext = NULL;
}
~MsgList()
{
if (lpNext && !::IsBadReadPtr(lpNext,sizeof(MsgList)))
delete lpNext;
memset(&Event,0,sizeof(EVENTMSG));
lpNext = NULL;
}
EVENTMSG Event;
MsgList *lpNext;
};
static HHOOK g_hHookOperationsRecord = NULL;
static HHOOK g_hHookOperationsDisplay = NULL;
static HINSTANCE g_AppInstance = NULL;
static MsgList* g_pMsgMovePtr = NULL;
static MsgList* g_pMsgListHeader = NULL;
static MsgList* g_pMsgListLast = NULL;
static MsgList* g_pMsgListPrev = NULL;
static HWND g_Dlg_Hwnd = NULL;
static DWORD RetTime = 0;
static MsgStruct messages[] = {
...};
/*****************stdafx.h***********************//*****************MessageTipDlg.h***********************/
#pragma once
#include "afxcmn.h"
// CMessageTipDlg 对话框
class CMessageTipDlg : public CDialog
{
// 构造
public:
CMessageTipDlg(CWnd* pParent = NULL); // 标准构造函数// 对话框数据
enum { IDD = IDD_MESSAGETIP_DIALOG }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon; // 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButtonStart();
afx_msg void OnBnClickedButtonDisplay();
afx_msg void OnBnClickedButtonExit();
afx_msg void OnOK();
afx_msg void OnCancel();
afx_msg void OnClose();
afx_msg LRESULT OnPassData(WPARAM,LPARAM);
private:
void EnableDisplayFunction(BOOL = TRUE);
void EnableStartRecordFunction(BOOL = TRUE);
CListCtrl m_ListCtrl_MsgTip;
CImageList m_ImageList;
CFile m_FileOut;
void InitListCtrl();
protected:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL DestroyWindow();
afx_msg void OnBnClickedButtonOpenrecord();
afx_msg void OnBnClickedButtonSaverecord();
};
/*****************MessageTipDlg.h***********************/
//
#include "stdafx.h"#include "MessageTip.h"
#include "MessageTipDlg.h"#include "HOOKService.h"
#include ".\messagetipdlg.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMessageTipDlg 对话框CMessageTipDlg::CMessageTipDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMessageTipDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CMessageTipDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST_MSGTIP, m_ListCtrl_MsgTip);
}BEGIN_MESSAGE_MAP(CMessageTipDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(ID_BUTTON_START, OnBnClickedButtonStart)
ON_BN_CLICKED(ID_BUTTON_DISPLAY, OnBnClickedButtonDisplay)
ON_BN_CLICKED(ID_BUTTON_EXIT, OnBnClickedButtonExit)
ON_MESSAGE(WM_PASSDATA,OnPassData)
// ON_WM_SIZE()
ON_BN_CLICKED(ID_BUTTON_OPENRECORD, OnBnClickedButtonOpenrecord)
ON_BN_CLICKED(ID_BUTTON_SAVERECORD, OnBnClickedButtonSaverecord)
END_MESSAGE_MAP()
// CMessageTipDlg 消息处理程序BOOL CMessageTipDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, TRUE); // 设置小图标 // TODO: 在此添加额外的初始化代码
EnableDisplayFunction(FALSE); m_ImageList.Create(16,16,ILC_COLOR32,1,1);
// m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_MSGNAME));
// m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_MSGTIME));
// m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_MSGPARAM));
m_ImageList.Add(m_hIcon); InitListCtrl(); return TRUE; // 除非设置了控件的焦点,否则返回 TRUE
}// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。void CMessageTipDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}//当用户拖动最小化窗口时系统调用此函数取得光标显示。
HCURSOR CMessageTipDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}void CMessageTipDlg::OnBnClickedButtonStart()
{
// TODO: Add your control notification handler code here
CFileDialog CommonFileDlg(FALSE,_T("hook"),_T("消息保存文件"));
if (m_FileOut.m_hFile == INVALID_HANDLE_VALUE)
{
if (CommonFileDlg.DoModal() != IDOK)
{
AfxMessageBox("请选择消息保存位置^_^");
return ;
}
CFileFind FindFind;
if (FindFind.FindFile((LPCTSTR)CommonFileDlg.GetPathName(),0))
m_FileOut.Open((LPCTSTR)CommonFileDlg.GetPathName(),CFile::modeReadWrite);
else
m_FileOut.Open((LPCTSTR)CommonFileDlg.GetPathName(),CFile::modeCreate|CFile::modeReadWrite);
}
else
m_FileOut.SeekToBegin(); ULONGLONG ulFileLength = m_FileOut.GetLength();
if (ulFileLength > 0xffff)
{
m_FileOut.Close();
CString cstrNewFile(_T(""));
cstrNewFile.Format("%s%I64d",CommonFileDlg.GetPathName(),rand() % ulFileLength);
CFileFind FindFind;
if (FindFind.FindFile((LPCTSTR)cstrNewFile,0))
m_FileOut.Open((LPCTSTR)cstrNewFile,CFile::modeReadWrite);
else
m_FileOut.Open((LPCTSTR)cstrNewFile,CFile::modeCreate|CFile::modeReadWrite);
} if (!InstallOperationsHook(m_hWnd,
AfxGetApp()->m_hInstance))
{
AfxMessageBox("安装系统钩子失败!");
} EnableStartRecordFunction(FALSE);
EnableDisplayFunction();
}void CMessageTipDlg::OnBnClickedButtonDisplay()
{
// TODO: Add your control notification handler code here
if (!InstallOperationsDisplayHook(m_hWnd,
AfxGetApp()->m_hInstance))
{
AfxMessageBox("安装系统钩子失败!");
} EnableStartRecordFunction();
EnableDisplayFunction(FALSE);
}void CMessageTipDlg::OnBnClickedButtonExit()
{
// TODO: Add your control notification handler code here
FreeMsgList();
UnInstallOperationsHook();
UnInstallOperationsDisplayHook();
CDialog::OnOK();
}void CMessageTipDlg::OnOK()
{
return ;
}void CMessageTipDlg::OnCancel()
{
return ;
}void CMessageTipDlg::OnClose()
{
return ;
}void CMessageTipDlg::EnableDisplayFunction(BOOL IsEnable/* = TRUE */)
{
((CButton*)GetDlgItem(ID_BUTTON_DISPLAY))->EnableWindow(IsEnable);
}void CMessageTipDlg::EnableStartRecordFunction(BOOL IsEnable/* = TRUE */)
{
((CButton*)GetDlgItem(ID_BUTTON_START))->EnableWindow(IsEnable);
}
void CMessageTipDlg::InitListCtrl()
{
g_AppInstance = AfxGetApp()->m_hInstance; m_ListCtrl_MsgTip.SetImageList(&m_ImageList,LVSIL_SMALL);
LVCOLUMN col;
col.mask = LVCF_FMT|LVCF_IMAGE|LVCF_SUBITEM|LVCF_TEXT|LVCF_WIDTH;
col.fmt = LVCFMT_CENTER|LVCFMT_IMAGE;
col.iImage = 0;
col.cchTextMax = ::lstrlen("消息名称")+1;
col.pszText = "消息名称";
col.iSubItem = 0;
CRect rect(0,0,0,0);
m_ListCtrl_MsgTip.GetWindowRect(&rect);
col.cx = 120;
m_ListCtrl_MsgTip.InsertColumn(0,&col); col.cx = 120;
col.cchTextMax = ::lstrlen("消息值")+1;
col.pszText = "消息值";
m_ListCtrl_MsgTip.InsertColumn(1,&col); col.cx = rect.Width();
col.cchTextMax = ::lstrlen("消息时间")+1;
col.pszText = "消息时间";
m_ListCtrl_MsgTip.InsertColumn(2,&col);
}LRESULT CMessageTipDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
return CDialog::WindowProc(message, wParam, lParam);
}BOOL CMessageTipDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
return CDialog::PreTranslateMessage(pMsg);
}LRESULT CMessageTipDlg::OnPassData(WPARAM wParam,LPARAM lParam)
{
LPEVENTMSG lpEventMsg = (LPEVENTMSG)lParam;
CString cstrMsg(_T(""));
TCHAR TargetWindowName[MAX_PATH] = { '\0' };
::GetWindowText(::GetActiveWindow(),TargetWindowName,MAX_PATH);
COleDateTime cdt(COleDateTime::GetCurrentTime());
CString cstrMsgName(GetMsgName(lpEventMsg->message));
cstrMsg.Format("消息名称:%s\r\n消息目标窗体:%s\r\n消息发送时间:%s\r\n---------------------------------------------\r\n",
cstrMsgName,TargetWindowName,
cdt.Format("%Y年%m月%d日%H时%M分%S秒"));
m_FileOut.Write((LPCTSTR)cstrMsg,cstrMsg.GetLength());
m_ListCtrl_MsgTip.DeleteAllItems();
m_ListCtrl_MsgTip.InsertItem(0,(LPCTSTR)cstrMsgName,0);
m_ListCtrl_MsgTip.SetItemText(0,1,(LPCTSTR)TargetWindowName);
m_ListCtrl_MsgTip.SetItemText(0,2,(LPCTSTR)cdt.Format("%Y年%m月%d日%H时%M分%S秒"));
return 0;
}BOOL CMessageTipDlg::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
if (m_FileOut.m_hFile != INVALID_HANDLE_VALUE)
m_FileOut.Close();
return CDialog::DestroyWindow();
}void CMessageTipDlg::OnBnClickedButtonOpenrecord()
{
// TODO: Add your control notification handler code here
}void CMessageTipDlg::OnBnClickedButtonSaverecord()
{
// TODO: Add your control notification handler code here
}
/*****************MessageTipDlg.cpp***********************/
我的本意是在回放过程中,能够点击"停止回放"按钮来达到取消回放的功能。