C# Windows 窗体的装饰器

发布于 2024-08-20 18:26:50 字数 220 浏览 3 评论 0原文

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

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

我将不胜感激任何帮助。

谢谢。

I have a canvas (Panel Control) in my WinForms app where users can drag things like textbox's, labels etc around. But I want to make it easier for them to more precisely align the objects. I've read into it and Adorners seem to be the way to go? But, apparently it's only for WPF. WPF is not an option for me, unfortunately.

What I'm trying to accomplish is to have lines pop up every time the user drags an object around in the canvas... Just how they work in the Windows Forms Designer View.

I'd appreciate any help at all.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我还不会笑 2024-08-27 18:26:50

谢谢大家的回答。


我已经设法提出自己的解决方案。代码在下面。目前还没有“线条”,但有一天我会解决它...

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 个像素。

Thank you all for your answers.


I've managed to come up with my own solution. The code is down below. There are no "lines" yet, but I'll get around to it oneday...

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();
}

The above code must be placed inside the Control_MouseMove Event, and ofcourse, you still need your own code that actually moves the controls.

The code above will snap the control you're dragging 5 pixels to the right, left, top or bottom of the nearest control.

一身骄傲 2024-08-27 18:26:50

这里有一个类似的问题:对齐行在运行时对齐控件

我建议如下:

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

对于捕捉部分。另一位用户指出 Form Desginer 可能会帮助您。

There was a similiar question here: Snap-To lines when aligning controls at Runtime

Where I suggested something like:

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

For the snap part. Another user pointed to Form Desginer which might help you out.

不顾 2024-08-27 18:26:50

这是完全有可能做到的。查看 MSDN。与此同时,我将尝试找到一些我在其中做同样事情的代码。

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);

It is quite possible to do. Look at the DrawReversibleLine method on MSDN. In the meantime, I'll try to find some code in which I was doing the same thing.

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);
    }
}

I know this is a very general & mostly crude start, but as mentioned, it can be a tedious task. Especially when it comes to tracking the movement, etc. Remember that on the MyControl_MouseUp event to call the ControlPaint.DrawReversibleFrame(...) to erase the frame. Also, during control movement. Calling the function again with the exact same parameters is all you need to to. Hope that helps.

Also, to reduce flicker, as Josh points out, add the following after your InitializeComponents();

//  To reduce redraw flicker
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
稀香 2024-08-27 18:26:50

如果我理解正确的话,您希望设置您的控件,使其行为类似于其他容器控件(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);
    }
}

现在,当我将其拖向边缘时,我作为子项放置的任何控件都会捕捉到该矩形。

哈!

If I understand correctly, you're looking to setup your control so that it act's kind of like the other container controls (GroupBox, Panel, etc)?

If so, I think DisplayRectangle is what you're after. You change it to the rectangle you want the other controls to snap to. For example, I have a GroupBox style control and I set the DisplayRectangle like so:

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

Now any control I place as a child will snap to that rectangle when I drag it toward the edges.

HTH!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文