Delphi 中的设计时拖放?
在 Delphi 2006(我认为)引入 TFlowPanel 和 TGridPanel 之前,我做了一个概念上类似的控件。 它仍然做一些这些控件不做的事情,当将我的代码升级到 Delphi 2009 时,我决定也添加一些增强功能。
现在,子控件的顺序由它们的创建顺序决定。 FlowPanel 和 GridPanel 显示了使用 ControlIndex 和其他过滤属性的更好方法,但我想知道是否有一种方法可以在设计时处理拖放重新排序? 据我所知,拖动编辑控件并将其放到面板上不会调用我在设计时可以访问的任何内容。
我半幻想有一种方法可以直接检测放置操作,或者检测控件何时移动,以便我可以确定它应该去哪里。
有任何想法吗?
更新: 好的,成功了。 容器控件已经重写 AlignControls 来管理控件的放置。 当您拖动嵌套控件并将其放下时,将再次调用 AlignControls。 然后,我将控件的新坐标与列表中的其他控件进行比较,并将其移动到适当的位置。
我必须解决几个问题(主要与对 AlignControls 的多次调用有关),但基本概念很简单。 感谢所有评论者的帮助。
Before Delphi 2006 (I think) introduced the TFlowPanel and TGridPanel, I did a control that was similar in concept. It still does a couple of things those controls do not do, and when upgrading my code to Delphi 2009, I decided to add a couple of enhancements to that as well.
Right now, the order of the child controls is determined by their creation order. The FlowPanel and GridPanel show a better way with ControlIndex and other filtered properties, but I was wondering if there is a way to handle drag and drop reordering in design-time? As far as I can tell, dragging an edit control and dropping it onto my panel doesn't call anything that I can access at design-time.
I was half-fantasising about a way to either detect the drop operation directly, or to perhaps detect when a control is moved so I can determine where it should go.
Any ideas?
Update:
OK, got it working. The container control was already overriding AlignControls to manage the placement of the controls. When you drag the nested control and drop it, AlignControls is again called. I then compared the new coordinates of the control with the other controls in the list and moved it to the appropriate position.
There were a couple of problems that I had to work through (mostly related to the many calls to AlignControls) but the basic concept is simple enough. Thanks to all the commenters for all the help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
也许其中一些建议可能会有所帮助。
您可以在设计器中重新设置控件的父级,而无需进行剪切和粘贴。 查看结构窗格,只需将可视控件拖动到结构窗格中另一个父级的节点即可。 如果流程面板中有内容,请将所有内容拖出流程面板,然后按照您希望的顺序将它们拖回。
(您可以通过这种方式重新设置任何视觉控件的父级,而无需更改其父级以外的任何内容。我强烈建议您这样做。)
您可以将表单视为文本,并在其中移动声明顺序 - 但显然您直接编辑“资源”文件时需要小心。
您可以在设计器中设置 Tab 键顺序,这样您就可以根据 Tab 键顺序创建不同的控件,使其按您的需要工作。 您可以右键单击窗体并更改非可视控件的创建顺序,但这不适用于可视控件。
Perhaps some of these suggestions might help.
You can re-parent a control in the designer without having to do cut-and-paste. View the structure pane, and simply drag the visual control to the node of another parent in the structure pane. If you have things in a flowpanel, drag everything out of the flow panel and drag them back in the order that you want them to be.
(You can re-parent ANY visual control this way, without changing anything other than its parent. I highly recommend doing it this way.)
You can view the form as text, and move the declaration order around in there -- but obviously you'll need to be careful when editing the "resource" file directly.
You can set tab order in the designer, so you could make a different control based on tab order that works as you want. You can right click on the form and change the creation order of the non-visual controls, but that doesn't work with visual controls.
您是否尝试过为网格组件编写“OnDragDrop”事件,在其中检查组件是否处于设计模式?
我还没有编写这样的组件,但我不明白为什么该事件不应该触发。
Have you tried to write an "OnDragDrop" event for your grid component, where you check if your component is in design mode?
I haven't written such a component yet, but I don't see why the event shouldn't trigger.
您无法将窗体上已有的控件拖放到面板上。 拖动仅用于移动控件,而不是更改其父控件。 要更改父级,请剪切并粘贴。
如果该控件已位于面板上,并且您希望将其移动到面板上的另一个位置,则面板可以通过重写
TWinControl.AlignControls
方法来控制布局。 当移动控件时,会调用其SetBounds
方法,并且会在其父窗口上调用AlignControl(Self)
。 这会调用AlignControls。 查看 Controls.pas,您会发现这是一个复杂的方法,但它负责控件上子级的布局,而这正是您计划更改的内容。You can't drag a control that's already on the form and drop it onto your panel. Dragging is only for moving a control, not for changing its parent. To change the parent, cut and paste.
If the control is already on your panel, and you want to move it to another position on your panel, then the panel can control the layout by overriding the
TWinControl.AlignControls
method. When a control is moved, itsSetBounds
method is called, and among the things tha happens is that it callsAlignControl(Self)
on its parent window. That callsAlignControls
. Look in Controls.pas, and you'll see that that's a complicated method, but it's what is responsible for the layout of the children on a control, and that's exactly what you're planning to change.