hur.cn - 华软网

 热门搜索

关于SendMessage函数在父窗口和子窗口中传递消息的问题

  作者:未知    来源:网络    更新时间:2015/11/25
我在子窗口中用SendMessage发送消息给父窗口的WM_PAINT函数,但是怎么也接受不到lParam,IParam是一个我定义的整数变量。
但是我在子窗口中用SendMessage发送给自己的WM_PAINT函数却很容易的接收到了。不知道为什么,求教。
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static HWND hwndChild[DIVISIONS] ;
     int         cxBlock, cyBlock, x, y ;
 int static cxChar, cyChar;
 PAINTSTRUCT ps;
 HDC hdc;
 int n, size;
 TCHAR szBuffer2[40];
 RECT        rect;
     
 switch (message)
 {
 case WM_CREATE:
 //创建10个子窗口
 for (x = 0; x < DIVISIONS; x++)
 hwndChild[x] = CreateWindow(szChildClass, NULL,
 WS_CHILDWINDOW | WS_VISIBLE,
 0, 0, 0, 0,
 hwnd, (HMENU)x,
 ((LPCREATESTRUCT)lParam)->hInstance,
 NULL);
 return 0;

 case WM_SIZE:
 cxBlock = LOWORD(lParam) / DIVISIONS;
 cyBlock = HIWORD(lParam) / 3;
 rect.left = 0;
 rect.top = 0;
 rect.right = LOWORD(lParam);
 rect.bottom = HIWORD(lParam) / 2;

 for (x = 0; x < DIVISIONS; x++)
 MoveWindow(hwndChild[x],
 x * cxBlock, HIWORD(lParam) - cyBlock, //调整子窗口的所在位子
 cxBlock, cyBlock, TRUE);
 return 0;

 case WM_LBUTTONDOWN:
 //  MessageBeep (0) ;
 //  return 0 ;

 // On set-focus message, set focus to child window

 case WM_SETFOCUS:
 SetFocus(GetDlgItem(hwnd, idFocus));
 return 0;

 // On key-down message, possibly change the focus window

 case WM_KEYDOWN:
 x = idFocus & 0xFF;
 y = idFocus >> 8;

 switch (wParam)
 {
 // case VK_UP:    y-- ;                    break ;
 //  case VK_DOWN:  y++ ;                    break ;
 case VK_LEFT:  x--;                    break;
 case VK_RIGHT: x++;                    break;
 // case VK_HOME:  x = y = 0 ;              break ;
 // case VK_END:   x = y = DIVISIONS - 1 ;  break ;
 default:       return 0;
 }

 x = (x + DIVISIONS) % DIVISIONS;
 y = (y + DIVISIONS) % DIVISIONS;

 idFocus = y << 8 | x;

 SetFocus(GetDlgItem(hwnd, idFocus));
 return 0;
 case WM_PAINT:
 InvalidateRect(hwnd, &rect, TRUE);
 hdc = BeginPaint(hwnd, &ps);    
 if (wParam == 1){          //这里接收不到消息,不知道为什么
 size = wsprintf(szBuffer2, TEXT("%d"), lParam);
 TextOut(hdc, 0, 10, szBuffer2, size);
 }
 EndPaint(hwnd, &ps);
 return 0;
     case WM_DESTROY :
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message, 
                               WPARAM wParam, LPARAM lParam)
{
     HDC         hdc ;
     PAINTSTRUCT ps ;
     RECT        rect ;
 int x, y;
 int num,size;
 TCHAR szBuffer[40];

 
     
     switch (message)
     {
     case WM_CREATE :
 
          SetWindowLong (hwnd, 0, 0) ;       // on/off flag
          return 0 ;

     case WM_KEYDOWN:
               // Send most key presses to the parent window
          
          if (wParam != VK_RETURN && wParam != VK_SPACE)
          {
               SendMessage (GetParent (hwnd), message, wParam, lParam) ;
               return 0 ;
          }
               // For Return and Space, fall through to toggle the square
          
     case WM_LBUTTONDOWN :
 
 srand(time(NULL));
 num = rand() % 10;

 SetWindowLong(hwnd, 0, 1 ^ GetWindowLong(hwnd, 0));
 SetFocus(hwnd);

 SendMessage(hwnd, WM_PAINT, 2, num);//在子窗口自己的WM_PAINT传送消息
 UpdateWindow(hwnd);
 SendMessage(GetParent(hwnd), WM_PAINT, 1, num);//给父窗口WM_PAINT传送消息和数据
 UpdateWindow(GetParent(hwnd));
         
        //  InvalidateRect (hwnd, NULL, FALSE) ;
  
          return 0 ;

               // For focus messages, invalidate the window for repaint
          
     case WM_SETFOCUS:
          idFocus = GetWindowLong (hwnd, GWL_ID) ;

               // Fall through

     case WM_KILLFOCUS:
          InvalidateRect (hwnd, NULL, TRUE) ;
          return 0 ;
          
     case WM_PAINT :
 
          hdc = BeginPaint (hwnd, &ps) ;
          
          GetClientRect (hwnd, &rect) ;
          Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;

               // Draw the "x" mark
          
          if (GetWindowLong (hwnd, 0))
          {
            /*   MoveToEx (hdc, 0,          0, NULL) ;
               LineTo   (hdc, rect.right, rect.bottom) ;
               MoveToEx (hdc, 0,          rect.bottom, NULL) ;
               LineTo   (hdc, rect.right, 0) ;
   */
          }

               // Draw the "focus" rectangle
  if (wParam == 2){  //这里可以接收到消息
  x = rect.left + rect.right / 10;
  y = rect.top + rect.bottom / 10;
  size = wsprintf(szBuffer, TEXT("%d"), lParam);
  // 注意,如果要用textout输出变量,一定要用wsprintf将整数转换为字符串,利用缓冲区。
  TextOut(hdc, x, y, szBuffer, size);//注意利用wsprintf.

  }
          if (hwnd == GetFocus ())
          {  
  
               rect.left   += rect.right / 10 ;
               rect.right  -= rect.left ;
               rect.top    += rect.bottom / 10 ;
               rect.bottom -= rect.top ;
  
               SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
               SelectObject (hdc, CreatePen (PS_DASH, 0, 0)) ;
   
   Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
   
               DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;
          }

          EndPaint (hwnd, &ps) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

---华软 网友回答---
有可能 WM_PAINT 都没有接受到。

你不如换一个消息先试试 ...

===========

另外我记得 Windows 对 WM_PAINT 是有特殊处理的,不如如果与几个没有处理的话会被合并成一个。记不清了。
---华软网友回复---
GetParent(hwnd) 返回的句柄是和父窗口的一样吗
---华软网友回复---
窗口句柄是对的,GetParent(hwnd) 返回的句柄是和父窗口的一样
---华软网友回复---
换个其它消息, invalidate , update 就相当于send paint了
---华软网友回复---
仅供参考,没你写的那么复杂:http://blog.csdn.net/wangshiqilin_fjy/article/details/14458843
---华软网友回复---
父窗口重绘就会重绘子窗口,你这是玩什么?
窗口重绘消息,不需要自己在程序里发送,
需要的话 invalidate , update 系列函数可以自动发送他们
---华软网友回复---
这是我自己写的一个小实验,就是一个简易的纸牌游戏,下面子窗口随机产生数0-9,父窗口客户区输出该数,现在问题就是消息传不过去啊,传不到父窗口中。却可以传给子窗口
---华软网友回复---
引用 6 楼 lm_whales 的回复:
父窗口重绘就会重绘子窗口,你这是玩什么?
窗口重绘消息,不需要自己在程序里发送,
需要的话 invalidate , update 系列函数可以自动发送他们


什么意思啊, invalidate , update 系列函数可以自动发送他们,能不能举个例子
---华软网友回复---
窗口没有失效,你发WM_PAINT也没有用
用InvalidateRect (HWND ,PRECT ,BOOL);来使子窗体失效
再用UpdateWindow (HWND)发送WM_PAINT
---华软网友回复---
WM_PAINT消息应该由系统生成并发送的,你不能随便发送。

你的代码中,
SendMessage(hwnd, WM_PAINT, 2, num);//在子窗口自己的WM_PAINT传送消息
 UpdateWindow(hwnd);
后面的UpdateWindow会让系统再生成一次WM_PAINT,其中的wParam和lParam是不确定的。

还有你的父窗口回调函数中:
case WM_PAINT:
 InvalidateRect(hwnd, &rect, TRUE);
这里有两个问题:一是不应在WM_PAINT下调用InvalidateRect;二是此处的rect未初始化,数值是不确定的。

==============

如果想在WM_PAINT下调用自己的数据,可以考虑使用全局变量,或是使用SetWindowLongPtr把指针传递过去,然后在WM_PAINT中GetWindowLongPtr读取。



---华软网友回复---
引用 10 楼 chehw_1 的回复:
WM_PAINT消息应该由系统生成并发送的,你不能随便发送。

你的代码中,
SendMessage(hwnd, WM_PAINT, 2, num);//在子窗口自己的WM_PAINT传送消息
 UpdateWindow(hwnd);
后面的UpdateWindow会让系统再生成一次WM_PAINT,其中的wParam和lParam是不确定的。

还有你的父窗口回调函数中:
case WM_PAINT:
 InvalidateRect(hwnd, &rect, TRUE);
这里有两个问题:一是不应在WM_PAINT下调用InvalidateRect;二是此处的rect未初始化,数值是不确定的。

==============

如果想在WM_PAINT下调用自己的数据,可以考虑使用全局变量,或是使用SetWindowLongPtr把指针传递过去,然后在WM_PAINT中GetWindowLongPtr读取。

那我应该怎么样修改呢,rect我已经初始化了。 UpdateWindow(hwnd);去掉了可是还是不行的。
你说的很对,我设了一个全局变量的数组0-9就可以传了,但是我就是不明白为什么这样不能传呢。
我感觉应该可以啊。
---华软网友回复---
引用 11 楼 ming1rui2 的回复:
那我应该怎么样修改呢,rect我已经初始化了。 UpdateWindow(hwnd);去掉了可是还是不行的。
你说的很对,我设了一个全局变量的数组0-9就可以传了,但是我就是不明白为什么这样不能传呢。
我感觉应该可以啊。


参考MSDN,不应由你的应用程序发送WM_PAINT:The WM_PAINT message is generated by the system and should not be sent by an application.

当消息队列中没有其他消息时,系统也会自动发送WM_PAINT,你直接发送WM_PAINT并传递参数的结果是难以确定的。

还有很多其他方法可以实现你想要的结果,比如使用双缓冲,创建一个兼容DC和位图,在上面直接绘制。需要显示时,InvalidRect对应的区域,父窗口在WM_PAINT中直接Bitblt这个memdc就行了。


---华软网友回复---
你也不要在窗口重绘消息里面Invalid,Update
这一切都应该在引发窗口重绘的其他消息,比如单击,比如定时器消息种处理
在窗口重绘消息中,Invalid,Update 
可能会引发无穷重绘,或者被忽略,总之很难正常工作。
---华软网友回复---
我很奇怪的是,WM_PAINT消息的WPARAM和LPARAM都是is not used,你觉得你发WM_PAINT消息传递参数合理吗?

case WM_PAINT:
 InvalidateRect(hwnd, &rect, TRUE);
 hdc = BeginPaint(hwnd, &ps);    
-------------------------------------------------------
paint消息里面调用InvalidateRect,调用这个函数系统会发一个WM_PAINT给目标窗口,这不是子子孙孙无穷尽了嘛!

LS都说了,通知窗口刷新,不要手动发送WM_PAINT消息,而是通过API让系统去发,比如希望立即刷新就调UpdateWindow,非立即刷新就调Invalidate,希望区域刷新就InvalidateRect      
华软声明:本内容来自网络,如有侵犯您版权请来信指出,本站立即删除。