Results 1 to 5 of 5

Thread: Drawing other controls

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    Drawing other controls

    I'm trying to code a designer for controls for my app (not an IDE designer). I'm going to be able to move the control around and size it using the mouse. I want to prevent mouse events on the control without disabling the control. The best way I can think of this is to hijack the drawing code and draw the control into my own control.

    I got it to work with the Button control: I call the OnPaint method. How? (Considering that it's protected...) I used reflection to find the "OnPaint" method signature and called it using the invoke method providing it the graphics object attached to a label control. The code to invoke the Button's paint event was in the Label's paint event.

    This worked surprisingly well for the button. Unfortunately, it didn't work so well for other controls, such as the Listbox.

    Using Lutz Roeder's .NET Reflector* (to decompile the listboxes drawing methods) I discovered that the Listbox does it's drawing from a method called by WndProc instead of OnPaint (like a rational control...)

    Is there a way anybody knows of to cause a control, in most sane circumstances, to paint to a Graphics object that is not its own?

    Do you know of a better way to obtain my long-term goal of preventing mouse events from reaching a visible and enabled control?

    I'm designing this with the intention that it work with anything that inherits Control.

    ---
    *Using Lutz Roeder's .NET Reflector decompiles .Net assemblies through reflection. Available free at http://www.aisto.com/roeder/dotnet/
    Last edited by agent; Nov 23rd, 2006 at 03:08 AM. Reason: Added URL for .NET Reflector

  2. #2
    PowerPoster sparrow1's Avatar
    Join Date
    May 2005
    Location
    Globetrotter
    Posts
    2,820

    Re: Drawing other controls

    Hi,

    Here's a link how to draw your own controls using GDI+.

    http://msdn.microsoft.com/library/de...cntrlsamp4.asp

    Hope it helps,

    sparrow1
    Wkr,
    sparrow1

    If I helped you, don't forget to Rate my post. Thank you

    I'm using Visual Studio.Net 2003 and
    2005
    How to learn VB.Net Create setup with VB 2005 Drawing for beginners VB.Net Tutorials GDI+ Tutorials
    Video's for beginners

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    Re: Drawing other controls

    Quote Originally Posted by sparrow1
    Hi,

    Here's a link how to draw your own controls using GDI+.

    http://msdn.microsoft.com/library/de...cntrlsamp4.asp

    Hope it helps,

    sparrow1
    I'm actually interested in getting another control to draw itself into a graphics object I provide... in other words, I want to draw a control other than mine into mine.

    If I attach my control to a button, my control will appear exactly as the attached button does.

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    Re: Drawing other controls

    The following is the incomplete but somewhat usable control that I'm working on. Copy/paste this into a new file (there are two classes).

    To use it, drop ControlSizer onto a form. Drag another control, (tested with Button, Label, Groupbox) onto the form. Set the property Control of ControlSizer to the control you just dropped.

    The controls listed above (Button, etc) work properly. It's other controls, such as ProgressBar, ScrollBars, TextBox, Listbox, etc, that don't work.

    Basically, anything that does the painting in OnPaint and OnBackgroundPaint properly paints in my control. Controls, such as Listbox which do their painting from WndProc don't paint in my control.

    Anybody know of a better way to do this?

    VB Code:
    1. Public Class ControlSizer
    2.     Private Const SizeGripSize = 8I
    3.  
    4.     'These hold the protected methods 'OnPaint' and 'OnBackgroundPaint' of _Control
    5.     Private _PaintMethod As System.Reflection.MethodInfo
    6.     Private _PaintBackgroundMethod As System.Reflection.MethodInfo
    7.  
    8.     'This is where the protected methods 'OnPaint' and 'OnBackgroundPaint' of _Control are called
    9.     Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs)
    10.         'everything is doublebuffered for speed now
    11.         Dim MyRect = New Rectangle(Point.Empty, Me.Size)
    12.  
    13.         'Paint _Control into a buffer
    14.         Dim ControlBuffer As New Bitmap(Me.Width - (SizeGripSize * 2), Me.Height - (SizeGripSize * 2), Imaging.PixelFormat.Format32bppArgb)
    15.         If _Control IsNot Nothing Then
    16.             Using ControlBufferGraphics As Graphics = Graphics.FromImage(ControlBuffer)
    17.                 Dim args As Object() = {New PaintEventArgs(ControlBufferGraphics, New Rectangle(Point.Empty, _Control.Size))}
    18.                 _PaintBackgroundMethod.Invoke(_Control, args)
    19.                 _PaintMethod.Invoke(_Control, args)
    20.             End Using 'ControlGraphics
    21.         End If
    22.  
    23.         'Paint the size grips, selection, and border into a buffer
    24.         Dim SizeGripBuffer As New Bitmap(Me.Width, Me.Height, Imaging.PixelFormat.Format32bppArgb)
    25.         Using SizeGripBufferGraphics As Graphics = Graphics.FromImage(SizeGripBuffer)
    26.             'todo: draw size grips
    27.  
    28.             'right now, we'll just draw a transparent selection box
    29.             Using SelectionBrush As New SolidBrush(Color.FromArgb(128, SystemColors.Highlight))
    30.                 SizeGripBufferGraphics.FillRectangle(SelectionBrush, MyRect)
    31.             End Using
    32.  
    33.             ControlPaint.DrawSelectionFrame(SizeGripBufferGraphics, True, MyRect, Rectangle.Inflate(MyRect, -2, -2), SystemColors.Highlight)
    34.  
    35.         End Using
    36.  
    37.         'Paint any owner draw stuff into a buffer
    38.         Dim OwnerDrawBuffer As New Bitmap(Me.Width, Me.Height, Imaging.PixelFormat.Format32bppArgb)
    39.         Using OwnerDrawBufferGraphics As Graphics = Graphics.FromImage(OwnerDrawBuffer)
    40.             MyBase.OnPaint(New PaintEventArgs(OwnerDrawBufferGraphics, MyRect))
    41.         End Using
    42.  
    43.         'Paint all the buffers to the control
    44.         pe.Graphics.DrawImage(ControlBuffer, New Point(SizeGripSize, SizeGripSize))
    45.         pe.Graphics.DrawImage(SizeGripBuffer, Point.Empty)
    46.         pe.Graphics.DrawImage(OwnerDrawBuffer, Point.Empty)
    47.  
    48.         'Dispose all the buffers
    49.         ControlBuffer.Dispose()
    50.         SizeGripBuffer.Dispose()
    51.         OwnerDrawBuffer.Dispose()
    52.     End Sub
    53.  
    54.     'This is where _PaintMethod and _PaintBackgroundMethod are set
    55.     Public Property Control() As Control
    56.         Get
    57.             Return _Control
    58.         End Get
    59.         Set(ByVal value As Control)
    60.             If value Is Me Then
    61.                 Throw New CircularReferenceException
    62.             Else
    63.                 _Control = value
    64.  
    65.                 RefreshSize(True)
    66.  
    67.                 If _Control IsNot Nothing Then
    68.                     _PaintBackgroundMethod = _Control.GetType.GetMethod("OnPaintBackground", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.FlattenHierarchy)
    69.                     _PaintMethod = _Control.GetType.GetMethod("OnPaint", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.FlattenHierarchy)
    70.                 End If
    71.             End If
    72.         End Set
    73.     End Property
    74.     Private _Control As Control
    75.  
    76.     'Adjusts the size of this control or _Control as needed. Also forces redraw
    77.     Public Sub RefreshSize(ByVal SizeToControl As Boolean)
    78.         If _Control IsNot Nothing Then
    79.             If SizeToControl Then
    80.                 Me.Bounds = Rectangle.Inflate(_Control.Bounds, SizeGripSize, SizeGripSize)
    81.                 Me.BringToFront()
    82.             Else
    83.                 _Control.Bounds = Rectangle.Inflate(Me.Bounds, -(SizeGripSize), -(SizeGripSize))
    84.             End If
    85.  
    86.             Me.Invalidate()
    87.         End If
    88.     End Sub
    89.  
    90.     Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
    91.         MyBase.OnSizeChanged(e)
    92.  
    93.         RefreshSize(False)
    94.     End Sub
    95.  
    96.     Protected Overrides Sub OnLocationChanged(ByVal e As System.EventArgs)
    97.         MyBase.OnLocationChanged(e)
    98.  
    99.         RefreshSize(False)
    100.     End Sub
    101. End Class
    102.  
    103. Public NotInheritable Class CircularReferenceException
    104.     Inherits ApplicationException
    105.  
    106.     Sub New()
    107.         MyBase.New("An attempt has been made to create a reference that is circular (for example, attaching a Resizer control to itself).")
    108.     End Sub
    109. End Class

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    Re: Drawing other controls

    I think what I'll do in the interim is add a 'special drawing' handler or something. If I notice something doesn't draw correctly, the host app can draw a generic control (a white box with some text or something)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width