第五章Windows Message Mapping Windows 消息映射(下)

原创 2004年12月31日 16:37:00
Scrolling Alternatives The CscrollView class supports a particular kind of scrolling that involves one big window and a small viewport. Each item is assigned a unique position in this big window. If, for example, you have 10,000 address lines to display, instead of having a window 10,000 lines long, you probably want a smaller window with scrolling logic that selects only as many lines as the screen can display. In that case, you should write your own scrolling view class derived from Cview. The OnInitialUpdate Function You’ll be seeing more of the OnInitialupdate function when you study the document-view architecture, starting in Chapter 15. The virtual OnInitialUpdate function is important here because it is the first function called by the framework after your view window is fully created. The framework calls OnInitialUpdate before it calls OnDraw for the first time, so OnInitialUpdate is the natural place for setting the logical size and mapping mode for a scrolling view. You set these parameters with a call to the CscrollView::SetScrollSizes function. Accepting Keyboard Input Keyboard input is really a two-step process. Windows sends WM_KEYDOWN and WM_KEYUP message, with virtual key codes, to a window, but before they get to the window they are translated. If an ANSI character is typed (resulting in a WM_KEYDOWN message), the translation function checks the keyboard shift status and then sends a WM_CHAR message with the proper code, either uppercase or lowercase. Cursor keys and function keys don’t have codes, so there’s no translation to do. The window gets only the WM_KEYDOWN and WM_KEYUP messages. You can use the Class View’s Properties window to map all these messages to your view. If you’re expecting characters, map WM_CHAR; if you’re expecting other keystrokes, map WM_KEYDOWN. The MFC library neatly supplies the character code or virtual key code as a handler function parameter. 选择滚动条 CscrollView类支持几中特殊的滚动条包括一个大窗口和一个小视口.每个成员在一个大窗口中分配一个位置.例如,你有10000行地址要显示,你大概想要个用滚动来选择跟屏幕大小一样多的行数的小窗口来代替一个有10000行的大窗口.在此例子中,你将要使用来自于Cview类来写你自己的滚动视图类. 光标键和和功能键是没有编码的,所以这里不需要转换工作.窗口仅获得WM_KEYDOWN和WM_KEYUP消息. OnInitialUpdate函数 从第15章开始,当你将学习文档-视图架构的时候,你将看到很多关于OnInitialUpdate函数.OnInitialUpdate是虚函数,它是很重要的,因为它是在你视图建立之后第一个被框架调用的函数.框架在调用OnInitialUpdate之前它将第一次调用OnDraw函数,所以OnInitialUpdate是最佳的设置逻辑大小和滚动视图映射模式的地点.你要设置这些参数可以调用CscrollView::SetScrollSizes函数. 接受键盘输入 键盘输入实际上是分俩步处理的.Windows发送WM_KEYDOWN和WM_KEYUP消息,使用的是虚拟键盘码,给窗口,但是在给窗口之前它们要进行转换.如果是ANSI类型字符(结果放在WM_KEYDOWN消息中),转换函数检查键盘的shift状态然后使用正确的编码发送WM_CHAR消息,任何的大小写. 光标键和和功能键是没有编码的,所以这里不需要转换工作.窗口仅获得WM_KEYDOWN和WM_KEYUP消息. 你可以使用属性类视图窗口的来映射所有的这些消息给你的视图.如果你需要字符,就映射WM_CHAR;如果你需要其他按键,映射WM_KEYDOWN.MFC完美的支持字符和虚拟键码就跟处理函数参数一样. The Ex05c Example: Scrolling The goal of Ex05c is to make a logical window 20 centimeters wide by 30 centimeters high. The program draws the same ellipse that it drew in the Ex05b project. You could edit the Ex05b source files to convert the Cview base class to a CscrollView base class, but it’s easier to start over with the MFC Application Wizard. The wizard generates the OnInitialUpdate override function for you. Here are the steps: 1. Run the MFC Application Wizard to create Ex05c. Use the wizard to generate an SDI program named Ex05c in the /vcppnet subdirectory. Set the Cex05cView base class to CscrollView, as shown here: 2. Add the m_rectEllipse and m_nColor data members in Ex05cView.h. Insert the following code using the Add Member Variable Wizard available from the Class View’s Properties window or by typing inside the Cex05cView class declaration: Private: CRect m_rectEllipse; Int m_nColor; These are the same data members that were added in the Ex05a and Ex05b projects. 3. Modify the MFC Application Wizard-generated OnInitialUpdate function.Edit OnInitialUpdate in Ex05cView.cpp as shown here: Void Cex05cView::OnInitialUpdate() { CscrollView::OnInitialUpdate(); Csize sizeTotal(20000,30000);//20 by 30 cm Csize sizePage(sizeTotal.cx /2,sizeTotal.cy /2); Csize sizeLine(sizeTotal.cx /50,sizeTotal.cy /50); SetScrollSizes(MM_HIMETRIC,sizeTotal,sizePage,sizeLine); } 4. Use the Class View’s Properties window to add a message handler for the WM_KEYDOWN message.The code wizards available from the Properties window generate the member function OnKeyDown along with the necessary message map entries and prototypes. Edit the code as follows: Void Cex05cView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch (nChar){ case VK_HOME: OnVSroll(SB_TOP,0,NULL); OnHSroll(SB_LEFT,0,NULL); Break; Case VK_END: OnVSroll(SB_BOTTOM,0,NULL); OnHSroll(SB_RIGHT,0,NULL); Break; Case VK_UP: OnVScroll(SB_LINEUP,0,NULL); Break; Case VK_DOWN: OnVScroll(SB_LINEDOWN,0,NULL); Break; Case VK_PRIOR: OnVScroll(SB_PAGEUP,0,NULL); Break; Case VK_NEXT: OnVScroll(SB_PAGEDOWN,0,NULL); Break; Case VK_LEFT: OnVHcroll(SB_LINELEFT,0,NULL); break; case VK_RIGHT: OnVHcroll(SB_LINERIGHT,0,NULL); Break; Default: Break; } } 5. Edit the constructor and the OnDraw function. Change the MFC Application Wizard-generated constructor and the OnDraw function in Ex05cView.cpp as follows: Cex05cView::Cex05cView():m_rectEllipse(0,0,4000,-4000) { m_nColor=GRAY_BRUSH; } void Cex05cView::OnDraw(CDC* pDC) { pDC ->SelectStockObject(m_nColor); pDC ->Ellipse(m_rectEllipse); } These functions are identical to those used in the Ex05a and Ex05b projects. 6. Map the WM_LBUTTONDOWN message and edit the handler. Make the following changes to the generated code: Void Cex05cView::OnLButtonDown(UINT nFlags, Cpoint point) { CClientDC dc(this); OnPrepareDC(&dc); CRect rectDevice=m_rectEllipse; dc.LPtoDP(rectDevice); if (rectDevice.PtInRect(point)){ if (m_nColor==GRAY_BRUSH){ m_nColor=WHITE_BRUSH; } else { m_nColor==GRAY_BRUSH); } InvalidateRect(rectDevice); } } This function is identical to the OnLButtonDown handler in the Ex05b project. It calls OnPrepareDC as before, but something is different. The Cex05bView class doesn’t have an overridden OnPrepareDC function, so the call goes to CscrollView::OnPrepareDC.That function sets the mapping mode based on the first parameter to SetScrollSizes, and it sets the window origin based on the current scroll position. Even if you scroll view were to user the MM_TEXT mapping mode, you’d still need the coordinate conversion logic to adjust for the origin offset. 7. Build and run the Ex05c program. Check to be sure that the mouse hit logic is working even if the circle is scrolled partially out of the window. Also check the keyboard logic. The output should look like this: 例子Ex05c:滚动 该例子的目的是创建一个20厘米x30厘米的窗口,并绘制跟EX05B项目一样的椭圆.你可以通过修改Ex05b的源文件Cview基类转换成CscrollView基类,但是你用MFC应用向导会更容易.向导为你产生OnInitialUpdate重载函数,下面是产生步骤: 1. 运行MFC应用程序向导建立Ex05c.使用向导在/vcppnet子目录下建立一个名为Ex05c的SDI程序.设置Cex05cView基类为CscrollView,如下图所示: 2. 增加m_rectEllipse和m_nColor变量到Ex05cView.h中.从类视图的属性窗口的增加数据变量向导插入以下代码或在Cex05cView类定义中键入代码: Private: CRect m_rectEllipse; Int m_nColor; 这些数据成员跟Ex05a和Ex05b项目中的一样. 3. 修改MFC应用程序向导产生的OnInitialUpdate函数.编辑Ex05cView.cpp中的OnInitialUpdate函数,如下所示: Void Cex05cView::OnInitialUpdate() { CscrollView::OnInitialUpdate(); Csize sizeTotal(20000,30000);//20 by 30 cm Csize sizePage(sizeTotal.cx /2,sizeTotal.cy /2); Csize sizeLine(sizeTotal.cx /50,sizeTotal.cy /50); SetScrollSizes(MM_HIMETRIC,sizeTotal,sizePage,sizeLine); } 4. 使用类视图的属性窗口为WM_KEYDOWN消息增加消息处理.使用来自于属性窗口的代码向导产生OnKeyDown函数和必须的消息映射入口和原形.编辑以下代码: Void Cex05cView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch (nChar){ case VK_HOME: OnVSroll(SB_TOP,0,NULL); OnHSroll(SB_LEFT,0,NULL); Break; Case VK_END: OnVSroll(SB_BOTTOM,0,NULL); OnHSroll(SB_RIGHT,0,NULL); Break; Case VK_UP: OnVScroll(SB_LINEUP,0,NULL); Break; Case VK_DOWN: OnVScroll(SB_LINEDOWN,0,NULL); Break; Case VK_PRIOR: OnVScroll(SB_PAGEUP,0,NULL); Break; Case VK_NEXT: OnVScroll(SB_PAGEDOWN,0,NULL); Break; Case VK_LEFT: OnVHcroll(SB_LINELEFT,0,NULL); break; case VK_RIGHT: OnVHcroll(SB_LINERIGHT,0,NULL); Break; Default: Break; } } 5. 修改构造器和OnDraw函数.用下列代码更改MFC应用程序向导的Ex05cView.CPP文件中产生的构造器和OnDraw函数 Cex05cView::Cex05cView():m_rectEllipse(0,0,4000,-4000) { m_nColor=GRAY_BRUSH; } void Cex05cView::OnDraw(CDC* pDC) { pDC ->SelectStockObject(m_nColor); pDC ->Ellipse(m_rectEllipse); } 这些函数在Ex05a和Ex05b中同样要使用. 6. 映射WM_LBUTTONDOWN消息和编辑处理.安排下列产生改变的代码: Void Cex05cView::OnLButtonDown(UINT nFlags, Cpoint point) { CClientDC dc(this); OnPrepareDC(&dc); CRect rectDevice=m_rectEllipse; dc.LPtoDP(rectDevice); if (rectDevice.PtInRect(point)){ if (m_nColor==GRAY_BRUSH){ m_nColor=WHITE_BRUSH; } else { m_nColor==GRAY_BRUSH); } InvalidateRect(rectDevice); } } 这个OnLButtonDown是同样在Ex05b项目中处理的.它是在调用OnPrepareDC之前调用的,但是有时候又不同.Cex05bView类不可以重载OnPrepareDC函数,所以要调用CscrollView::OnPrepareDC.SetScrollSize函数的第一个参数是设置映射模式的,它同时也根据当前的滚动坐标来设置窗口的原点.即使你的滚动视图使用MM_TEXT映射模式,你仍旧需要转换逻辑坐标并调整原点偏移. 7. 生成和运行Ex05c程序. 检查当圆有部分在滚动到窗口的外面而鼠标点击仍然有效同样也要用键盘测试.输出的程序如下图所示: Using Other Windows Messages The MFC library directly supports hundreds of Windows message-handling functions. In addition, you can define your own messages. You’ll see plenty of message-handling examples in later chapters, including handlers for menu items, child window controls, and so forth. In the meantime, five special Windows messages deserve special attention: WM_CREATE, WM_CLOSE, WM_QUERYENDSESSION, WM_DESTROY, and WM_NCDESTROY. The WM_CREATE Message This is the first message that Windows sends to a view. It is sent when the window’s Create function is called by the framework. At that time, the window creation is not finished, so the window is not visible. Therefore, your OnCrecte handler cannot call Windows functions that depend on the window being completely alive. You can call such functions in an overridden OnInitialUpdate function, but you must be aware that in an SDI application OnInitialUpdate can be called more than once in a view’s lifetime. 使用其他Windows消息 MFC库直接支持数百种Windows消息处理函数.另外,你能第一属于你自己的消息.你将在后面的章节中看到大量的消息处理的例子,包括菜单处理,子窗口控件,等等.在此其间,有五个特别的Windows消息应该特别注意: WM_CREATE, WM_CLOSE, WM_QUERYENDSESSION, WM_DESTROY, 和WM_NCDESTROY. WM_CREATE消息 这个消息是Windows首先发送个视图的消息.当框架调用窗口的Create函数时发送它.在那时窗口没有被建立起来,是不可见的.因此,你的OnCreate函数里不能调用Windows函数它需要窗口完全的活动才可以.你可以在重载函数OnInitialUpdate中调用这样的函数,但是你必须明白在一个SDI应用程序的一个视图生存期内OnInitialUpdate将不止一次的被调用. The WM_CLOSE Message Windows sends the WM_CLOSE message when the user closes a window from the system menu and when a parent window is closed. If you implement the OnClose message map function in your derived view class, you can control the closing process. If, for example, you need to prompt the user to save changes to a file, you can do it in OnClose. Only after you’ve determined that it is safe to close the window should you call the base class OnClose function, which will continue the close process. The view object and the corresponding window will both still be active. Note When you’re using the full application framework, you probably won’t use the WM_CLOSE message handler. You can override the Cdocument::SaveModified virtual function instead, as part of the application framework’s highly structured program exit procedure. The WM_QUERYENDSESSION Message Windows sends the WM_QUERYENDSESSION message to all running application when the user exits Windows. The OnQueryEndSession message map function handles it. If you write a handler for WM_CLOSE, you should write one for WM_QUERYENDSESSION, too. The WM_DESTROY Message Windows sends the WM_DESTROY message after the WM_CLOSE message, and the OnDestroy message map function handles it. When your program receives this message, it should assume that the view window is no longer visible on the screen but that it is still active and its child windows are still active. You use this message handler to do cleanup that depends on the existence of the underlying window. Be sure to call the base class OnDestroy function. You cannot “abort” the window destruction process in your view’s OnDestroy function. OnClose is the place to do that. The WM_NCDESTROY Message This is the last message that Windows sends when the window is being destroyed. All child windows have already been destroyed. You can do final processing in OnNcDestroy that doesn’t depend on a window being active. Be sure to call the base class OnNcDestroy function. Note Do not try to destroy a dynamically allocated window object in OnNcDestroy. That job is reserved for a special CWnd virtual function, PostNcDestroy, that the base class OnNcDestroy calls. MFC Technical Note #17 in the online documentation offers hints about when it’s appropriate to destroy a window object. WM_CLOSE消息 当用户从系统菜单关闭窗口并且父窗口是关闭的Windows就发送WM_CLOSE消息.如果你在源视图类中执行OnClose消息函数,你可以控制关闭的进程.例如,你需要提示用户保存改变的文件,你就要在OnClose中做.只有在你认为可以安全的关闭窗口之后,你才可以调用基类的OnClose函数,那将继续关闭进程.视图对象和相应的窗口仍旧是活动的. 注意:当你完全的使用应用程序框架的时候,你大概不会使用WM_CLOSE消息处理了.在应 用程序框架高度结构化的程序中你可以重载Cdoument::SaveModified虚函数来代替它. WM_QUERYENDSESSION消息 当用户退出Windows时发送WM_QUERYENDSESSION消息给正在运行的应用程序.OnQuerEndSession消息映射函数专门处理该消息.如果你要处理WM_CLOSE消息,你也要写一个处理WM_QUERENDSESSION的消息. WM_DESTROY消息 当在WM_CLOSE消息之后Windows就发送WM_DESTROY消息,并且在OnDestroy消息函数中处理.当你的程序接收到这个消息,它将使视图窗口在屏幕上不再是显示的但是窗口和它的子窗口仍旧是存在的.你使用这个消息处理来清除依靠在下面的窗口.在调用基类的OnDestroy函数中确认.在你的视图的OnDestroy函数中你不能”异常中断”窗口的销毁过程.OnClose中可以处理. WM_NCDESTROY消息 当窗口被彻底销毁之后Windows发送的最后的一个消息.所有的子窗口已经被销毁了.你能做的就是在不依赖活动窗口的OnNcDestroy中来处理最后结局. 注意:不可以在OnNcDestroy中销毁动态分配的窗口对象.这个工作留到特定的CWnd虚函数PostNcDestroy中去做,它在基类的OnNcDestroy中调用.MFC技术在线文档的17页提示它是最适合销毁窗口对象的.

第五章Windows Message Mapping Windows 消息映射(上)

第五章 Windows Message Mapping Windows 消息映射In Chapter 3, you saw how the MFC library application framew...
  • GodSun_
  • GodSun_
  • 2004年12月24日 16:02
  • 2053

Windows-消息映射机制原理和简单的绘图技术

Windows-消息映射机制原理和简单的绘图技术 1.MFC消息映射机制 众所周知,Windows程序是基于消息编程的,但是在MFC中已经为我们封装好了这个框架的消息机制,我们需要了解它的实现原理...
  • qq_22075977
  • qq_22075977
  • 2016年04月24日 16:21
  • 2544

windows编程(消息机制、消息队列、消息映射、线程同步)笔记windows编程(消息机制、消息队列、消息映射、线程同步)笔记

PostMessage和SendMessage的区别 BOOL   PostMessage(      HWND   hWnd,             //   handle   of   de...
  • u010669196
  • u010669196
  • 2016年08月20日 14:19
  • 387

Message Mapping(消息映射)(转)

 来源:http://www.cppblog.com/nacci/archive/2006/05/18/7363.htmlMFC中的消息循环呢?我们熟悉的switch……case……到哪里去了?在MF...
  • shaozhongwu505
  • shaozhongwu505
  • 2010年09月08日 18:42
  • 179

深入浅出MFC Message Mapping 消息映射

stdafx // stdafx.h : 标准系统包含文件的包含文件, // 或是经常使用但不常更改的 // 特定于项目的包含文件 // #pragma once #include "targe...
  • u012513234
  • u012513234
  • 2014年12月31日 11:01
  • 261

Windows下使用GMT(Generic Mapping Tools)全过程

注:本文参考了 《Windows下使用GMT的正确姿势》 一文,网址为:http://seisman.info/how-to-use-gmt-under-windows.html首先下载四个必备...
  • IvanLJF
  • IvanLJF
  • 2016年12月25日 20:58
  • 663

Windows Message Queue(优先级队列+map)

Windows Message Queue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/O...
  • cs_zlg
  • cs_zlg
  • 2012年11月18日 11:50
  • 3042

MFC中的消息映射(Message Mapping)

Windows靠消息的流动来维持运行。MFC里有消息映射表,这个消息映射表,把消息和处理消息的程序关联起来。       当我们的类库建立成功后,如果其中与消息相关的类(姑且叫做“消息标志类”,在MF...
  • sanqima
  • sanqima
  • 2015年01月01日 22:21
  • 1267

Windows Message 消息队列,消息循环,Post消息,Send消息

MessageQueue The system does not automatically create a messagequeue for each thread. Instead, the ...
  • yyw610879290
  • yyw610879290
  • 2014年09月30日 19:15
  • 1080

hdu1509(Windows Message Queue) 优先队列

1、PriorityQueue类与普通队列最主要的区别就是多了个比较器。一般情况下,都是自己通过实现Comparator接口写一个比较器,在new 优先队列时将这个比较器丢进去就ok了, 构造方法中就...
  • u011479875
  • u011479875
  • 2015年08月15日 00:56
  • 1157
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章: 第五章Windows Message Mapping Windows 消息映射(下)
举报原因:
原因补充:

(最多只允许输入30个字)