深入浅出MFC学习笔记(1)

1.
 LRESULT CALLBACK WndProc(HWND hWnd,     UINT message,
        WPARAM wParam, LPARAM lParam)
 {
  ...
 }
 参数:
 message 相当于WM_COMMAND,WM_DESTROY等
 wParam:
 如:
 int wmId, wmEvent;
 wmId    = LOWORD(wParam);//取低位 IDM_EXIT,IDM_ABOUT
 wmEvent = HIWORD(wParam);//取高位

 LPARAM   A 32-bit value passed as a parameter to a window procedure or callback function.
 WPARAM   A value passed as a parameter to a window procedure or callback function: 16 bits on Windows versions 3.0 and 3.1; 32 bits on Win32.

   while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);//转换键盘消息
    DispatchMessage(&msg);//分派消息
   }
---------------------------------------
2.
 WM_CREATE消息 由WinMain(...)中的CreateWindow(...)产生(产生窗口后发生),由WndProc(...)接收处理
 关闭窗口时产生消息WM_CLOSE,WndProc(...)接收,相应其中的case WM_DESTROY:,触发函数PostQuitMessage(0);,PostQuitMessage(0)产生消息WM_QUIT消息,最终结束窗口进程。
------------------------------------------
3.WM_CREATE WM_COMMAND WM_LBUTTONDOWN WM_PAINT WM_CLOSE WM_DESTROY
 WM_PAINT
 This message is sent by an application when Windows or another application makes a request to paint a portion of an application's window. The message is sent when the UpdateWindow function is called, or by the DispatchMessage function when the application obtains a WM_PAINT message by using the GetMessage or PeekMessage function.
 WM_CREATE
 The WM_CREATE message is sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. (The message is sent before the function returns.) The window procedure of the new window receives this message after the window is created, but before the window becomes visible.
 WM_COMMAND
 The WM_COMMAND message is sent when the user selects a command item from a menu, when a control sends a notification message to its parent window, or when an accelerator keystroke is translated.
 WM_LBUTTONDOWN
 The WM_LBUTTONDOWN message is posted when the user presses the left mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.
 WM_CLOSE
 The WM_CLOSE message is sent as a signal that a window or an application should terminate.
 WM_DESTROY
 The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window procedure of the window being destroyed after the window is removed from the screen.

 This message is sent first to the window being destroyed and then to the child windows (if any) as they are destroyed. During the processing of the message, it can be assumed that all child windows still exist.
-----------------------------------------------
4.
  用户可以在自己的程序中使用自定义消息,并利用自定义消息传递数据。

  在理解消息之后,我们看消息循环。简而言之,消息循环就是一个循环体,在这个循环体中,程序利用

 GetMessage 函数不停地从消息队列中获得消息,然后利用 DispatchMessage 函数将消息发送到指定的窗口,也就是

 调用指定窗口的窗口过程,并传递消息及其参数。典型的消息循环如下所示:

 while (GetMessage (&Msg, hMainWnd)) {
     TranslateMessage (&Msg);
     DispatchMessage (&Msg);
 }

  如上所示,GetMessage 函数从 hMainWnd 窗口所属的消息队列当中获得消息,然后调用 TranslateMessage 函

 数将 MSG_KEYDOWN 和 MSG_KEYUP 消息翻译成 MSG_CHAR 消息,最后调用 DispatchMessage 函数将消息发送到指定

 的窗口。

  在 MiniGUI-Threads 版本中,每个建立有窗口的 GUI 线

 LRESULT CALLBACK WndProc(HWND hWnd,     UINT message,
        WPARAM wParam, LPARAM lParam)
 {
  ...
 }
 message 相当于WM_COMMAND,WM_DESTROY等
 wParam:
 int wmId, wmEvent;
 wmId    = LOWORD(wParam);//IDM_EXIT,IDM_ABOUT
 wmEvent = HIWORD(wParam);

 LPARAM   A 32-bit value passed as a parameter to a window procedure or callback function.
 WPARAM   A value passed as a parameter to a window procedure or callback function: 16 bits on Windows versions 3.0 and 3.1; 32 bits on Win32.

   while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);//转换键盘消息
    DispatchMessage(&msg);//分派消息
   }
-------------------------------------------
Unhandled exception的大概意思是“未处理的例外情况,异常”(
0xC00000005你应该猜测到是内存地址,猜不到也不重要
值是0x00000000,这是一个空指针
vc++中指针的初始值为何是0xcccccccc
窗口的客户区(例如我们的窗口客户区加一个背景图片),用OnDraw维护视图的客户区
窗口的客户区,视图的客户区
什么是无效区域?
 自己到网上搜索或者看相关资料。我这里给出一个特殊的解释:以最小化后还原为例,假设只有一个程序在

运行,窗口最小化时显示计算机桌面,并不妨假设桌面是蓝色的背景,当窗口还原时,窗口所占的这一块区域该显示

些什么东西呢?操作系统并不知道,因此,就形成一块无效区域。

要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其实DC是一个数据结构,它包含输出设备(不单指你17寸

的纯屏显示器,还包括打印机之类的输出设备)的绘图属性的描述。

窗口的无效区域演示程序
--------------------------------------------------------------------------------

窗口的无效区域
作者: 姜学哲([email protected])
教材: Windows程序设计(第五版)北京大学出版社
 [美]Charles Petzold 著
 北京博彦科技发展有限公司 译  ¥:160
环境: windows2000 Pro sp4 + Internet Explorer 6.0 sp1 + Visual C++ 6.0
图们江计算机程序编制小组(http://chulsoft.xiloo.com)版权所有,转载请说明出处
----------------------------------------------------------------
当窗口客户区的一部分或者全部变为“无效”,以致于必须刷新时,系统将给窗口过程发送WM_PAINT消息。
收到WM_PAINT消息后必须绘制客户区。在很多时候我们只需要更新很小的一个区域就可以了。当对话框覆盖了部分客

户区的时候情况就是如此。关闭对话框后,需要重画的只是先前被对话框遮住的矩形区域。这个区域就是“无效区域

”或“更新区域”。
为了让你更好地理解什么是无效区域,我写了一个程序。该程序的功能是获取最新的无效区域的坐标。运行该程序后

你可以用另一个较小的窗口遮住该窗口的全部或一小部分。然后再移走。又或者改变窗口的尺寸。客户区出现的四个

数就是最新的无效区域坐标。以下是WndProc部分的代码:
 ===========================================================
 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
   static int  cxChar, cxCaps, cyChar ;
   HDC         hdc ;
 static int  t[4] ;
 int   i ;
   PAINTSTRUCT ps ;
   TCHAR       szBuffer [10] ;
   switch (message)
   {
   case WM_PAINT :
     hdc = BeginPaint (hwnd, &ps) ;
   
  t[0] = ps.rcPaint.left ;
  t[1] = ps.rcPaint.top ;
  t[2] = ps.rcPaint.bottom ;
  t[3] = ps.rcPaint.right ;
  for (i = 0 ; i < 4 ; i++)
  {
   TextOut (hdc, t[0], t[1] + i * 20, szBuffer,
       wsprintf (szBuffer, TEXT ("%5d"), t[i])) ;
  }
  EndPaint (hwnd, &ps) ;
     return 0 ;
   case WM_DESTROY :
     PostQuitMessage (0) ;
     return 0 ;
   }
   return DefWindowProc (hwnd, message, wParam, lParam) ;
 }
 ===========================================================
 BeginPaint函数除了获取设备描述表句柄之外,还从系统中获取相关信息填充她的第二个参数,也就是PAINTSTRUCT

 结构。该结构包含了一个rcPaint结构。而rcPaint结构就是最新无效区域的坐标。
 确定无效区域的时候不需要程序员干预,是由系统自动完成的。是暗箱操作。我们只需要用BeginPaint函数获取就可

 以了。我对微软的这种隐藏细节的做法很不满。也仅限于不满。人在屋檐下,不得不低头。


=======================================================
雷神推荐大家可以看看侯大师的《深入浅出MFC》,
还有John E.Swanke著的《Visual C++MFC 编程实例》,
因为雷神从这两本书中获得了大量的“营养”。

----------------------------
深度探索C++对象模型

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

OnPaint函数和OnDraw函数区别
2006-09-17 17:46
OnPaint函数
这是WM_PAINT消息得消息映射函数,写在这个函数中得绘图代码,只能显示再屏幕上,而不能输出到打印机上,关于

打印机得代码要另外编写
OnDraw函数
能保证屏幕得完整性,可在屏幕和打印机上显示
在视图中实现绘图得代码应该写在OnDraw函数中
 
OnDraw和OnPaint函数的区别?
OnPaint响应WM_PAINT消息,在CView中,它接着调用OnDraw  
CPaintDC响应WM_PAINT消息,自动完成绘制  
ClientDC实时绘制
一般情况下,你看不到两个函数有什么太大区别,因为一般情况下,它们的任务都是重画窗口。  
  在CView及其子类中,OnDraw是由OnPaint调用的,也就是你可以像在窗口类中一样,调用Invalidate函数导致,

OnDraw的调用(当然,Invalidate是先导致OnPaint的调用)。  
  要说OnDraw和OnPaint有什么区别,那就是它除了可以把画画到屏幕外,还可以把它画到其它任何标准输出设备,

如打印机  

1楼  lxgcn   (浪刀)   回复于 2001-03-26 13:58:00  得分 7
onpait   响应WM_PAINT消息,在CView中,它接着调用OnDraw  
  CPaintDC响应wm_paint消息,自动完成绘制  
  ClientDC实时绘制

Top
2楼  lgs   (老臭虫)   回复于 2001-03-26 14:14:00  得分 3
建议你看看MFC源代码。

Top
3楼  happylaodu   (青菜豆腐)   回复于 2001-03-26 14:44:00  得分 10
一般情况下,你看不到两个函数有什么太大区别,因为一般情况下,它们的任务都是重画窗口。  
  在CView及其子类中,恰如浪刀所言,OnDraw是由OnPaint调用的,也就是你可以像在窗口类中一样,调用

Invalidate函数导致,OnDraw的调用(当然,Invalidate是先导致OnPaint的调用)。  
  要说OnDraw和OnPaint有什么区别,那就是它除了可以把画画到屏幕外,还可以把它画到其它任何标准输出设备,

如打印机  

关于vc的onpaint()和ondraw()函数
aifeihuang (波波)     2001-01-09 20:20:00 在 VC/MFC / 基础类 提问
      不知道那位大虾能给我说一下vc的CDialog   的   OnPaint函数和CView   的   OnDraw()的区别吗?这两个

函数是不是都是message   WM_PAINT的处理函数?  
 

问题点数:20、回复次数:5

1楼  sun2000   (非常可乐)   回复于 2001-01-09 20:29:00  得分 5
一般来说只有View下才有这种情况,  
  OnPaint只对屏幕输出有效,OnPrint只对打印机输出有效,  
  而OnDraw对两者都有效,一般OnPaint和OnPrint优先权高于OnDraw,  
  也就是说有OnPaint消息处理则OnDraw对屏幕输出无效,  
  同理有OnPrint消息处理则OnDraw对打印机的输出无效。

Top
2楼  YuHao   ()   回复于 2001-01-09 20:29:00  得分 5
事实上CView::OnPaint代码是这样的:  
  void   CView::OnPaint()  
  {  
  CPaintDC   dc(this);  
  OnPrepareDC(&dc);  
  OnDraw(&dc);  
  }  
  OnPrepareDC会为你完成一些如坐标映射等方面的工作,而CDialog没有这方面的内容.另一方面,在CView打印或者打

印预览时也会调用OnDraw,只不过这时dc.IsPrinting是True,如果打印的内容和屏幕上完全一样的话,这样就很方便了

.

Top
3楼  MildSeven   (方言)   回复于 2001-01-09 20:42:00  得分 5
附加:  
  (1)   OnDraw()在初始化时触发,它用来处理第一次绘制(DC);  
  (2)   OnPaint()在每次视图被激活时触发,重新绘制(刷新)。  
 

Top
4楼  wolf_   (地主)   回复于 2001-01-09 20:47:00  得分 5
OnDraw()不是message   WM_PAINT的处理函数,OnPaint()才是。  
 

OnDraw()和OnPaint()有什么区别呢?
我们先要明确CView类派生自CWnd类。而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息。OnDraw()是CVIEW

的成员函数,并且没有响应消息的功能。这就是为什么你用VC成的程序代码时,在视图类只有OnDraw没有OnPaint的

原因。
当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows   将   WM_PAINT   消息发送给它。该视图的

  OnPaint   处理函数通过创建   CPaintDC   类的DC对象来响应该消息并调用视图的   OnDraw   成员函数。通常

我们不必编写重写的   OnPaint   处理成员函数。
我们一般用OnPaint维护窗口的客户区(例如我们的窗口客户区加一个背景图片),用OnDraw维护视图的客户区(例

如我们通过鼠标在视图中画图)。
10:39 添加评论 阅读评论 (4) 固定链接 引用通告 (0) 记录它
固定链接http://zhangyingchao2008.spaces.live.com/blog/cns!7b5e1b2c48fc90ff!126.entry
评论Luke Luke
hehe,你理解的不对,onDraw onPaint都会响应wm_paint的,他们的区别只是ondraw的图形不仅输出到屏幕上而且输

出到打印机中,onpaint只是输出到屏幕上,看看onpaint()的定义就知道它其实是每次必须调用ondraw的
5月25日 11:06
(http://spaces.msn.com/LukeKevees/)


OnDraw()和OnPaint()的区别

[引用 2006-08-22 15:36:55 ] 发表者: zwigsnrr06   

原作者姓名 雷神
文章原始出处 http://www.ai361.com
介绍
我在视图画的图象或者文字,当窗口改变后为什么不见了?
OnDraw()和OnPaint()两个都是解决上面的问题,有什么不同?


读者评分 20 评分次数 5

正文
OnDraw()和OnPaint()兄弟

经常有朋友问雷神这样的问题:
我在视图画的图象或者文字,当窗口改变后为什么不见了?
OnDraw()和OnPaint()两个都是解决上面的问题,有什么不同?

雷神在这里一并解答一下吧。
OnDraw()和OnPaint()好象兄弟俩,因为它们的工作类似。

至于不见了的问题简单,因为当你的窗口改变后,会产生无效区域,这个无效的区域需要重画。一般Windows回发送

两个消息WM_PAINT(通知客户区有变化)和WM_NCPAINT(通知非客户区有变化)。非客户区的重画系统自己搞定了,

而客户区的重画需要我们自己来完成。这就需要OnDraw()或OnPaint()来重画窗口。

OnDraw()和OnPaint()有什么区别呢?
首先:
我们先要明确CView类派生自CWnd类。而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息。OnDraw()是CVIEW

的成员函数,并且没有响应消息的功能。这就是为什么你用VC成的程序代码时,在视图类只有OnDraw没有OnPaint的

原因。

其次:
我们在第《每天跟我学MFC》3的开始部分已经说到了。要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其

实DC是一个数据结构,它包含输出设备(不单指你17寸的纯屏显示器,还包括打印机之类的输出设备)的绘图属性的

描述。MFC提供了CPaintDC类和CWindwoDC类来实时的响应,而CPaintDC支持重画。

当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows 将 WM_PAINT 消息发送给它。该视图的

OnPaint 处理函数通过创建 CPaintDC 类的DC对象来响应该消息并调用视图的 OnDraw 成员函数。通常我们不必编写

重写的 OnPaint 处理成员函数。

///CView默认的标准的重画函数
void CView::OnPaint()
{
    CPaintDC dc(this);
    OnPreparDC(&dc);
    OnDraw(&dc); //调用了OnDraw
}

既然OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。下面是一个典型的程序

///视图中的绘图代码首先检索指向文档的指针,然后通过DC进行绘图调用。
void CMyView::OnDraw( CDC* pDC )
{
    CMyDoc* pDoc = GetDocument();
    CString s = pDoc->GetData();   // Returns a CString
    CRect rect;

    GetClientRect( &rect );
    pDC->SetTextAlign( TA_BASELINE | TA_CENTER );
    pDC->TextOut( rect.right / 2, rect.bottom / 2,
                  s, s.GetLength() );
}

最后:
现在大家明白这哥俩之间的关系了吧。因此我们一般用OnPaint维护窗口的客户区(例如我们的窗口客户区加一个背

景图片),用OnDraw维护视图的客户区(例如我们通过鼠标在视图中画图)。当然你也可以不按照上面规律来,只要

达到目的并且没有问题,怎么干都成。

补充:
我们还可以利用Invalidate(),ValidateRgn(),ValidateRect()函数强制的重画窗口,具体的请参考MSDN吧。

 

 

 

 

 

你可能感兴趣的:(工作随笔与感悟,深入浅出MFC学习笔记,我的VC++生活,学习笔记)