关于MFC的MVC一些想法

在写MFC的时候, 很少是一个对话框能够搞定的, 一般都需要多个对话框交互, 如要是DoMudule的对话框也还好, 因为这种对话框一般不用操作父窗口或者与他平级的窗口, 但是如果是类似在一个 PropertySheet或者更复杂时, 就会出现要多个对话框进行交互. 类似下面一种情况:
1
A区域是一个全局区域(如一个树形控件), B区域根据A区域的选择是用来显示不同的对话框, C域可能是一个Log Window, D区域可能是一些全局按钮(它的操作影响到所有会在B区域出现的对话框), 所有在B区域出现的对话框都要在C区域打印log.
还有最重要的一点, 在B区域中设置一个对话框B1后, 下次显示另一个对话框B2时可能会根据B1的设置状态来做不同的显示.试想一下如果B区域有5个对话框B1, B2, B3, B4, B5.而他们的依赖关系如下:
B1 –> B2, B3, B4;
B2 –> B1, B3, B5;
B3 –> B1, B2, B4;

那么仔细看一下就会发现各种循环依赖, 但是我个人对于循环依赖是有洁癖的.
—————————————————————————————
所以在最近的一次MFC项目中我采用如下方法:
首先我抽象出一个模块E, 这个模块是用来处理纯数据, 他对应于B1~B5对所有状态及实现函数. B1~B5可以设置模块E中属于自己的属性, 可以调用属于自己操作, 至于内部状态怎么去切换是E模块的事, E模块可以用C来实现也可以用C++ 的单例/件模式来实现, 这样他们的依赖关系就成了下面这样:
B1 –> E;
B2 –> E;
B3 –> E;
B4 –> E;
B5 –> E;
如果B区域操作想要对于些全局窗口进行操作如C, 那么只在主对话框在OnInitialDialog中设置一下对于C操作的callback函数即可,这样B1~B5在调用属于自己的函数时, 模块E来决定是不是要使用callback来控制区域C, 还有其它B区域中对话框的数据.

可以看到到目前为止把B区域的对话框当作Module的话, 那么模块E就是Control了.

其实显示即View我没有太好的办法:
我从CDialogEx继承了一个CViewDlg出来然后加了void RefreshUI(void), void RefreshUIData(void)两个纯虚函数, 并重写了OnShowWindow函数差在OnShowWindow中判断当这个对话框在显示时调用RefreshUI, 在被隐藏时调用RefreshUIData.
这样所有B区域的对话框全从CViewDlg中派生出来, 强迫所有B区域对话框来实现RefreshUI来从E模块中获得自己的属性并设置相应的UI内容, 实现RefreshUIData在被隐藏时设置自己的属性到模块E中,以便其他模块在ShoWindow时可能会要用到.
到此View也分开了.

这是我目前有想到的惟一解决循环依赖并差不多实现MVC方法的一种实现, 其实可以看到虽然这种思路可以在写MFC时通用,但是其实做法并不通用尤其是View部分的实现如果是其他的UI设计可能要重新设计View部分的机制才行.



评论

  1. […] 与大名鼎鼎的MVC模式有不谋而合的味道, 后来我在做UI时采用了相同的方法. 然后我们就把逻辑处理部分定义为后台, […]

发表评论