怎样在非客户区捕捉鼠标状态?
鉴于很多网友苦于在非客户区捕捉鼠标状态,特写出用DirectX来解决的方法.
首先新建一个基于对话框的工程(定为MouseR)
在工程属性的Link-->Object/Library Modules:里加上:
dxguid.lib dxerr8.lib dinput8.lib
(如果你的机器上安装了DirectX 8.0 SDK,只需要如上操作就行了,
如果没有安装或没有将VC的库指定到SDK里,你需要将这几个库拷贝到你的工程中)
同时,在MouseRDlg.cpp的头部加上:#include <dinput.h>//安装了SDK情况下.
以下为原文件:
/////////////////////////////////////////////////////////////////////////////
// CMouseRDlg dialog
class CMouseRDlg : public CDialog
{
// Construction
public:
CMouseRDlg(CWnd* pParent = NULL); // standard constructor
//此处定义三个函数
VOID FreeDirectInput(); //释放
void ReadImmediateData(); //读取
void InitDevice(); //初始化
// Dialog Data
//{{AFX_DATA(CMouseRDlg)
enum { IDD = IDD_MOUSER_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMouseRDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CMouseRDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MOUSERDLG_H__BC9AFF7C_C2BE_439A_9D50_CDC608606DFA__INCLUDED_)
// MouseRDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MouseR.h"
#include "MouseRDlg.h"
//dirctx
#include <dinput.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
//定义两个小函数
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
//#define SAMPLE_BUFFER_SIZE 16 // arbitrary number of buffer elements
LPDIRECTINPUT8 g_pDI = NULL; //定义两个控制变量
LPDIRECTINPUTDEVICE8 g_pMouse = NULL;
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMouseRDlg dialog
CMouseRDlg::CMouseRDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMouseRDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CMouseRDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMouseRDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMouseRDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMouseRDlg, CDialog)
//{{AFX_MSG_MAP(CMouseRDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMouseRDlg message handlers
BOOL CMouseRDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
InitDevice();
SetTimer(1,10,0);
return TRUE; // return TRUE unless you set the focus to a control
}
void CMouseRDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMouseRDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CMouseRDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CMouseRDlg::InitDevice()
{
HRESULT hr;
FreeDirectInput();
if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,
IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
return ;
// Obtain an interface to the system mouse device.
if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) ) )
return ;
if( FAILED( hr = g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) )
return ;
if( FAILED(hr) )
return ;
g_pMouse->Acquire();
}
///////////////////read mouse info////////
void CMouseRDlg::ReadImmediateData( )
{
HRESULT hr;
CString strNewText;
DIMOUSESTATE2 dims2; // DirectInput mouse state structure
CPoint point;
if( NULL == g_pMouse )
return ;
ZeroMemory( &dims2, sizeof(dims2) );
hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &dims2 );
if( FAILED(hr) )
{
hr = g_pMouse->Acquire();
while( hr == DIERR_INPUTLOST )
hr = g_pMouse->Acquire();
if( hr == DIERR_OTHERAPPHASPRIO ||
hr == DIERR_NOTACQUIRED )
SetDlgItemText(IDC_STATIC1, "失败!" );
}
GetCursorPos(&point); //得到鼠标位置.这个功能直接用API得到更方便,所以这里取
// 代了DirectX
strNewText.Format("L=%d R=%d M=%d X=%4d Y=%4d", //写入结果,分别为L左
//键,R右键,M中键,X鼠标X
//值,Y鼠标Y值.前三个值,1
//表示按下,0为弹起
(dims2.rgbButtons[0] & 0x80) ? 1 : 0,
(dims2.rgbButtons[1] & 0x80) ? 1 : 0,
(dims2.rgbButtons[2] & 0x80) ? 1 : 0,
point.x,point.y
);
CString strOldText;
GetDlgItemText(IDC_STATIC1, strOldText);
if( 0 != lstrcmp( strOldText, strNewText ) )
SetDlgItemText( IDC_STATIC1, strNewText ); //显示结果,IDC_STATIC1为用来
//显示的文本标签
}
VOID CMouseRDlg::FreeDirectInput() //释放
{
if( g_pMouse )
g_pMouse->Unacquire();
SAFE_RELEASE( g_pMouse );
SAFE_RELEASE( g_pDI );
}
void CMouseRDlg::OnTimer(UINT nIDEvent)
{
ReadImmediateData( );
CDialog::OnTimer(nIDEvent);
}
void CMouseRDlg::OnDestroy()
{
FreeDirectInput();
KillTimer(1);
CDialog::OnDestroy();
}
OK了,运行一下程序就可以了,这时你会发再点击屏幕任意一个地方都会有响应了.
下载工程代码:
http://www.7forever.com/rwdata/temp/MouseR.rar
作者Blog:http://blog.csdn.net/zhucde/