在 vc++win32 Application 中区分鼠标的单双击事件

土豆丫 2010-10-29 07:39:38
下面是我自己写的一个程序代码框架
// 头文件包含 文件中包含应用程序中所需的数据类型和数据结构定义
#include<windows.h>



// 窗口过程函数声明
LRESULT CALLBACK WinProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam );

// 程序的入口处:WinMain函数
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance 由于windows95以及以后的
// windows版本都是独立的进程空间,因此它的值总是NULL
LPSTR lpCmdLine, // command line
int nCmdShow // show state
)
{
char lpszClassname[]="窗口"; // 窗口类名
char lpszTitle[]="My_Windows"; // 窗口标题名

// 窗口类的定义
WNDCLASS wc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hInstance=hInstance;
wc.lpfnWndProc=WinProc;
wc.lpszClassName=lpszClassname;
wc.lpszMenuName=NULL; // 窗口中无菜单
wc.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
// 注册窗口类,如果注册失败则发出警告声音
if(!RegisterClass(&wc))
{
MessageBeep(0);
return FALSE;
}

// 创建窗口
HWND hwnd;
hwnd=CreateWindow(lpszClassname,lpszTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);

ShowWindow(hwnd,SW_SHOWNORMAL); // 显示窗口

UpdateWindow(hwnd); // 更新窗口 绘制用户区

// 消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}



// 窗口过程函数(回调函数 callback),该函数处理窗口上的各种输入事件,在此添加代码
LRESULT CALLBACK WinProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
static BOOL DLine=FALSE,DArc=FALSE,DRectangle=FALSE;
switch(uMsg)
{
case WM_LBUTTONDOWN:
if(!DLine)
{
DLine=TRUE;
}
InvalidateRect(hwnd,NULL,TRUE);
break;
case WM_LBUTTONUP:
if(DLine)
{
DLine=FALSE;
}
InvalidateRect(hwnd,NULL,TRUE);
break;
case WM_RBUTTONDOWN:
DArc=~DArc;
InvalidateRect(hwnd,NULL,TRUE);
break;
case WM_RBUTTONUP:
break;
case WM_LBUTTONDBLCLK:

if(!DRectangle)
{
DLine=FALSE;
DRectangle=TRUE;
InvalidateRect(hwnd,NULL,TRUE);
}
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
if(DLine)
{
LineTo(hdc,500,500);
}
else if(DArc)
{
Arc(hdc,63,137,138,212,100,137,100,137);
}
else if(DRectangle)
{
Rectangle(hdc,213,212,287,250);
}
EndPaint(hwnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}
哪位帮我用改下,用Settimer区分鼠标的单双击
...全文
467 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
wltg2001 2010-10-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 tudouya1 的回复:]
是要用这个方法实现鼠标的单双击的,也就是说不处理WM_LBUTTONDOWNDBCLICK,只处理WM_LBUTTONDOWN来实现鼠标的单双击
[/Quote]
你的意思是不处理WM_LBUTTONDOWNDBCLICK,而是用WM_LBUTTONDOWN来模拟双击?
明明有双击消息,为什么要这样呢?
你可以设一个static变量,每有WM_LBUTTONDOWN消息时将它加1,当它的值是2时,就是双击了,另外还得设一个定时器,在一定时间内将它清0。
土豆丫 2010-10-30
  • 打赏
  • 举报
回复
是要用这个方法实现鼠标的单双击的,也就是说不处理WM_LBUTTONDOWNDBCLICK,只处理WM_LBUTTONDOWN来实现鼠标的单双击
土豆丫 2010-10-30
  • 打赏
  • 举报
回复
独立处理单击、双击和三击             我们先看一下Windows对鼠标的响应。对左键而言,如果鼠标按下,则产生     WM_LBUTTONDOWN消息。接着,鼠标释放产生WM_LBUTTONUP消息;但如果鼠标双击,     则Windows并不仅仅只产生WM_LBUTTONDBLCLK   消息,而是先产生WM_LBUTTONDOWN消     息,然后产生WM_LBUTTONDBLCLK消息,其中还有WM_LBUTTONUP等消息,这里暂不讨     论。对于鼠标的三击,Windows没有提供独立的消息,但我们不妨认为三击是在     WM_LBUTTONDBLCLK消息之后再发一个WM_LBUTTONDOWN消息。所以,在应用程序编程     时若要窗口分别独立地响应鼠标的单击、双击、三击消息,只有用户自己动手去处     理。例如,Winows95中的文件夹改名就是一个例子,用鼠标单击一个已经加亮的文     件夹名称时稍作停留便可改名,如果双击则可打开该文件。这时,就必须单独处理     鼠标的单击和双击,否则执行顺序应该是先响应WM_LBUTTONDOWN消息,然后再响应     WM_LBUTTONDBLCLK,即先改名再打开,这是事与愿违的。             为了单独识别这三个鼠标消息,我们不能直接使用WM_LBUTTONDOWN和     WM_LBUTTONDBLCLK消息来判断鼠标的单击和双击。这里,定义三个“伪”消息     WM_MYSNGCLK、WM_MYDBLCLK、WM_MYTHRCLK,用它们分别标识鼠标的单击、双击和三     击事件。由于我们在两次连续的鼠标单击后还不能确定是否有三击,所以再增加一     个   WM_MYDBLCLKT伪消息,在处理该伪消息时再进一步判断双击与三击。我们只处理     WM_LBUTTONDOWN消息,所以注册窗口类时不设置CS_DBLCLKS风格。                 具体处理过程如下:设置逻辑标志FLAG1及FLAG2,初始值均为FALSE,当已经单     击时将FLAG1置为TRUE,已经双击时将FLAG2置为TRUE。在处理WM_LBUTTONDOWN消息     时通过函数   SetTimer增加一个计时器ID_TIMER1,计时器的时间参数置为鼠标双击     的时间间隔(用GetDoubleClickTime取得),并将FLAG1置为TRUE。如果计时器     D_TIMER1发出消息,则表明在规定时间内没有按键,可以判断鼠标为单击,可发出     WM_MYSNGCLK消息,同时将FLAG1置为FALSE;如果计时器消息没有产生,则表明在规     定的时间内有鼠标键按下,此时鼠标已经双击,将FLAG2置为TRUE,但是否有三击还     需要继续判断,此时发出WM_MYDBLCLKT消息,我们用同样的方法在伪消息     WM_MYDBLCLKT中再定义一个计时器ID_TIMER2。同理,如果计时器ID_TIMER2发出消     息,则表明在规定时间内没有按键,可以判断鼠标为双击,可发出WM_MYDBLCLK消息     ;如果计时器ID_TIMER2没有发出消息,则表明在规定的时间内有鼠标键被按下,此     时鼠标已经三击,可以发出WM_MYTHRCLK消息。至此已完成识别,当然计时器要使用       KillTimer及时删除。另外要注意的是,鼠标双击的时间间隔不要设置太大,否则延     时感太明显。             下面是具体的实现方法,本文只给出窗口过程WndProc的部分内容,其它函数与     通常的Windows应用程序大同小异,故从略。             #define   ID_TIMER1   1001   /*   计时器1*/             #define   ID_TIMER2   1002   /*   计时器2*/             #define   WM_MYDBLCLKT   WM_USER+100   /*当已经双击但还不能决定三击时发出*/             #define   WM_MYSNGCLK   WM_USER+101   /*已经确定为单击时发出*/             #define   WM_MYDBLCLK   WM_USER+102   /*已经确定为双击时发出*/             #define   WM_MYTHRCLK   WM_USER+103   /*已经确定为三击时发出*/             LRESULT   CALLBACK   WndProc(HWND   hwnd,UINT   uMessage,WPARAM   wparam,LPARAM   lparam)             {                static   int   FLAG1,FLAG2;                int   wTime;                POINT   pt;                switch   (uMessage)                {                case   WM_LBUTTONDOWN:   /*程序只对单击消息进行处理,不处理双击消息*/                GetCursorPos(&pt);   /*取鼠标位置用于传递消息中的LPARAM*/                ScreenToClient(hwnd,&pt);                if(!   FLAG2)   /*FLAG2不为真时,鼠标状态为第一次单击或第二次单击*/                {if(!FLAG1)   /*FLAG1不为真时为第一次单击*/                {   wTime=GetDoubleClickTime();   /*取鼠标双击时间间隔*/                SetTimer(hwnd,ID_TIMER1,wTime,NULL);   /*第一次单击后建立计时器*/                }                if(FLAG1)   /*FLAG1为真,已经确定为双击,发出WM_MYDBLCLKT继续判断*/                {PostMessage(hwnd,WM_MYDBLCLKT,0,MAKELPARAM(pt.x,pt.y));                FLAG1=FALSE;                KillTimer(hwnd,ID_TIMER1);                break;                }                FLAG1=TRUE;                }                if(FLAG2)   /*FLAG2为真,已经确定为三击*/                {PostMessage(hwnd,WM_MYTHRCLK,0,MAKELPARAM(pt.x,pt.y));                FLAG2=FALSE;                KillTimer(hwnd,ID_TIMER2);                break;                }                break;                case   WM_TIMER:   /*计时器消息产生,说明鼠标没有按键操作*/                switch(wparam)                {                case   ID_TIMER1:   /*第一次按键后没有后续按键,故确定为单击*/                {   KillTimer(hwnd,wparam);                FLAG1=FALSE;                GetCursorPos(&pt);                ScreenToClient(hwnd,&pt);                PostMessage(hwnd,WM_MYSNGCLK,0,MAKELPARAM(pt.x,pt.y));                }                break;                case   ID_TIMER2:   /*第二次按键后没有后续按键,故确定为双击*/                {KillTimer(hwnd,wparam);                FLAG2=FALSE;                GetCursorPos(&pt);                ScreenToClient(hwnd,&pt);                PostMessage(hwnd,WM_MYDBLCLK,0,MAKELPARAM(pt.x,pt.y));                }                break;                }                break;                case   WM_MOUSEMOVE:   /*如果鼠标移动,则不认为是双击或三击*/                FLAG1=FALSE;                FLAG2=FALSE;                break;                case   WM_MYDBLCLKT:   /*双击后等待再次按鼠标键*/                wTime=GetDoubleClickTime();                SetTimer(hwnd,ID_TIMER2,wTime,NULL);                FLAG2=TRUE;                break;    
zgl7903 2010-10-29
  • 打赏
  • 举报
回复
case WM_LBUTTONDBLCLK: 缺少了 break
mayudong1 2010-10-29
  • 打赏
  • 举报
回复
如果在窗口风格中未包含CS_DBLCLKS,而使用者在短时间内双击了鼠标按键,那么窗口消息处理程序会接收到下面这些消息:

WM_LBUTTONDOWN

WM_LBUTTONUP

WM_LBUTTONDOWN

WM_LBUTTONUP

窗口消息处理程序可能在这些键的消息之前还收到了其它消息。如果您想实作自己的双击处理,那么您可以使用Windows函数GetMessageTime取得WM_LBUTTONDOWN消息之间的相对时间。第八章将更详细地讨论这个函数。

如果您的窗口类别风格中包含了CS_DBLCLKS,那么双击时窗口消息处理程序将收到如下消息:

WM_LBUTTONDOWN

WM_LBUTTONUP

WM_LBUTTONDBLCLK

WM_LBUTTONUP

WM_LBUTTONDBLCLK消息简单地替换了第二个WM_LBUTTONDOWN消息。


以上是windows程序设计上的话
产生双击鼠标的消息的时候,是会伴随这wm_lbuttondown消息的
你的代码是在WM_LBUTTONDOWN消息中显示的线
所以会先画一次线,再画矩形了
土豆丫 2010-10-29
  • 打赏
  • 举报
回复
就是实现 单击画一条线 双击画矩形 现在我的问题是 双击的时候他不但画了直线 还画了矩形
mayudong1 2010-10-29
  • 打赏
  • 举报
回复
不知道你想要什么效果

单双击不都分别有对应的消息的吗

19,469

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧