【问题标题】:Adorners for C# Windows FormsC# Windows 窗体的装饰器
【发布时间】:2010-02-11 20:56:07
【问题描述】:

我的 WinForms 应用程序中有一个画布(面板控件),用户可以在其中拖动文本框、标签等内容。但我想让他们更容易更精确地对齐对象。我读过它,装饰器似乎是要走的路?但是,显然它仅适用于 WPF。不幸的是,WPF 不适合我。

我想要完成的是每次用户在画布中拖动对象时都会弹出线条...它们在 Windows 窗体设计器视图中的工作方式。

如果有任何帮助,我将不胜感激。

谢谢。

【问题讨论】:

    标签: c# winforms controls adorner


    【解决方案1】:

    谢谢大家的回答。


    我已经想出了自己的解决方案。代码在下面。还没有“台词”,但我总有一天会解决的……

    Label l = (Label)sender;
    foreach (Control control in Canvas.Controls)
    {
        if (l.Location.X > control.Location.X + control.Size.Width && l.Location.X < control.Location.X + control.Size.Width + 5)
            l.Location = new Point(control.Location.X + control.Size.Width + 5, l.Location.Y);
        else if (l.Location.X < control.Location.X - l.Size.Width && l.Location.X > control.Location.X - l.Size.Width - 5)
            l.Location = new Point(control.Location.X - l.Size.Width - 5, l.Location.Y);
        else if (l.Location.Y > control.Location.Y + control.Size.Height && l.Location.Y < control.Location.Y + control.Size.Height + 5)
            l.Location = new Point(l.Location.X, control.Location.Y + control.Size.Height + 5);
        else if (l.Location.Y < control.Location.Y - control.Size.Height && l.Location.Y > control.Location.Y - control.Size.Height - 5)
            l.Location = new Point(l.Location.X, l.Location.Y - 5);
    
        this.Update();
    }
    

    上述代码必须放在 Control_MouseMove 事件中,当然,您仍然需要自己的代码来实际移动控件。

    上面的代码会将您拖动 5 个像素的控件捕捉到最近的控件的右侧、左侧、顶部或底部。

    【讨论】:

      【解决方案2】:

      这里有一个类似的问题:Snap-To lines when aligning controls at Runtime

      我建议的地方如下:

      left = (left/10)*10;
      top = (top/10)*10;
      

      对于按扣部分。另一位用户指出 Form Desginer 可能会对您有所帮助。

      【讨论】:

        【解决方案3】:

        这是完全可以做到的。查看MSDN 上的DrawReversibleLine 方法。与此同时,我会尝试找到一些我在其中做同样事情的代码。

        bool AllowResize;
        bool DoTracking;  
        
        private void MyControl_MouseDown(object sender, MouseEventArgs e)
        {
            if (AllowResize)
            {
                DoTracking = true;
                        ControlPaint.DrawReversibleFrame(new Rectangle(this.PointToScreen(new Point(1,1)),
                this.Size), Color.DarkGray, FrameStyle.Thick);
            }
        }
        

        我知道这是一个非常笼统且主要是粗略的开始,但如前所述,这可能是一项乏味的任务。尤其是在跟踪运动等方面。请记住,在 MyControl_MouseUp 事件中调用 ControlPaint.DrawReversibleFrame(...) 以擦除帧。此外,在控制运动期间。您只需要使用完全相同的参数再次调用该函数。希望对您有所帮助。

        此外,为了减少 闪烁,正如 Josh 指出的那样,在您的 InitializeComponents(); 之后添加以下内容

        //  To reduce redraw flicker
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.DoubleBuffer, true);
        

        【讨论】:

          【解决方案4】:

          如果我理解正确,您希望设置您的控件,使其行为类似于其他容器控件(GroupBox、Panel 等)?

          如果是这样,我认为 DisplayRectangle 就是您所追求的。您将其更改为您希望其他控件捕捉到的矩形。例如,我有一个 GroupBox 样式控件,我将 DisplayRectangle 设置如下:

          public override Rectangle DisplayRectangle
          {
              get
              {
                  return Rectangle.FromLTRB(base.DisplayRectangle.Left,
                      base.DisplayRectangle.Top + Font.Height + 4,
                      base.DisplayRectangle.Right,
                      base.DisplayRectangle.Bottom);
              }
          }
          

          现在,当我将它拖向边缘时,我小时候放置的任何控件都会捕捉到该矩形。

          HTH!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-04-10
            • 2011-11-27
            • 1970-01-01
            • 1970-01-01
            • 2010-09-19
            • 1970-01-01
            • 2020-11-23
            • 1970-01-01
            相关资源
            最近更新 更多