C++/CLI MFC 控件的循环创建与删除

C++/CLI中使用MFC框架,可以创建一些非常灵活的用户界面控件。本文将介绍一个自定义控件的实现过程,该控件通过循环创建和删除来实现用户界面的动态调整。这种技术虽然不是最高效的,但它在实际应用中表现出了良好的性能和用户体验。

操作概述

该控件与其父控件协同工作,形成一个循环。父控件首先创建控件,并为其指定初始位置和大小。控件负责绘制测试区域、活动可逆框架、提供光标反馈,并处理鼠标事件,以便用户执行一次调整大小的操作。当鼠标移动后释放,控件会触发一个事件,返回新的位置和大小数据。父控件捕获该事件并更新数据,然后删除控件。更新和删除操作会导致父控件的矩形区域无效,从而清理控件的绘制活动,并在父控件中绘制更新后的数据。然后,控件会使用新数据重新创建,允许用户继续调整活动对象的大小。这个过程会一直重复,直到用户在控件的边界内执行右键鼠标事件。此时,控件会发送一个终止事件,父控件会执行最终的更新、删除和无效操作,而不再重新创建控件。

一些细节

在本例中,用户可以通过上下文菜单选择创建两种形状(椭圆或三角形),并通过鼠标左键拖动可逆框架来创建。当在鼠标左键事件处理程序中选择现有形状时,如果存在sizerCtrl,它将被删除,形状枚举和包围矩形存储在结构中,并调用WSSizerHelper()。

WSSizerHelper()是创建WSSizer^ sizerCtrl、设置所需属性并链接到返回事件处理程序的地方:WSSizedEvent()和WSTerminateEvent()。所有WSSizer属性都以“WS”(代表WedgeSoft)为前缀,以便在IntelliSense中分组。

控件

如上所述,控件处理单个调整操作,并触发WSSizedEvent或WSTerminateEvent事件。控件的大小比输入矩形大WSPadding。用户的鼠标被限制在父控件的客户矩形内。但是,当鼠标移动到边缘附近时,可逆框架会绘制在父控件的边界之外。不知道如何阻止这种不希望的效果。框架被正确擦除,对象在父窗口内被正确裁剪。鼠标左键释放事件发送WSSizedEvent,鼠标右键释放事件发送WSTerminateEvent。

父控件

父控件再次从WSSizerSizedHandler中的WSSizedEvent链接到WSSizedEvent(),在WSSizedEvent()中捕获调整事件。在那里,它使用从控件接收到的数据修正活动形状。然后它删除控件,使矩形无效,并再次调用WSSizerHelper(),使用更新后的数据。使无效操作清理了大小调整控件所做的绘制工作,并刷新形状到其新位置和/或大小。WSSizerHelper()重新创建sizerCtrl,然后再次开始,直到用户执行右键鼠标事件。在这种情况下,执行上述所有操作,除了调用WSSizerHelper()。

一些有趣的点

考虑在控件中捕获Esc键,但进一步思考后,控件最多只能将其报告回父控件;因为只有父控件才能将形状恢复到原始大小。在示例中,参见MainForm_Keyup()。

在上面提到的废弃的用户界面中,不得不驯服DrawReversibleFrame()的怪癖。创建了DrawReversibleFrameEx(bool clear)。当调用时,参数“clear”设置为false,它绘制一个框架并将其推入堆栈。当设置为true时,该函数清空堆栈中的所有存储框架。认为在当前实现下堆栈是多余的;但它被证明是清理最后一个可见可逆框架所需的解决方案。从不构造函数中调用它。

早期,创建了一个BackColor的覆盖。在开发过程中,控件没有隐藏父控件的绘制工作。然后做了一些清理,发现控件现在隐藏了父控件的绘制工作。一些研究证明,BackColor的覆盖是关键,是必要的。

aRectangle = Rectangle(Point(X,Y),Drawing::Size(Width,Height)); aRegion->MakeEmpty(); aRegion->Complement(aRectangle);
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485