有没有办法在 C# 中的其他控件上绘制控件?

发布于 2024-07-12 03:10:06 字数 82 浏览 5 评论 0原文

我想在其重写的绘制事件中在其他控件上绘制一个控件。 我所说的绘图是指真正的绘图,而不是将控件放置在另一个控件内。 有什么好的方法可以做到这一点吗?

I would like to draw a control on some other control in it's overriden paint event. By drawing I mean real drawing, not placing the control inside the other control. Is there any nice way to do that?

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

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

发布评论

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

评论(5

黎歌 2024-07-19 03:10:06

尝试 ControlPaint 类上的静态方法。 绘制的控件可能不像 GUI 的其余部分那样具有皮肤,但效果将非常可信。 下面是我的一些代码的精简版本。 它使用 ControlPaint.DrawButton 方法重写所有者绘制的 ListBox 的 DrawItem 方法,使列表项看起来像按钮。

该类还有更多关于复选框、组合、甚至拖动手柄的好东西。

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)
{
    e.DrawBackground();

    if (e.Index > -1)
    {
        String itemText = String.Format("{0}", this.Items.Count > 0 ? this.Items[e.Index] : this.Name);

        //Snip

        System.Windows.Forms.ControlPaint.DrawButton(e.Graphics, e.Bounds, ButtonState.Normal);

        e.Graphics.DrawString(itemText, this.Font, SystemBrushes.ControlText, e.Bounds);
    }
}

Try the static methods on the ControlPaint class. Drawn controls may not be skinned like the rest of the GUI, but the effect will be pretty believable. Below is a stripped-down version of some of my code. It is overriding the DrawItem method of an ownerdrawn ListBox to make the list items look like buttons, using ControlPaint.DrawButton method.

There are more goodies on that class for checkboxes, combos, even drag handles.

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)
{
    e.DrawBackground();

    if (e.Index > -1)
    {
        String itemText = String.Format("{0}", this.Items.Count > 0 ? this.Items[e.Index] : this.Name);

        //Snip

        System.Windows.Forms.ControlPaint.DrawButton(e.Graphics, e.Bounds, ButtonState.Normal);

        e.Graphics.DrawString(itemText, this.Font, SystemBrushes.ControlText, e.Bounds);
    }
}
飞烟轻若梦 2024-07-19 03:10:06
public delegate void OnPaintDelegate( PaintEventArgs e );
private void panel1_Paint( object sender, PaintEventArgs e ) {
    OnPaintDelegate paintDelegate = (OnPaintDelegate)Delegate.CreateDelegate(
        typeof( OnPaintDelegate )
        , this.button1
        , "OnPaint" );
    paintDelegate( e );
}
public delegate void OnPaintDelegate( PaintEventArgs e );
private void panel1_Paint( object sender, PaintEventArgs e ) {
    OnPaintDelegate paintDelegate = (OnPaintDelegate)Delegate.CreateDelegate(
        typeof( OnPaintDelegate )
        , this.button1
        , "OnPaint" );
    paintDelegate( e );
}
旧街凉风 2024-07-19 03:10:06

您可以按照 @TcKs 建议添加/覆盖 OnPaint 处理程序或使用 BitBlt 函数:

[DllImport("gdi32.dll")]
private static extern bool BitBlt(
    IntPtr hdcDest,
    int nXDest, 
    int nYDest, 
    int nWidth, 
    int nHeight, 
    IntPtr hdcSrc, 
    int nXSrc, 
    int nYSrc, 
    int dwRop 
);

private const Int32 SRCCOPY = 0xCC0020;

....

Graphics sourceGraphics = sourceControl.CreateGraphics();
Graphics targetGraphics = targetControl.CreateGraphics();
Size controlSize = sourceControl.Size;
IntPtr sourceDc = sourceGraphics.GetHdc();
IntPtr targerDc = targetGraphics.GetHdc();
BitBlt(targerDc, 0, 0, controlSize.Width, controlSize.Height, sourceDc, 0, 0, SRCCOPY);
sourceGraphics.ReleaseHdc(sourceDc);
targetGraphics.ReleaseHdc(targerDc);

You can add/override OnPaint handler as @TcKs suggested or use BitBlt function:

[DllImport("gdi32.dll")]
private static extern bool BitBlt(
    IntPtr hdcDest,
    int nXDest, 
    int nYDest, 
    int nWidth, 
    int nHeight, 
    IntPtr hdcSrc, 
    int nXSrc, 
    int nYSrc, 
    int dwRop 
);

private const Int32 SRCCOPY = 0xCC0020;

....

Graphics sourceGraphics = sourceControl.CreateGraphics();
Graphics targetGraphics = targetControl.CreateGraphics();
Size controlSize = sourceControl.Size;
IntPtr sourceDc = sourceGraphics.GetHdc();
IntPtr targerDc = targetGraphics.GetHdc();
BitBlt(targerDc, 0, 0, controlSize.Width, controlSize.Height, sourceDc, 0, 0, SRCCOPY);
sourceGraphics.ReleaseHdc(sourceDc);
targetGraphics.ReleaseHdc(targerDc);
海之角 2024-07-19 03:10:06

也许您所追求的是一个“面板”,您可以继承它,然后创建自己的行为?

class MyPanel : System.Windows.Forms.Panel
{
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        base.OnPaint(e);
    }
}

抓住 e.graphics,您几乎可以在控件的范围内做任何您想做的事情。 根据记忆,您可以在控件等上设置最小尺寸,但您需要跳转到 MSDN 中的 windows.forms 文档以了解更多细节(或者您可以在此处提出另一个问题;))。

或者,如果您例如添加功能,您应该从尝试增强并覆盖其绘制方法的控件继承?

也许您可以(在您的问题中)详细说明您希望这样做的目的?

Perhaps what you're after is a "panel" which you can inherit from and then create your own behaviour?

class MyPanel : System.Windows.Forms.Panel
{
    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        base.OnPaint(e);
    }
}

Grab e.graphics and you can do pretty much anything you want within the bounds of the control. From memory you can set minimum sizes on your control etc. but you'll need to jump over to windows.forms documentation in MSDN for more specifics (or you could ask another question here ;) ).

Or if your for instance adding functionality, you should inherit from the control your attempting to enhance and override it's paint method?

Perhaps you could elaborate (in your question) what you wish to do this for?

他是夢罘是命 2024-07-19 03:10:06

您可以使用控件的 DrawToBitmap 方法非常轻松地完成此操作。 下面是一个片段,它将创建一个 Button 并将其绘制在相同大小的 PictureBox 上:

Button btn = new Button();
btn.Text = "Hey!";
Bitmap bmp = new Bitmap(btn.Width, btn.Height);
btn.DrawToBitmap(bmp, new Rectangle(0, 0, btn.Width, btn.Height));
PictureBox pb = new PictureBox();
pb.Size = btn.Size;
pb.Image = bmp;

要在另一个控件的 Paint 事件中使用此方法,您可以像上面那样从该控件创建位图,然后将其绘制在控件的表面上,如下所示:

e.Graphics.DrawImage(bmp, 0, 0);
bmp.Dispose();

You can do this very easily by using the control's DrawToBitmap method. Here is a snippet that will create a Button and draw it on a same-sized PictureBox:

Button btn = new Button();
btn.Text = "Hey!";
Bitmap bmp = new Bitmap(btn.Width, btn.Height);
btn.DrawToBitmap(bmp, new Rectangle(0, 0, btn.Width, btn.Height));
PictureBox pb = new PictureBox();
pb.Size = btn.Size;
pb.Image = bmp;

To use this approach in another control's Paint event, you would create the Bitmap from the control as above, then draw it on the control's surface like this:

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