回 帖 发 新 帖 刷新版面

主题:请教WM_MOUSEMOVE和Invalidaterect()的奇怪问题

各位朋友大家好!!  我初学windows编程。
发现有些消息的处理和函数的功能和想象中的并不一致,有2个想不明白的问题,就写了段代码和我的
理解,请大家帮我分析一下我写下的代码段,帮我解释一下原因。十分感谢!!!

    [...]
static int iCount = 0;   // number of calling WM_PAINT
char Buff[50];
switch(message)
{
    case WM_LBUTTONDOWN:  // left mouse button click
    InvalidateRect(hwnd,NULL,TRUE);    // (1) ???????????????????????????    
    hdc = GetDC();

    sprintf(Buff,"Clicked Position:%i,%i",Point.x,Point,y);
    TextOut(hdc,0,0,Buff,lstrlen(Buff));

    ReleaseDC(hwnd,hdc);
        return 0;

    case WM_MOUSEMOVE:             // (2) ???????????????????????
    hdc = GetDC();

    TextOut(hdc,0,yClient/2,"Moving",lstrlen("Moving"));

    ReleaseDC(hwnd,hdc);
    InvalidateRect(hwnd,NULL,TRUE);    
    return 0;

    case WM_PAINT:
    hdc = BeginPaint(hwnd,&ps);

    sprintf(Buff,"OnPaint: %i times",iCount);
    TextOut(hcd,0,yClient-16,Buff,lstrlen(Buff));
    iCount++;      // increment every time calling WM_PAINT 

    EndPaint(hwnd,&ps);
    return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
    [...]
根据我的理解,运行后,窗口客户区域应该显示 OnPaint: 0 times
是因为WINMAIN中创建窗口时调用的UpdateWindow(),然后静态变量iCount自增一次,为下次
WM_PAINT的调用次数显示做准备。
    问题1:
    我首先假定代码段中没有标记注释为 // (1) ??????????????? 的这句Invalidaterect。
    此时,如果客户区域单击鼠标左键,就会在0,0位置写出 Clicked Position:x,y。我以Point变量
表示当前鼠标的位置,假如写出来的位置是Clicked Position:566,588。但是根据此消息,并没通知
更新客户区域,原来的数值还留会在客户区,所以在为 3,3 的位置单击鼠标,本来应该显示为:
         Clicked Position:3,3
但是由于没有更新,实际的显示受到原来残留的值影响:Clicked Position:3,3,588  其中后边的,588
就是原来残留的值, 3,3这3个字符只是覆盖了原来的566。
    所以我加上了注释为// (1) ???????????????的这句Invalidaterect,我认为在消息的开头先调用
这个函数通知窗口客户区域擦除原来背景重新画,这样原来残留的值就被擦掉了,然后向下执行代码:
输出文本,也就是写出新的鼠标位置。
    可是实际运行的结果却不会写出的文本,无论怎么单击都不会,只显示出WM_PAINT中的OnPaint……
为什么会是这样??
    
    问题2:
    关于WM_MOUSEMOVE消息,这次其中的注释为// (2) ???????????????的是一直存在的。
    这时,根据我的想法,把鼠标指针在客户区域移动就会导致窗口重画,每次重画OnPaint: X times
的iCount值都会增加。而鼠标停在客户区域中不动,就不会看见OnPaint的值在不断增加.而实际上,即
使把鼠标停在客户区域中,那个iCount值也在不断地增加,应该表示还在不停的调用WM_PAINT,只是我移
动鼠标的时候,它增加得更快而以,只有把鼠标移到客户区以外这个值才停止增加,
    WM_MOUSEMOVE消息不是应该只监听鼠标移动吗?怎么不动时也会发送这个消息啊???

    求各位的解答,再次感谢!!!!

回复列表 (共5个回复)

沙发

case WM_RBUTTONDOWN:  // left mouse button click
这好像不是左键按下的消息吧.是不是应该这样呀:WM_LBUTTONDOWN

板凳

是我写错了  不好意思  现在改正了  还请各位帮忙啊!!

3 楼

TextOut里的 yClient 赋值了吗

4 楼

要回答你的第一个问题就应该先弄明白InvalidateRect函数,按照你程序中的调用形式:InvalidateRect(hwnd,NULL,TRUE)是使整个客户区无效,并且用背景色从绘客户区,这里要注意了,这个函数并不会引发WM——PAINT消息,而只是单纯的合并无效区域.所以真实的过程是这样的:
你单击中鼠标左键,设置了一个无效区域(是整个客户区)然后TEXTOUT输出了文本,接下来WINDOWS检查发现存在一个无效区域,这会引发WM——PAINT消息,好差除客户区,显示ONPAINT中的内容,因为时间短暂,所以你看不到单击中鼠标左键显示的内容了

问题2也是出在InvalidateRect函数上,你明白问题1了自然就明白了

5 楼

太感谢了!!!  原来调用Inv……函数时并不是马上重新修改客户区啊 这样就明白了  
还有  yClient是假设在WM_SIZE修改了后赋值  原文中提到这方面了可能是内容太多  3楼的朋友没有耐性看完  所以没注意到  不好意思!!

我来回复

您尚未登录,请登录后再回复。点此登录或注册