tags:

views:

212

answers:

5

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?

A: 

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?

Spence
A: 
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 );
}
TcKs
A: 

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);
aku
+1  A: 

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);
    }
}
Ishmaeel
A: 

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