Making a bitmap from a control.

vis781

Well-known member
Joined
Aug 30, 2005
Messages
2,016
Location
Cambridge, UK
Programming Experience
5-10
Hi all, I jave set myself the task of creating a custom textbox, one that has round corners for example. After much trolling through the help files i have found that it's not going to be easy as the vb.net textbox is just a wrapper for the old win32 textbox. However i had an idea that i could override the wndproc and create a bitmap of the original textbox, then alter it as i needed, then show it to the screen in a picturebox. So my question is can you create a bitmap of a control?

P.s if i manage it i'll post the full code.
 
Not sure where you're heading, but for drawing control to bitmap... InvokePaint normally work, but it didn't for TextBox when I tried. .Net 2.0 got DrawToBitmap method :) Not much help, a textbox shouldn't be that difficult to subclass and draw yourself with paint/background, especially when you're drawing the corners/border anyway?
 
on custom control try something like this:

ProtectedOverridesSub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(pe)
Me.BorderStyle = BorderStyle.None
Me.BackColor = SystemColors.Control
'here you draw rounded rectangle (find code somewhere dont have time to write it)
'set size of the rectangle to size of the textbox
EndSub
 
Thats the direction that i started off in, however if you override the onpaint event it is ignored unless you set the controlstyle 'userpaint' to true, but if you do this the textbox doesn't redraw itself unless the user selects some text. So maniccw if i followed your suggestion it would draw the border, but the moment you started to edit the textbox it would overwrite anything that has been painted, and it would not repaint itself. Doing other controls has been fairly easy but this one is a bit of a pain!!
JohnH here are my thoughts....

Add a picturebox to the control instead of the actual textbox
Capture a bitmap of the original textbox by sending a WM_PRINT message //The bit i'm stuck on

Then finally i wil need to redirect all the mouseevents from the picturebox to the textbox. See what i mean, a bit of a pain.
 
vis781, here is some use of WM_PRINT:
VB.NET:
Private Function getControlBitmap(ByVal ctrl As Control) As Bitmap
  Dim bmp As New Bitmap(ctrl.Width, ctrl.Height)
  Dim g As Graphics = Graphics.FromImage(bmp)
  Dim ip As IntPtr = g.GetHdc()
  SendMessage(ctrl.Handle, WM_PRINT, ip, PRF_CLIENT + PRF_NONCLIENT + PRF_OWNED + PRF_CHILDREN + PRF_ERASEBKGND)
  g.ReleaseHdc(ip)
  g.Dispose()
  Return bmp
End Function
 
Const WM_PRINT As Int32 = &H317
Const PRF_CLIENT As Int32 = &H4I
Const PRF_NONCLIENT As Int32 = &H2I
Const PRF_CHILDREN As Int32 = &H10I
Const PRF_OWNED As Int32 = &H20I
Const PRF_ERASEBKGND As Int32 = &H8I
 
Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
  ByVal hwnd As IntPtr, _
  ByVal wMsg As Int32, _
  ByVal wParam As IntPtr, _
  ByVal lParam As Int32) As Int32
I also played some with creating a rounded textbox usercontrol, it absolutely needs a lot of refinements. Some properties in the misc section. Also the 'disappearing usercontrol problem' is incredibly annoying and present in the project attached.
 

Attachments

  • vbnet11-roundedTextbox.zip
    8.2 KB · Views: 55
Ok here it is, actually it's a bit of a cheat, but never the less a rounded textbox that supports alpha blended backcolors. Thanks to johnH and a site from the code project. Didn't get time to sort out one particular bug which was how to make the parent form invalidate if the control eas removed from the form. It works if you set the rounded property to false though. There are two new properties. BackAlpha (0-255) which will allow the backcolor to become translucent or even totally transparent, and 'Rounded' which will give the textbox round corners. The whole project is attached. Enjoy. Wish i could say that i done it all myself.
 

Attachments

  • LightningControlsSE.zip
    47.2 KB · Views: 55
It's looking good, but there are some troubles:
- first I only got 'object reference not set to instance's. This is because you in first If statement of GetBitmaps method access width-height properties of bitmaps without checking if they are nothing, easy to fix.
- remove paint handler in Dispose method, else it will keep drawing after control is removed from form.
 
The big problem i have with this is that it seems to be quite a expensive control to have on your form. I going to look into ways i can optimize this control, any suggestions would be appreciated.
 
Re

JohnH said:
vis781, here is some use of WM_PRINT:
VB.NET:
Private Function getControlBitmap(ByVal ctrl As Control) As Bitmap
  Dim bmp As New Bitmap(ctrl.Width, ctrl.Height)
  Dim g As Graphics = Graphics.FromImage(bmp)
  Dim ip As IntPtr = g.GetHdc()
  SendMessage(ctrl.Handle, WM_PRINT, ip, PRF_CLIENT + PRF_NONCLIENT + PRF_OWNED + PRF_CHILDREN + PRF_ERASEBKGND)
  g.ReleaseHdc(ip)
  g.Dispose()
  Return bmp
End Function
 
Const WM_PRINT As Int32 = &H317
Const PRF_CLIENT As Int32 = &H4I
Const PRF_NONCLIENT As Int32 = &H2I
Const PRF_CHILDREN As Int32 = &H10I
Const PRF_OWNED As Int32 = &H20I
Const PRF_ERASEBKGND As Int32 = &H8I
 
Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
  ByVal hwnd As IntPtr, _
  ByVal wMsg As Int32, _
  ByVal wParam As IntPtr, _
  ByVal lParam As Int32) As Int32
I also played some with creating a rounded textbox usercontrol, it absolutely needs a lot of refinements. Some properties in the misc section. Also the 'disappearing usercontrol problem' is incredibly annoying and present in the project attached.

good code..it help others
 
Back
Top