- 公开视频 -> 链接点击跳转公开课程
- 博客首页 -> 链接点击跳转博客主页
目录
MFC鼠标
派发流程
- 消息捕获:当鼠标在屏幕上移动或点击时,Windows捕获这些事件,并生成相应的消息。
- 消息队列:Windows将这些消息放入应用程序的消息队列中。
- 消息循环:应用程序的消息循环(通常在主窗口的消息泵中)从消息队列中取出消息。
- 消息派发:消息循环将消息派发给相应的窗口处理。对于客户区消息,这些消息通常由窗口的视图类或主窗口类处理;对于非客户区消息,这些消息由窗口的非客户区处理函数处理。
- 消息处理:窗口接收到消息后,通过消息映射机制调用相应的消息处理函数进行处理。
鼠标消息(客户区)
WM_MOUSEMOVE
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_RBUTTONDBLCLK
鼠标消息(非客户)
WM_NCHITTEST
WM_NCLBUTTONDOWN
WM_NCLBUTTONUP
WM_NCLBUTTONDBLCLK
坐标处理
客户区
- 客户区坐标是指窗口内部可用于绘制内容的区域坐标。这个区域的坐标原点(0,0)通常位于窗口的左上角。在客户区坐标系统中,X轴向右增加,Y轴向下增加。
- 原点:窗口的左上角。
- X轴:向右为正。
- Y轴:向下为正。
非客户
- 非客户区坐标是指窗口的非客户区域,包括标题栏、边框、滚动条等部分的坐标。非客户区的坐标系统是屏幕坐标系统,其原点(0,0)位于屏幕的左上角。
- 原点:屏幕的左上角。
- X轴:向右为正。
- Y轴:向下为正。
坐标转换
- 在处理窗口事件时,经常需要在这两种坐标系统之间进行转换。
ScreenToClient
: 将屏幕坐标转换为客户区坐标。ClientToScreen
: 将客户区坐标转换为屏幕坐标。
示例代码
cpp
#include "main.h"
CMyApp MyApp;
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMainWnd;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
CMainWnd::CMainWnd()
{
Create(NULL, NULL);
}
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_NCLBUTTONDOWN()
ON_WM_NCLBUTTONUP()
END_MESSAGE_MAP()
void CMainWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
CString strPoint;
strPoint.Format(_T("OnLButtonDown %d - %d\r\n"), point.x, point.y);
OutputDebugString(strPoint);
}
void CMainWnd::OnLButtonUp(UINT nFlags, CPoint point)
{
CString strPoint;
strPoint.Format(_T("OnLButtonUp %d - %d\r\n"), point.x, point.y);
OutputDebugString(strPoint);
}
void CMainWnd::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
CString strPoint;
strPoint.Format(_T("OnNcLButtonDown %d - %d\r\n"), point.x, point.y);
OutputDebugString(strPoint);
CFrameWnd::OnNcLButtonDown(nHitTest, point);
}
void CMainWnd::OnNcLButtonUp(UINT nHitTest, CPoint point)
{
CString strPoint;
strPoint.Format(_T("OnNcLButtonUp %d - %d\r\n"), point.x, point.y);
OutputDebugString(strPoint);
CFrameWnd::OnNcLButtonUp(nHitTest, point);
}
void CMainWnd::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
{
if (nHitTest != HTCAPTION)
{
CFrameWnd::OnNcLButtonDblClk(nHitTest, point);
}
}
LRESULT CMainWnd::OnNcHitTest(CPoint point)
{
UINT uHit = CFrameWnd::OnNcHitTest(point);
if (uHit == HTCLIENT)
{
uHit = HTCAPTION;
}
return uHit;
}
cpp
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
void CMainWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
m_Flg = TRUE;
m_str = point;
m_End = point;
}
void CMainWnd::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_Flg)
{
m_Flg = FALSE;
m_End = point;
CClientDC dc(this);
dc.MoveTo(m_str);
dc.LineTo(point);
}
}
void CMainWnd::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_Flg)
{
CClientDC dc(this);
DrawLine(&dc, m_str, m_End);
DrawLine(&dc, m_str, point);
m_End = point;
}
}
VOID CMainWnd::DrawLine(CDC* pDC, CPoint str, CPoint end)
{
INT nOld = pDC->SetROP2(R2_NOT);
pDC->MoveTo(m_str);
pDC->LineTo(end);
pDC->SetROP2(nOld);
}
MFC键盘
击键消息
WM_KEYDOWN
:非系统键被按下。WM_KEYUP
:非系统键被释放。WM_SYSKEYDOWN
:系统键(通常是Alt键)被按下。WM_SYSKEYUP
:系统键被释放。
虚拟键代码
- 虚拟键代码(Virtual-Key Codes)是Windows用来标识键盘上每个键的唯一值。例如,VKA代表字母A,VKSHIFT代表Shift键等。
键状态
- 在MFC中,可以使用
GetKeyState
函数来获取特定键的状态,例如Shift、Ctrl或Alt键的状态。