Есть ли способ нарисовать элемент управления на другой элемент управления в C #? - PullRequest
3 голосов
/ 16 января 2009

Я хотел бы нарисовать элемент управления для другого элемента управления в переопределенном событии рисования. Под рисованием я подразумеваю реальный рисунок, не помещая элемент управления в другой элемент управления. Есть ли хороший способ сделать это?

Ответы [ 5 ]

1 голос
/ 16 января 2009

Попробуйте статические методы в классе ControlPaint . Нарисованные элементы управления не могут быть скины, как остальная часть графического интерфейса, но эффект будет довольно правдоподобным. Ниже приведена урезанная версия моего кода. Он переопределяет метод DrawItem владельца ListBox, отрисованного владельцем, чтобы элементы списка выглядели как кнопки, используя метод ControlPaint.DrawButton .

В этом классе есть еще много полезных для флажков, комбо и даже ручек перетаскивания.

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);
    }
}
0 голосов
/ 29 сентября 2009

Вы можете сделать это очень легко, используя метод DrawToBitmap элемента управления. Вот фрагмент кода, который создаст кнопку и нарисует ее на 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();
0 голосов
/ 16 января 2009
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 );
}
0 голосов
/ 16 января 2009

Вы можете добавить / переопределить обработчик OnPaint, как предложено @TcKs, или использовать функцию 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);
0 голосов
/ 16 января 2009

Возможно, вам нужна «панель», от которой вы можете унаследовать, а затем создать свое собственное поведение?

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

Возьмите e.graphics, и вы можете делать практически все, что захотите, в пределах контроля. Из памяти вы можете установить минимальные размеры для вашего элемента управления и т. Д., Но вам нужно будет перейти к документации windows.forms в MSDN для более подробной информации (или вы могли бы задать другой вопрос здесь;)).

Или, если вы, например, добавляете функциональность, вы должны унаследовать от элемента управления попытки улучшить и переопределить его метод рисования?

Возможно, вы могли бы уточнить (в своем вопросе), для чего вы хотите это сделать?

...