第五章消息映射
遇到的问题:
一、映射模式。
坐标使用的经验规则:
1、 可以认为CDC的所有成员函数都以逻辑坐标作为其参数。
2、 可以认为CWnd的成员函数都以设备坐标作为其参数。
3、 所有点中测试(hit-test)操作都应该考虑设备坐标。区域的定义应采用设备坐标。某些像CRect::PtInRect之类的函数只有在采用设备坐标参数时才会保证有正确的结果。
4、 将一些长期使用的值用逻辑坐标或物理坐标来保存。如果用设备坐标来保存某点得坐标的话,那么只要用户对窗口进行一下滚动,该点得坐标就不再有效了。
SetWindowOrg(x,y):把设备坐标的原点映射到逻辑坐标的(x, y)处。如:
dc.SetWindowOrg(20, 20); //将(20,20)作为设备环境的原点。
GDI绘图使用的是逻辑坐标。但是,从windows的鼠标消息所获得的鼠标光标的坐标值(如:OnLButtonDown的point参数)却是设备坐标。而且许多其他的MFC库函数,尤其是类CRect的成员函数,则只能在设备坐标下才能正确工作。
CRect函数总是假定右大于左且底大于顶,如果出现(0,0,1000,-1000)等情况时,有些函数就无法处理,如CRect::PtInRect函数就不行。需先调用CRect::NormallizeRect,这样就能将矩形的数据成员改变为(0,-1000,1000,0)。
框架在第一次调用OnDraw前会调用OnInitialUpdate,因此OnInitialUpdate是设置滚动视图的逻辑尺寸和映射模式最合适的地方。
二、窗口重绘问题,打算用GetUpdateRect();函数获得无效区域,却达不到想要的效果。
GetUpdateRect()函数可能需要你提供一个无效区域,返回包含此无效区域的最小矩形。待验证,有高手请留言。。。
知识点:
CEx07cDialog(CView *pView); //无模式窗口构造函数
CEx07cDialog(CWnd* pParent = NULL); //模式窗口构造函数
如果用CView类或其派生类作为参数来调用构造函数的话,编译器就会自动选择调用无模式构造函数;但如果用CWnd或其派生类作为参数来调用构造函数的话,编译器就会自动产生对模式构造函数的调用。
对于无模式对话框,一定不要调用CDialog::OnOK()和CDialog::OnCancel(),必须在派生类中改写这些虚函数;否则,当使用Esc或回车时,就会激发对相应基类函数的调用,进而导致调用window的EndDialog函数,而此函数只适合模式对话框。无模式对话框必须调用DestroyWindow函数。
除了主框架之外,对于其他几乎所有的窗口类型,DestroyWindow函数都不会将C++对象销毁掉,正好符合我们要在析构中销毁。