重温MFC.

    使用MFC已经足足有五年的时间了, 时间不短了, 应该算是一个老手了,但是每每提及MFC的时候, 虽然都会得到别人的一些小小的恭维,但其实自己都不是那么的胸有成竹, 总是有一丝丝的恐惧, 因为我知道,在这里,我有一些软胁. 有一些不把自由把握的东西. 对于一个自己不能完全把握的事情, 理所当然的就没有信心. 我属于比较上进的一类人, 一直以来都会很努力的学习, 但是因为项目经验太少, 太多的知识都是来自书本, 没有经过实践锻炼的知识都是不牢固的知识, 过阵子都忘了.  原来看到过一些前辈说编程一定要多动手,多实践, 但我一直没把这个当回事,甚至于觉得动手写简直都是浪费时间, 现在终于有些明白了, 不自己写一遍, 记忆不深刻, 不管当时理解的多么的透彻, 过后都会和没看过一模一样.所以以后要多多动手.

    进步就是不断的克服自己的缺点, 弥补自己的弱项. 在MFC中,我的弱项,让我恐惧的让我没信心的是什么? 这个十一长假的首要任务就是找出它们,解决掉它们.

 

1 单文档和多文档工程.

   一直以来都是做的工程都是对话框架工程.从来没有做过一个单文档或多文档的工程. 其实不懂单文档就是不懂doc/frame/view结构, 这个是MFC的灵魂.

   一直以来总是觉得view是个特别抽象的东西, 没有办法从根本上去理解它. 但是有的时候,如果你不能理解的话, 最起码要记住. 当你以后用的多了,时间长了,慢慢就会理解了.

   其实view和frame一样,都是继承自cwnd, 都是一种窗口,只是这个名字起的容易让人误解.    就好像不同职业的人有不同的名字一样, 比如一类人叫工程师, 一类人叫驾驶员, 都是人, 但是根据分工不同起了不同名字. frame view 都是wnd, 只是因为结构和分工不同, 所以给它们起了一个不同的名字.

   单文档程序, 包含这样几个类, class CMainFrame : public CFrameWnd, CMainFrame, 主窗口. 负责管理工具栏, 状态栏等. 它内嵌一个class CHgView : public CScrollView,它负责显示及接受用户输入. class CHgDoc : public CDocument负责文档读写.

   多文档程序,包含class CMainFrame : public CMDIFrameWnd, class CChildFrame : public CMDIChildWnd, class CScribbleView : public CView, class CScribbleDoc : public CDocument.

   要记住这几个类, CWnd, CFrameWnd, CMDIFrameWnd, CMDIChildWnd. 它们都是MFC标准类.

   根据名字可以知道, CFrameWnd 是一种专门做为frame的wnd, 所以单文档程序的外框是对应的类就是CFrameWnd.

   CMDIFrameWnd 是多文档程序的主框架对应的类. CMDIChildWnd是子框架对应的类.

   frame和button一样理解就好多了.要生成一个按钮, 需要生成一个CButton类的对象.要生成一个程序的外框,需要生成一个CFrameWnd对象.

  

BOOL CScribbleApp::InitInstance()

{

     // create main MDI Frame window
    CMainFrame* pMainFrame = new CMainFrame;
    if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
     return FALSE;
    m_pMainWnd = pMainFrame;

 

    // The main window has been initialized, so show and update it.
    pMainFrame->ShowWindow(m_nCmdShow);
    pMainFrame->UpdateWindow();

}

 

为什么这么简单的事情五年了才真正的理解? 因为从来没有认真的考虑过.

  

  

 

2 serialize()函数文件读写.

3 滚动窗口, 拆分窗口

4 工具栏. 

 

第五章: 浅出MFC 程序设计.

1 AFXRES.H.

   mfc程序的RC文件必须载入此文件. MFC对于标准资源(例如File, Edit等菜单项目)的ID都有默认值.定义于此文件中, 例如:

   #define ID_FILE_NEW 0XE100

 

2 多文档. 分割窗口,滚动条. 标准动作的再处理.

3 如果在AppWizard 中没有选择支持Activex, 后来就不能使用Activex了吗?

4 为什么感到迷惑?因为你从来都不曾动手去做. 只是看啊看...而且不求甚解.不仔细,不认真,稀里糊涂的的看.

   看到CFrameWnd   CMainFrame CView CMDIFrameWnd CMDIChildWnd 这些东西就害怕. 因为你没有真正去搞清楚它们每一个空间是啥? 一些是MFC标准类,一些是你从标准类中继承下来的, just remember them!!

 

5  

CMultiDocTemplate* pDocTemplate;
 pDocTemplate = new CMultiDocTemplate(
  IDR_SCRIBTYPE,
  RUNTIME_CLASS(CScribbleDoc),
  RUNTIME_CLASS(CChildFrame), // custom MDI child frame
  RUNTIME_CLASS(CScribbleView));
 AddDocTemplate(pDocTemplate);

 

这段代码的作用是绑定! 你的CScriibleView 中有一个这样的函数:

inline CScribbleDoc* CScribbleView::GetDocument()
   { return (CScribbleDoc*)m_pDocument; }

 

假如你的工程中有十个view类, 十个doc类. 在程序起来后会有十个view对象, 十个doc对象. 那么当你调用CScribbleView的GetDocument()时, 程序怎么知道把哪个doc对象给你? 答案就是通过绑定!

 

6 工具栏

 if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
  | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
  !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
 {
  TRACE0("Failed to create toolbar/n");
  return -1;      // fail to create
 }

 

我们在MainFrame里创建一个工具栏(CreateEx), 然后载入一个指定的工具栏图标(LoadToolBar函数指定IDR_MAINFRAME).

实际上一个ToolBar是一个bmp图片. 存放在工程中的res文件夹中. 在vc的资源编辑器中这个bmp会分成为很多个小图标.可以一个个编辑.

 

这些分开的小图标有自己的ID吗.?它们是怎么知道我点击的哪个?

在rc中有描述.

我随便载入一个BMP可以吗?

在工具栏上增加一项,如何为它添加行为?

在.rc文件中会有这样的描述:

IDR_MAINFRAME           BITMAP  MOVEABLE PURE   "res//Toolbar.bmp"

/
//
// Toolbar
//

IDR_MAINFRAME TOOLBAR DISCARDABLE  16, 15
BEGIN
    BUTTON      ID_FILE_NEW
    BUTTON      ID_FILE_OPEN
    BUTTON      ID_FILE_SAVE
    SEPARATOR
    BUTTON      ID_EDIT_CUT
    BUTTON      ID_EDIT_COPY
    BUTTON      ID_EDIT_PASTE
    SEPARATOR
    BUTTON      ID_FILE_PRINT
    SEPARATOR
    BUTTON      ID_APP_ABOUT
    BUTTON      ID_BUTTON32771
END

其中IDR_MAINFRAME是toolbar的ID.

我们在CScribbleApp中增加一个对于ID_BUTTON32771的处理函数即可.

 

 

怎么操作图像中的每个小图像?

loadbitmap?

 

 

文档读写?

 

消息路径, frame/view

 

单文档和多文档的区别:

单文档有一个Frame类  class CMainFrame : public CFrameWnd

多文档有两个Frame类  主Frame :  class CMainFrame : public CMDIFrameWnd

                                 子Frame:   class CChildFrame : public CMDIChildWnd

CMDIFrameWnd和CMDIChildWnd 都是标准MFC类, 且它们都继承自CFrameWnd.

 

 

view中可以在ondraw中画图,在别的函数中行不行? 可以创建控件? frame中也可以画图?

view, frame, dialog在本质上有何不同?在行为上有何不同?dialog能做的事view frame都可以做吗?

view frame dialog都是从cwnd继承而来的, 只要是cwnd,就可以画图, 所以view frame dialog都可以画图.

方法是使用DC. view的ondraw函数在frame 的onpaint之前执行.

 

有一个问题是如果在frame中的onpaint()中画条线, 但是如果前面没有afxmessagebox(), 那么这条线将不能显示????

 

当然也都可以摆放控件.只是在view frame里我们要动态创建, 不能像dialog那样拖控件上去.

如果想拖拉控件,可以使用CFormView, 这个结合了dialog和view的双重功能!

只是我们既然有了view ,我们就不再在frame上画图了,而是在view上画图.

 

状态栏上的文字?

 

滚动条:

为什么要滚动?

一个view窗口有尺寸, 比如说是300像素 * 500像素. 当你将一幅图像载入到该view中时,这幅图是一个点一个点的画出来的,

代码是这样的:

 for(int i=1; i < m_pointArray.GetSize(); i++)
 {
  pDC->LineTo(m_pointArray[i]);
 } 

 

假如一个点占一个像素的话, 如果横向点数超过了300个,那么超出的部分我们就看不到了。这时候我们可以将view窗口拉大,这时候就可以多看到一部分了。但是如果view拉到了和屏幕一样大(比如800*900),但是实际图像超过800*900个点,那我们就没办法看到整个图像了。

 

为了解决这个问题,滚动条出现了,即出现了一个cscrollview. 它靠什么解决问题? 要知道它不能将你的显示器变大,它的解决方法是每次只看该图像的一部分,这样你就可以通过这种方法来了解整个图像了。这时候view上有一个横向的按钮和一个竖向的按钮。假设这个view的大小是80*90, 你的显示器是800*900,图像是8000*9000, 这个view在一开始的时候显示的是图像的百分之一,点一下按钮,view去显示图像的下一个百分之一。点到一百下以后,图像就为空了,但是这时候我们可以一直点下去。。。这样似乎不太好,我们不知道什么时候图像已经显示完了,所以我们应该把scrollview设计为大小可控的,当我们设定了该view最大可以体现的像素数后,根据现在view的大小,我们可以计算出滚动条大小,点一次按钮滚动多少都可以计算出来。

即: SetScrollSizes(MM_TEXT, CSize(800,900));

如果图像中保存着自己的大小的话,那么我们在显示图像的程序中动态设定scrollview的大小的话,那不就完美了吗。。

即:SetScrollSizes(MM_TEXT, GetDocument()->GetDocSize());

至此我们可以精确的用scrollview来显示一幅任意大的图像。一切搞定。

 

 滚动条的 具体编程方法:

  1 让你的view类继承自CScrollView,

      class CHgView : public CScrollView

  2 在view类中实现一个方法:

     void CHgView::OnInitialUpdate()
      {
      CScrollView::OnInitialUpdate();
 
       // TODO: Add your specialized code here and/or call the base class
       SetScrollSizes(MM_TEXT, CSize(800,900));
     }

 

分割窗口的编程方法:

如果是单文档程序,则在CMainFrame类中增加一个成员变量CSplitterWnd m_splitwnd; 在类中实现这样一个函数

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
 // TODO: Add your specialized code here and/or call the base class
 return m_splitwnd.Create(this, 2,2,CSize(10,10),pContext);
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值