鼠标点击区域的问题!! 我想做一个对话框上面有一个人体位图,点击人体不同的部位在这个对话框的另一边就显示这个人体具体部位的位图图象,我用鼠标单击事件OnLButtonDown来做的.我现在能通过GetCursorPos(&point);来捕获鼠标坐标,但怎么确定点击位置矩形区域,然后怎么判断是否在那个区域内?请各位高人指点一下小弟! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 CRect btnRc; m_MyBtn.GetWindowRect(&btnRc); CPoint t_CurPnt; ::GetCursorPos(&t_CurPnt); if(btnRc.PtInRect(t_CurPnt)) { AfxMessageBox("在左边的窗口"); } CRect btnRc;m_MyBtn.GetWindowRect(&btnRc);取的是哪个矩形区域?我想取的是我那个人体位图的矩形大小. OnLButtonDown里面已经传入鼠标位置了,不需要自己获取坐标。对于你这个需求来说,首先要把位图进行分区,然后根据分区数据创建一个区域Region,下面就可以用GDI的区域函数来判断点击的位置。大致这样:先处理位图,把需要区分出来的区域单独提取成一个一个位图,一个位图里把“活性区”涂成一种颜色,背景涂成一种颜色,比如黑色和白色,程序开始逐个读入这些位图,根据位图数据创建区域(网上一些创建异型窗口的代码中有这个函数),把这些区域添加到一个列表中,鼠标点击消息中,从当前点生成一个矩形,逐个判断是否在某个区域内:CRect rc(point.x, point.y, point.x + 1, point.y + 1);if (rgn.RectInRegion(&rc)){ ...调用相应区域的处理函数} 如 Mackz(在相互) ( 四星(高级)) 信誉:117 可能是我太菜了还是有点不太明白,我单独提取出来的位图坐标该怎么样确定,是用具体的数值还是怎么的?MACKZ大哥能不能给一段示例的代码? 楼上说的都是对的啊,你照着做就可以了!!!你那个人体图的各个矩形区域应当是已知的吧(如果不固定那就另外处理),最苯的办法就是将它们都存成一个个固定的变量(相对你对话框的位置是固定的),比方说“手”的区域CRect(10,10,30,30)在你窗体的OnLButtonDown函数下处理,取得鼠标的坐标,然后判断这个鼠标点是否在这个区域中就可以了 写了点代码,希望有帮助。我从CWnd继承了一个CRgnView类,使用的时候,对话框上添加一个Static Text控件或者Picture Control控件,修改一下ID,然后用向导添加一个成员变量,变量的类型输入为CRgnView即可。该类的功能是在鼠标移动到激活的区域的时候,描绘区域的边框。RgnView.h:#pragma once#include "afxwin.h"#include <afxtempl.h>// CRgnViewclass CRgnView : public CWnd{ DECLARE_DYNAMIC(CRgnView)public: CRgnView(); virtual ~CRgnView();protected: //内存DC,用于显示位图 CDC m_dcMem; //内存位图,保存需要显示的位图 CBitmap m_bmpRgn; //当前激活的区域 CRgn* m_pActiveRgn; //保存区域的链表 CTypedPtrList<CObList, CRgn*> m_lstRgn;protected: DECLARE_MESSAGE_MAP()public: //修改窗口样式 virtual void PreSubclassWindow(); //绘图 afx_msg void OnPaint(); //鼠标移动消息 afx_msg void OnMouseMove(UINT nFlags, CPoint point); //从位图句柄创建区域的函数,默认白色为透明色,也就是区域的外部,其他颜色作为区域内部 CRgn* CreateRgnFromBitmap(HBITMAP hBmp, COLORREF clrTransparent = RGB(255, 255, 255));}; // RgnView.cpp : 实现文件//#include "stdafx.h"#include "RgnView.h"#include <shlwapi.h>// CRgnViewIMPLEMENT_DYNAMIC(CRgnView, CWnd)CRgnView::CRgnView(): m_pActiveRgn(NULL) //变量初始化{ //获取当前程序运行路径,因为假定位图文件放在和程序相同的目录下 TCHAR szPath[MAX_PATH]; ::GetModuleFileName(NULL, szPath, MAX_PATH); ::PathRemoveFileSpec(szPath); TCHAR szFile[MAX_PATH]; ::PathCombine(szFile, szPath, _T("rgn.bmp")); //从磁盘读取位图,当然应该修改成接收文件名就更灵活了 HBITMAP hbmp = (HBITMAP)::LoadImage(NULL, szFile, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_LOADFROMFILE); if (hbmp) m_bmpRgn.Attach(hbmp); //将位图句柄绑定到位图对象变量 //获取当前程序运行路径,因为假定位图文件放在和程序相同的目录下 ::PathCombine(szFile, szPath, _T("rgn_*.bmp")); //查找读取用来创建区域的位图 CFileFind flRgn; BOOL bFounded = flRgn.FindFile(szFile); while (bFounded) { bFounded = flRgn.FindNextFile(); HBITMAP hbmp = (HBITMAP)::LoadImage(NULL, flRgn.GetFilePath(), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_LOADFROMFILE); if (hbmp) { //从位图创建区域并加入链表中 m_lstRgn.AddTail(CreateRgnFromBitmap(hbmp)); } DeleteObject(hbmp); } flRgn.Close();}CRgnView::~CRgnView(){ //释放GDI和内存资源 if (m_bmpRgn.GetSafeHandle()) m_bmpRgn.DeleteObject(); if (m_dcMem.GetSafeHdc()) m_dcMem.DeleteDC(); POSITION pos = m_lstRgn.GetHeadPosition(); while (pos) { CRgn *pRgn = m_lstRgn.GetNext(pos); if (pRgn) delete pRgn; } m_lstRgn.RemoveAll();}BEGIN_MESSAGE_MAP(CRgnView, CWnd) ON_WM_PAINT() ON_WM_MOUSEMOVE()END_MESSAGE_MAP()// CRgnView 消息处理程序//修改窗口样式void CRgnView::PreSubclassWindow(){ // TODO: 在此添加专用代码和/或调用基类 ModifyStyle(0, SS_NOTIFY);//增加SS_NOTIFY样式,可以接收鼠标消息 CWnd::PreSubclassWindow();}//绘图void CRgnView::OnPaint(){ CPaintDC dc(this); // device context for painting // TODO: 在此处添加消息处理程序代码 // 不为绘图消息调用 CWnd::OnPaint() //绘制位图 if (!m_dcMem.GetSafeHdc()) m_dcMem.CreateCompatibleDC(&dc); if (m_bmpRgn.GetSafeHandle()) { BITMAP bmp; m_bmpRgn.GetBitmap(&bmp); CBitmap *pOldBmp = m_dcMem.SelectObject(&m_bmpRgn); CRgn rgnClip; CRect rcClient; GetClientRect(rcClient); rgnClip.CreateRectRgnIndirect(rcClient); dc.SelectClipRgn(&rgnClip); dc.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &m_dcMem, 0, 0, SRCCOPY); m_dcMem.SelectObject(pOldBmp); //描绘激活的区域边框 POSITION pos = m_lstRgn.GetHeadPosition(); while (pos) { CRgn *pRgn = m_lstRgn.GetNext(pos); if (m_pActiveRgn && m_pActiveRgn == pRgn) { CBrush brush(RGB(255, 0, 0)); dc.FrameRgn(pRgn, &brush, -2, -2); brush.DeleteObject(); } } }}void CRgnView::OnMouseMove(UINT nFlags, CPoint point){ // TODO: 在此添加消息处理程序代码和/或调用默认值 CRgn *pOldRgn = m_pActiveRgn; CRgn *pActiveRgn = NULL; //判断鼠标位置在哪个区域上 POSITION pos = m_lstRgn.GetHeadPosition(); while (pos) { CRgn *pRgn = m_lstRgn.GetNext(pos); CRect rc(point.x, point.y, point.x + 1, point.y + 1); if (pRgn && pRgn->RectInRegion(rc)) { //如果找到了一个区域就停止查找 pActiveRgn = pRgn; break; } } //如果找到地区域和原来的不一样才刷新,这样减少了刷新,增加效率 if (pOldRgn != pActiveRgn) { m_pActiveRgn = pActiveRgn; //刷新界面,只刷新需要更新的部分 InvalidateRgn(pOldRgn); InvalidateRgn(pActiveRgn); } CWnd::OnMouseMove(nFlags, point);}CRgn* CRgnView::CreateRgnFromBitmap(HBITMAP hBmp, COLORREF clrTransparent){ //这里的方法适用于24位色以上位图、桌面颜色也在24位色以上,否则要采用查找位图颜色标的方法 if (!hBmp) return NULL; CDC memDC; memDC.CreateCompatibleDC(NULL); BITMAP bmp; ::GetObject(hBmp, sizeof(BITMAP), &bmp); HBITMAP holdBmp = (HBITMAP)::SelectObject(memDC.m_hDC, hBmp); CRgn *pRgn = new CRgn; for (int x = 0; x < bmp.bmWidth; x++) for (int y = 0; y < bmp.bmHeight; y++) { COLORREF clrGet = memDC.GetPixel(x, y); if (clrGet != clrTransparent) { CRect rc(x, y, x + 1, y + 1); if (!pRgn->GetSafeHandle()) { pRgn->CreateRectRgnIndirect(&rc); } else { CRgn rgn; rgn.CreateRectRgnIndirect(&rc); //通过组合形成区域 pRgn->CombineRgn(pRgn, &rgn, RGN_OR); rgn.DeleteObject(); } } } ::SelectObject(memDC.m_hDC, holdBmp); memDC.DeleteDC(); return pRgn; } 呵呵,让Mackz老大敲了这么多代码,楼主的面子真大。 万分赶紧Mackz大哥对小弟的照顾,真是谢谢你了~~ WORD库与EXCEL库冲突的问题,高手请进。 急求对24位图像旋转函数 请教算法设计 TeeChart的问题,高手看看 当执行DoModal()后,对话框显示了出来,但,整个界面马上就无法操作了 谁知道怎么启用ICMP?急!!!! 2道数学题,解不出来。 求助!! RichEdit2.0中不能使用ctrl+c和ctrl+v是什么原因啊? !!!急啊!!!请问哪里有XPD风格的视频控制用的按钮和界面的图标或类库 如何在vc中打开bmp图片 请问如何设置控件的属性? 在对话框中预览相片
m_MyBtn.GetWindowRect(&btnRc);
CPoint t_CurPnt;
::GetCursorPos(&t_CurPnt);
if(btnRc.PtInRect(t_CurPnt))
{
AfxMessageBox("在左边的窗口");
}
m_MyBtn.GetWindowRect(&btnRc);取的是哪个矩形区域?
我想取的是我那个人体位图的矩形大小.
对于你这个需求来说,首先要把位图进行分区,然后根据分区数据创建一个区域Region,下面就可以用GDI的区域函数来判断点击的位置。
大致这样:
先处理位图,把需要区分出来的区域单独提取成一个一个位图,一个位图里把“活性区”涂成一种颜色,背景涂成一种颜色,比如黑色和白色,程序开始逐个读入这些位图,根据位图数据创建区域(网上一些创建异型窗口的代码中有这个函数),把这些区域添加到一个列表中,鼠标点击消息中,从当前点生成一个矩形,逐个判断是否在某个区域内:
CRect rc(point.x, point.y, point.x + 1, point.y + 1);
if (rgn.RectInRegion(&rc))
{
...调用相应区域的处理函数
}
你那个人体图的各个矩形区域应当是已知的吧(如果不固定那就另外处理),最苯的办法就是将它们都存成一个个固定的变量(相对你对话框的位置是固定的),比方说“手”的区域CRect(10,10,30,30)
在你窗体的OnLButtonDown函数下处理,取得鼠标的坐标,然后判断这个鼠标点是否在这个区域中就可以了
#include "afxwin.h"
#include <afxtempl.h>// CRgnViewclass CRgnView : public CWnd
{
DECLARE_DYNAMIC(CRgnView)public:
CRgnView();
virtual ~CRgnView();protected:
//内存DC,用于显示位图
CDC m_dcMem;
//内存位图,保存需要显示的位图
CBitmap m_bmpRgn;
//当前激活的区域
CRgn* m_pActiveRgn;
//保存区域的链表
CTypedPtrList<CObList, CRgn*> m_lstRgn;
protected:
DECLARE_MESSAGE_MAP()
public:
//修改窗口样式
virtual void PreSubclassWindow();
//绘图
afx_msg void OnPaint();
//鼠标移动消息
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
//从位图句柄创建区域的函数,默认白色为透明色,也就是区域的外部,其他颜色作为区域内部
CRgn* CreateRgnFromBitmap(HBITMAP hBmp, COLORREF clrTransparent = RGB(255, 255, 255));
};
//#include "stdafx.h"
#include "RgnView.h"
#include <shlwapi.h>// CRgnViewIMPLEMENT_DYNAMIC(CRgnView, CWnd)CRgnView::CRgnView()
: m_pActiveRgn(NULL) //变量初始化
{
//获取当前程序运行路径,因为假定位图文件放在和程序相同的目录下
TCHAR szPath[MAX_PATH];
::GetModuleFileName(NULL, szPath, MAX_PATH);
::PathRemoveFileSpec(szPath);
TCHAR szFile[MAX_PATH];
::PathCombine(szFile, szPath, _T("rgn.bmp"));
//从磁盘读取位图,当然应该修改成接收文件名就更灵活了
HBITMAP hbmp = (HBITMAP)::LoadImage(NULL, szFile, IMAGE_BITMAP, 0, 0,
LR_DEFAULTCOLOR | LR_LOADFROMFILE);
if (hbmp)
m_bmpRgn.Attach(hbmp); //将位图句柄绑定到位图对象变量 //获取当前程序运行路径,因为假定位图文件放在和程序相同的目录下
::PathCombine(szFile, szPath, _T("rgn_*.bmp"));
//查找读取用来创建区域的位图
CFileFind flRgn;
BOOL bFounded = flRgn.FindFile(szFile);
while (bFounded)
{
bFounded = flRgn.FindNextFile();
HBITMAP hbmp = (HBITMAP)::LoadImage(NULL, flRgn.GetFilePath(), IMAGE_BITMAP, 0, 0,
LR_DEFAULTCOLOR | LR_LOADFROMFILE);
if (hbmp)
{
//从位图创建区域并加入链表中
m_lstRgn.AddTail(CreateRgnFromBitmap(hbmp));
}
DeleteObject(hbmp);
}
flRgn.Close();
}CRgnView::~CRgnView()
{
//释放GDI和内存资源
if (m_bmpRgn.GetSafeHandle())
m_bmpRgn.DeleteObject();
if (m_dcMem.GetSafeHdc())
m_dcMem.DeleteDC();
POSITION pos = m_lstRgn.GetHeadPosition();
while (pos)
{
CRgn *pRgn = m_lstRgn.GetNext(pos);
if (pRgn)
delete pRgn;
}
m_lstRgn.RemoveAll();
}
BEGIN_MESSAGE_MAP(CRgnView, CWnd)
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()// CRgnView 消息处理程序//修改窗口样式
void CRgnView::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
ModifyStyle(0, SS_NOTIFY);//增加SS_NOTIFY样式,可以接收鼠标消息 CWnd::PreSubclassWindow();
}//绘图
void CRgnView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CWnd::OnPaint() //绘制位图
if (!m_dcMem.GetSafeHdc())
m_dcMem.CreateCompatibleDC(&dc);
if (m_bmpRgn.GetSafeHandle())
{
BITMAP bmp;
m_bmpRgn.GetBitmap(&bmp);
CBitmap *pOldBmp = m_dcMem.SelectObject(&m_bmpRgn);
CRgn rgnClip;
CRect rcClient;
GetClientRect(rcClient);
rgnClip.CreateRectRgnIndirect(rcClient);
dc.SelectClipRgn(&rgnClip);
dc.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &m_dcMem, 0, 0, SRCCOPY);
m_dcMem.SelectObject(pOldBmp); //描绘激活的区域边框
POSITION pos = m_lstRgn.GetHeadPosition();
while (pos)
{
CRgn *pRgn = m_lstRgn.GetNext(pos);
if (m_pActiveRgn && m_pActiveRgn == pRgn)
{
CBrush brush(RGB(255, 0, 0));
dc.FrameRgn(pRgn, &brush, -2, -2);
brush.DeleteObject();
}
}
}
}void CRgnView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRgn *pOldRgn = m_pActiveRgn;
CRgn *pActiveRgn = NULL;
//判断鼠标位置在哪个区域上
POSITION pos = m_lstRgn.GetHeadPosition();
while (pos)
{
CRgn *pRgn = m_lstRgn.GetNext(pos);
CRect rc(point.x, point.y, point.x + 1, point.y + 1);
if (pRgn && pRgn->RectInRegion(rc))
{
//如果找到了一个区域就停止查找
pActiveRgn = pRgn;
break;
}
}
//如果找到地区域和原来的不一样才刷新,这样减少了刷新,增加效率
if (pOldRgn != pActiveRgn)
{
m_pActiveRgn = pActiveRgn; //刷新界面,只刷新需要更新的部分
InvalidateRgn(pOldRgn);
InvalidateRgn(pActiveRgn);
} CWnd::OnMouseMove(nFlags, point);
}CRgn* CRgnView::CreateRgnFromBitmap(HBITMAP hBmp, COLORREF clrTransparent)
{
//这里的方法适用于24位色以上位图、桌面颜色也在24位色以上,否则要采用查找位图颜色标的方法
if (!hBmp)
return NULL; CDC memDC;
memDC.CreateCompatibleDC(NULL); BITMAP bmp;
::GetObject(hBmp, sizeof(BITMAP), &bmp); HBITMAP holdBmp = (HBITMAP)::SelectObject(memDC.m_hDC, hBmp); CRgn *pRgn = new CRgn;
for (int x = 0; x < bmp.bmWidth; x++)
for (int y = 0; y < bmp.bmHeight; y++)
{
COLORREF clrGet = memDC.GetPixel(x, y);
if (clrGet != clrTransparent)
{
CRect rc(x, y, x + 1, y + 1);
if (!pRgn->GetSafeHandle())
{
pRgn->CreateRectRgnIndirect(&rc);
}
else
{
CRgn rgn;
rgn.CreateRectRgnIndirect(&rc);
//通过组合形成区域
pRgn->CombineRgn(pRgn, &rgn, RGN_OR);
rgn.DeleteObject();
}
}
} ::SelectObject(memDC.m_hDC, holdBmp);
memDC.DeleteDC(); return pRgn;
}