MFC鼠标单击截获鼠标双击事件,且无法记录单击的数据的解决方案

时间:2023-03-08 16:09:39
MFC鼠标单击截获鼠标双击事件,且无法记录单击的数据的解决方案

遇到的问题:

  1. 鼠标点击会截断鼠标双击的事件,无法保存椭圆的数据。也就是说双击执行的过程是OnLButtonDown,OnLButtonUp,OnLButtonDblClk,OnLButtonUp。并不是想象中的直接执行OnLButtonDblClk,那么如果在OnLButtonDown中定义起始点,OnLButtonUp中定义终点,椭圆可以直接画出,但是双击时,会先执行OnLButtonDown,OnLButtonUp那么起点和终点就会被重新覆盖,且覆盖后的点的坐标都一样,然后才执行OnLButtonDblClk,此时,起点和终点相同,就没法再画椭圆,而且最后还会再执行一次OnLButtonUp。

那么如何解决问题?

刚开始百度发现他们是通过判断鼠标两次点击的时间差是否小于系统定义的时间差500,鼠标双击会先执行一次OnLButtonDown然后在第二次的OnLButtonDown来判断是不是鼠标在双击,然而这种方法还是会将原始数据覆盖,无法保存那条线的数据。

后来我在睡觉前突然想到可以通过数组来保存原始数据,通过数组的下标来控制鼠标双击时的数据保存到另一个数组中,以避免数据的覆盖,于是写出上面的程序。

  1. MFC中数据的查看

MFC中如何查看数据,刚开始打算直接使用TextOut来直接输出执行过程中的数据,但是,它只支持CString类型,遇到int型还要sprintf转格式,太麻烦,而且也不能实时刷新,显示的范围还有限。

使用控制台输出,可是MFC执行时 ,连控制台的界面都没见。

只能使用文件流来输出信息。

实现思路:

1通过两点画椭圆

2.以这将这两点组合到一起,也就是可以看做一条线决定了一个椭圆。每画一个椭圆就往线的数组里记录一次。

3.获取鼠标双击的坐标,并判断这点是否在椭圆内部,如果在内部,则重画椭圆(带填充)并将线的数组清空,如果不在,则继续双击时,线的数组的下标不增加,重新覆盖数据,然后再判断这个点是否在椭圆内。

程序:

全局变量
 CPoint start_p,end_p;
bool flag=true;//双击时的点是否在椭圆内
ofstream myfile;
int i=;//用来计数线的数组 class Line{
public :
CPoint p1,p2;
Line(){
p1.SetPoint(,);
p2.SetPoint(,);
}
void set_p1( CPoint a1){
p1.SetPoint(a1.x,a1.y);
}
void set_p2( CPoint a2){
p2.SetPoint(a2.x,a2.y);
} }; Line l[];

  1 // CMy91View 消息处理程序
 

 void CMy91View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: ÔÚ´ËÌí¼ÓÏûÏ¢´¦Àí³ÌÐò´úÂëºÍ/»òµ÷ÓÃĬÈÏÖµ CView::OnLButtonDown(nFlags, point); //单击
start_p=point;
l[i].set_p1(point); myfile.open("1.txt",ios::app);
myfile<<"单击OnLButtonDown:"<<endl;
myfile<<"l:"<<i<<endl;
myfile<<"p1:("<<l[i].p1.x<<","<<l[i].p1.y<<")"<<endl;
myfile<<"p2:("<<l[i].p2.x<<","<<l[i].p2.y<<")"<<endl;
myfile<<endl<<endl;
myfile.close(); } void CMy91View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: ÔÚ´ËÌí¼ÓÏûÏ¢´¦Àí³ÌÐò´úÂëºÍ/»òµ÷ÓÃĬÈÏÖµ CView::OnLButtonUp(nFlags, point); if(){
end_p=point;
l[i].set_p2(point); CClientDC dc(this);
dc.Ellipse(start_p.x,start_p.y,end_p.x,end_p.y); myfile.open("1.txt",ios::app);
myfile<<"单击OnLButtonUp:"<<endl;
myfile<<"l:"<<i<<endl;
myfile<<"p1:("<<l[i].p1.x<<","<<l[i].p1.y<<")"<<endl;
myfile<<"p2:("<<l[i].p2.x<<","<<l[i].p2.y<<")"<<endl;
myfile<<endl<<endl;
myfile.close(); //判断是不是双击,双击后会让下一个坐标的p2点不为0,但p1点为0;
if(l[i].p1.x!=&&l[i].p1.y!=){
i++;//增加椭圆
}else{
if(i>&&!flag){
i--;//不在圆内双击,计数减1,,重新计数
} } }
} //判断一个点是否在椭圆内部
bool in_Elliplse(CPoint p1,CPoint p2,CPoint p3){
CPoint center((p1.x+p2.x)/,(p1.y+p2.y)/);
CPoint r(abs(p1.x-p2.x)/,abs(p1.y-p2.y));
CPoint p3_0(p3.x-center.x,p3.y-center.y); if(r.x>r.y){
double x=pow((double)p3_0.x,)/pow((double)r.x,);
double y=pow((double)p3_0.y,)/pow((double)r.y,);
if(x+y<=){
return true;
}else{
return false;
}
}else{
double x=pow((double)p3_0.y,)/pow((double)r.x,);
double y=pow((double)p3_0.x,)/pow((double)r.y,);
if(x+y<=){
return true;
}else{
return false;
}
} } void CMy91View::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: ÔÚ´ËÌí¼ÓÏûÏ¢´¦Àí³ÌÐò´úÂëºÍ/»òµ÷ÓÃĬÈÏÖµ CView::OnLButtonDblClk(nFlags, point); myfile.open("1.txt",ios::app);
myfile<<"双击"<<endl<<"OnLButtonDblClk:"<<endl;
myfile<<"l:"<<i<<endl;
myfile<<"p1:("<<l[i].p1.x<<","<<l[i].p1.y<<")"<<endl;
myfile<<"p2:("<<l[i].p2.x<<","<<l[i].p2.y<<")"<<endl;
myfile<<"l-1:"<<i-<<endl;
myfile<<"p1:("<<l[i-].p1.x<<","<<l[i-].p1.y<<")"<<endl;
myfile<<"p2:("<<l[i-].p2.x<<","<<l[i-].p2.y<<")"<<endl;
myfile<<"l-2:"<<i-<<endl;
myfile<<"p1:("<<l[i-].p1.x<<","<<l[i-].p1.y<<")"<<endl;
myfile<<"p2:("<<l[i-].p2.x<<","<<l[i-].p2.y<<")"<<endl;
myfile<<endl<<endl;
myfile.close(); //填充
if(in_Elliplse(l[i-].p1,l[i-].p2,l[i-].p1)){
CBrush brush(RGB(,,));
CClientDC dc(this);
dc.SelectObject(&brush);
dc.Ellipse(l[i-].p1.x,l[i-].p1.y,l[i-].p2.x,l[i-].p2.y); //重新计数
i=; //清空椭圆
for(int a=;a<;a++){
CPoint p(,);
l[i].set_p1(p);
l[i].set_p2(p);
}
flag=true;
}else{
flag=false;
} }

数据分析:

使用文件流来输出信息,如下:

在第一次鼠标按下再抬起时画椭圆,然后椭圆内双击填充时的数据信息:

单击OnLButtonDown:

l:0

p1:(270,94)

p2:(0,0)

单击OnLButtonUp:

l:0

p1:(270,94)

p2:(488,222)

单击OnLButtonDown:

l:1

p1:(391,176)

p2:(0,0)

单击OnLButtonUp:

l:1

p1:(391,176)

p2:(391,176)

双击

OnLButtonDblClk:

l:2

p1:(0,0)

p2:(0,0)

l-1:1

p1:(391,176)

p2:(391,176)

l-2:0

p1:(270,94)

p2:(488,222)

单击OnLButtonUp:

l:0

p1:(0,0)

p2:(391,176)

在第一次鼠标按下再抬起时画椭圆,然后椭圆外双击(可以任意次)这里就一次,然后在椭圆内双击填充时的数据信息:

单击OnLButtonDown:

l:0

p1:(335,85)

p2:(0,0)

单击OnLButtonUp:

l:0

p1:(335,85)

p2:(601,197)

单击OnLButtonDown:

l:1

p1:(397,284)

p2:(0,0)

单击OnLButtonUp:

l:1

p1:(397,284)

p2:(397,284)

双击

OnLButtonDblClk:

l:2

p1:(0,0)

p2:(0,0)

l-1:1

p1:(397,284)

p2:(397,284)

l-2:0

p1:(335,85)

p2:(601,197)

单击OnLButtonUp:

l:2

p1:(0,0)

p2:(397,284)

单击OnLButtonDown:

l:1

p1:(423,141)

p2:(397,284)

单击OnLButtonUp:

l:1

p1:(423,141)

p2:(423,140)

双击

OnLButtonDblClk:

l:2

p1:(0,0)

p2:(397,284)

l-1:1

p1:(423,141)

p2:(423,140)

l-2:0

p1:(335,85)

p2:(601,197)

单击OnLButtonUp:

l:0

p1:(0,0)

p2:(423,140)

实验结果:

MFC鼠标单击截获鼠标双击事件,且无法记录单击的数据的解决方案

程序的不足:

在程序只有双击填充时,线的数组才会清空,下标再次重0开始,如果用户不双击,一直在画椭圆,那么最多画30个椭圆(这个数值可以任意修改),但这个数值不是无穷的。或许可以通过动态建立数组或者使用线性列表来解决。(如果有谁解决了,@我,大家一起进步)