As is typical with me, what started out as a seemingly achievable project has quickly snowballed out of control. I was talking to some of the Itron developers in Vancouver and them mentioned the desire to have a designer that would allow users to create custom screens or to customize existing screens. "No problem," says me. Just implement drag and drop on the form controls. I proceeded to do this and once I realized that the X and Y coordinates of the MouseEventArgs parameter of the MouseDown event were relative to the sending control (not the Form) I was set. I simply passed the Form.MousePostion as the data parameter for DoDragDrop method. Inside the DragDrop event I then subtracted the old location from the new location (using the X and Y coordinates since the Point class does not support arithmetic) and determined the distance to move the control. To figure out which control was moved I used the forms GetChildAtPoint( ) method using the original MouseDown point and converting it to client coordinates with the PointToClient() function. I have been deliberately brief in this discussion because as I delved further into the idea I realized how many complexities I would have to add. Here are just a few of them:
- Determining when to copy and when to paste.
- If copying creating the controls on the fly.
- Linking the controls to data.... what data?
- Adding new controls.
- Linking the new controls to data.
- Undo support
- Cut and Paste support
- Show control while dragging (easily supported via the MouseMove event.)
As you can see, this list quickly gets out of hand. Not that this isn't possible or that some of these items aren't reasonable on their own even. In combination, however, this is more than a simple spike I could complete in and evening or even two weeks of evenings. I think I will wait until I have a real need.
Anyway, here is the code:
public MyForm() {
// ... //******************************* // NOTE: Add this call InitializeForm(); //******************************* // ... // // Required for Windows Form Designer support // InitializeComponent();
}
//******************************* #region Form Design Support //******************************* // Initialize to true to demo code. Normally this would be set by a menu // option or some such. private bool m_DesignModeActive = true; public bool DesignModeActive { get { return m_DesignModeActive; } set { m_DesignModeActive = value; } } private void InitializeForm() { this.AllowDrop = true; this.ControlAdded += new ControlEventHandler(this.Control_Added); this.DragDrop += new DragEventHandler(this.ControlDragDrop); this.DragEnter += new DragEventHandler(this.ControlDragEnter); } private void ControlMouseEnter(object sender, System.EventArgs e) { Control control; control = this.GetChildAtPoint( this.PointToClient(Form.MousePosition)); if(control != null) { if(DesignModeActive) { control.Cursor = Cursors.SizeAll; } else { control.Cursor = Cursors.Default; } } } private void ControlMouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { if(DesignModeActive) { Control control = this.GetChildAtPoint( this.PointToClient(Form.MousePosition)); if(control != null) control.DoDragDrop(Form.MousePosition, DragDropEffects.Copy | DragDropEffects.Move); } } private void Control_Added(object sender, System.Windows.Forms.ControlEventArgs e) { e.Control.MouseDown += new MouseEventHandler(this.ControlMouseDown); e.Control.DragDrop += new DragEventHandler(this.ControlDragDrop); e.Control.MouseEnter += new EventHandler(this.ControlMouseEnter); this.AllowDrop = true; } private void ControlDragDrop(object sender, System.Windows.Forms.DragEventArgs e) { Control control; Point mouseDownPoint; if(e.Data.GetDataPresent(typeof(Point)) && DesignModeActive) { mouseDownPoint = (Point) e.Data.GetData(typeof(Point)); control = this.GetChildAtPoint( this.PointToClient(mouseDownPoint)); if(control !=null) { Point dropPoint = Form.MousePosition; control.Left = control.Left + (dropPoint.X - mouseDownPoint.X); control.Top = control.Top + (dropPoint.Y - mouseDownPoint.Y); } } } private void ControlDragEnter(object sender, System.Windows.Forms.DragEventArgs e) { if(e.Data.GetDataPresent(typeof(Point)) && DesignModeActive) e.Effect = DragDropEffects.Move; //DragDropEffects.Copy; } private void ControlQueryContinueDrag(object sender, System.Windows.Forms.QueryContinueDragEventArgs e) { // TODO } //******************************* #endregion // Form Designer Support
Note that this code was written generically so adding it to any form will enable moving of all controls on that form. To do this simply paste the Form Designer Support region to your form and call InitializeForm() from inside your constructor. Admittedly this isn't fully flushed out and I have already commented about all that is missing but hopefully this will provide a good start for those of you wishing to do a subset of what I list. Sorry about the abundance of comments.
P.S. Is there some way to get radio to stop changing the color when I use double back slashes?
11:56:13 PM
|