分享
 
 
 

WTL体系结构(3)

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

WTL体系结构

视图

视图窗口看起来显得很简单:

class CMyView : public CWindowImpl<CMyView>

{

public:

DECLARE_WND_CLASS(NULL)

BOOL PreTranslateMessage(MSG* pMsg)

{

pMsg;

return FALSE;

}

BEGIN_MSG_MAP(CMyView)

MESSAGE_HANDLER(WM_PAINT, OnPaint)

END_MSG_MAP()

LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&)

{

CPaintDC dc(m_hWnd);

//TODO: Add your drawing code here

return 0;

}

};

上面是一个SDI程序的视图类. 多线程SDI和MDI的视图类在本质上也跟这个一样,但他们没有PreTranslateMessage()方法. SDI程序就是使用这个函数,赶在框架类处理消息之前把消息抓住. PreTranslateMessage()在SDI的框架类中的实现是,直接将消息转发给视图类.

这里显示的视图实际上没有做什么工作.你应该自己在OnPaint()函数中加入画出文档内容的代码.如果需要支持输入,如鼠标的点击和键盘的按键,你应该加入相应消息处理函数到类和映射中. 可以看到这个窗口是从CWindowImpl<>继承下来的,如果你想让它基于一个Win32控件的话,就应该从定义在AtlCtrls.h文件中某个WTL类继承.

如果想在基于CWindowImpl<>的类里加上滚动条,那么你应该把基类换成CScrollWindowImpl<>,同时把消息链给它:

class CMyView : public CScrollWindowImpl<CMyView>

{

public:

typedef CScrollWindowImpl<CMyView> parent;

BEGIN_MSG_MAP(CMyView)

CHAIN_MSG_MAP(parent)

END_MSG_MAP()

void DoPaint(CDCHandle dc)

{

}

};

基类保证窗口具备滚动条,并提供滚动条消息的默认处理.视图类不再有WM_PAINT的处理函数,因为它已被CScrollWindowImpl<>处理.根据滚动条的位置,CScrollWindowImpl<>画出视图相对应的部分. 取而代之的是,在你的类里实现DoPaint(),在这里你需要画出整个视图.如果你想指定滚动的范围,大小或起点,你需要加上处理WM_CREATE消息的函数,把这些初始化代码放到里边.

正如我先前所提到的,框架窗口会改变视图窗口的大小,以使它客户区未被状态条和工具条覆盖的部分为视图所填充. 在大多数情况下,这样就够了.但是当你想要一个具有Windows Explorer样子的程序时,该怎么办呢? Windows Explorer的窗口包含了一个tree view 和一个list view,还有两者之间的分割条. WTL的解决方案很简单:使用splitter窗口!

为此你需要改变一下框架窗口,让它创建splitter窗口的一个实例作为它的视图. 例如, 在你的框架类里有如下的数据成员:

CSplitterWindow m_view;

CTreeViewCtrl m_tree;

CListViewCtrl m_list;

你可以在OnCreate()创建一个splitter窗口:

// get the frame client rect, so that we set the splitter initial size

// and we can get the splitter bar in the centre

RECT rect;

GetClientRect(&rect);

m_hWndClient = m_view.Create(m_hWnd, rect,

NULL, WS_CHILD | WS_VISIBLE);

m_tree.Create(m_view, rcDefault, NULL,

WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT,

WS_EX_CLIENTEDGE);

m_list.Create(m_view, rcDefault,

NULL, WS_CHILD | WS_VISIBLE | LVS_REPORT, WS_EX_CLIENTEDGE);

m_view.SetSplitterPanes(m_tree, m_list);

m_view.SetSplitterPos();

Splitter窗口如同一个视图,将框架窗口作为它的父窗口. 在这段代码里,我将框架窗口客户区的实际大小传给了splitter窗口. 我也可以在这里使用 rcDefault,因为一旦框架窗口创建完成,框架窗口就会转发WM_SIZE消息给splitter. 这样splitter可以马上改变自身的大小来填充框架. 然而,当我准备使用不带参数的SetSplitterPos(),把分割条设置于窗口中线时,出现了问题.Splitter窗口使用它的大小来决定中线的位置,由于rcDefault告诉窗口它的大小是0(因此中线的位置也是0),从而意味着分割条将出现在z最左边,将左窗口隐藏了起来.

创建了splitter窗口后,你需要创建那些你想要分割的窗口了.它们将作为splitter窗口的子窗口被创建.最后你将这些子窗口通过SetSplitterPanes()加到splitter窗口中去,并确定分割条的位置所在.

UI Update

菜单项可以被设置为有效或无效,可以带check记号或着像radio按钮一样,在一组菜单项中同时有且只有一个能被check.此外,菜单项还可以带图标和文字. 所有的这些状态都可以在运行时根据程序中的某个值进行改变.工具条在某种程度上可以看做是菜单的易见形态,因为它们的按钮可以个别地,或者作为一组的一部分被置成有效或无效,推入推出. UI update机制允许你指定哪些UI元件(UI element)的状态可以在运行时改变. WTL使用如下的UI update映射来实现这一功能:

BEGIN_UPDATE_UI_MAP(CMainFrame)

UPDATE_ELEMENT(ID_FILE_SAVERESULTS, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)

UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)

UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)

END_UPDATE_UI_MAP()

这个例子指出三个菜单项在运行时有一个状态需要显示,其中的一个, ID_FILE_SAVERESULTS,还有一个工具条按钮跟它相关联. WTL通过建立一个数组来保存这些信息.为此你需要完成两方面的工作:

首先是UI元件的状态. 如果是菜单项, 你可以使用UIEnable()使能该菜单项, UISetCheck()设置check记号, UISetText()改变菜单的文字.如果是工具条按钮,那么你使用UIEnable()使能该按钮, UISetCheck()或者UISetRadio()决定按钮是推入还是推出.下边的代码根据是否有文本被选中,来使能Cut菜单项和工具条按钮:

BOOL bSelected = GetSelected();

UIEnable(ID_EDIT_CUT, bSelected);

你可以把这样的代码放入相应处理函数中(如一个菜单项的状态依赖于另一个菜单项的动作,将它放入后者的处理函数中),或者放入OnIdle()方法,通过检查某个类变量来决定元件的状态.

其次是确定各个UI元件是否都被更新了,为此你需要调用CUpdateUI<>的某个方法将UI元件加入到列表中.主菜单已被自动加入,但是其他的任何菜单和所有的工具条必须分别通过调用UIAddMenuBar()和UIAddToolBar()手动加入.

其他还有一堆事情要注意. 首先,设置了工具条的状态后,使用UIUpdateToolBar()以使工具条状态更新. 对于菜单,你不需如此,因为子菜单是动态生成的.UIUpdateMenuBar()这个方法也存在,但是它的作用是把菜单恢复到初始状态,如果你改变过某些项的文字,调用UIUpdateMenuBar()的结果可能不是你所期望的(因为菜单项的文字会变成老的).

尽管还有一个方法UISetRadio(),但是还没有一个把几个菜单项或者工具条按钮当做radio按钮组(也就是说,有一个而且只有一个被选中)的机制.如果你希望得到这样效果,你必须自己编码,不过它并不难.

(未完待续)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有