VB.NET - Non-client painting with Graphics.FromHwnd as Handle - vb.net

I'm trying to do some non-client area painting to get a MS Office like windowsform. I have one or two other posts of the sort, but here is the one that is done with Graphics.FromHwnd passing IntPtr.Zero as arg. I consulted a lot of information, that I tried and just simply cannot get it to work. Dwm functions, GetWindowDC, and or combination of these. Nothing works. Except this example that I post.
Public Class Form6
Protected Overrides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
Select Case m.Msg
Case WinAPI.Win32Messages.WM_ACTIVATEAPP
Me.Invalidate()
End Select
End Sub
Private Sub Form6_LocationChanged(sender As Object, e As EventArgs) Handles Me.LocationChanged
Me.Invalidate()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Dim usedColor As Color = Color.Beige
Me.BackColor = usedColor
Dim usedBrush As Brush = New SolidBrush(usedColor)
'Dim hDC As IntPtr = WinAPI.GetWindowDC(Me.Handle.ToInt64)
Using g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
'Using g As Graphics = Graphics.FromHdc(hDC)
'Caption
Dim rect As Rectangle = New Rectangle(Me.Left, Me.Top, Me.Width, SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height)
g.FillRectangle(usedBrush, rect)
'left border
rect = New Rectangle(Me.Left, Me.Top + SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height, (Me.Width - Me.ClientSize.Width) / 2, Me.ClientSize.Height)
g.FillRectangle(usedBrush, rect)
'right border
rect = New Rectangle(Me.Right - 2 * SystemInformation.FrameBorderSize.Width, Me.Top + SystemInformation.CaptionHeight + 2 * SystemInformation.FrameBorderSize.Height, (Me.Width - Me.ClientSize.Width) / 2, Me.ClientSize.Height)
g.FillRectangle(usedBrush, rect)
'bottom border
'If on maximize this border isn't drawn, by default the windowsize "drawing" is correct
If Me.WindowState <> FormWindowState.Maximized Then
rect = New Rectangle(Me.Left, Me.Bottom - 2 * SystemInformation.FrameBorderSize.Width, Me.Width, 2 * SystemInformation.FrameBorderSize.Height)
g.FillRectangle(usedBrush, rect)
End If
End Using
'WinAPI.ReleaseDC(Me.Handle.ToInt64, hDC)
End Sub
Private Sub Form6_Resize(sender As Object, e As EventArgs) Handles Me.Resize
Me.Invalidate()
End Sub
Private Sub Form6_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
Me.Invalidate()
End Sub
End Class
To generate graphics, I pass IntPtr.Zero for the hole screen.
I tried the GetWindowDC API (commented in code), and nothing happens. The handle was passed as Me.Handle, Me.Handle.ToInt32 and .ToInt64, and no result.
The invalidate called is to try to draw in every situation possible.
Problems that bring me here:
Form does not start up painted (can't figure it out);
Resizing flickers a lot (probably because the handle is to the entire screen, even form being double-buffered);
On the resizing, it's visible the painting over the cursor (again probably because of the handle for the graphics isn't the form's handle);
On mouse over control buttons (min, max and close), all drawing disappears;
Although I can detect problems, I can't get other ways to work, like the famous GetWindowDC, regardless of how many examples I tried that don't work, or even the DWM functions.
Being the purpose of getting my own "Office" like form, I ask some help in getting improvements to this code or some other ideas, that are welcome.
[EDIT]
Another flavor of the above code. This code was tried in form_load event, but nothing happened.
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
If Not DwmAPI.DwmIsCompositionEnabled(True) Then
Dim myHandle As IntPtr = WinAPI.FindWindow(vbNullString, Me.Text)
Dim hDC As IntPtr = WinAPI.GetWindowDC(myHandle)
Dim rect As WinAPI.RECT
With rect
.Left = 0
.Right = Me.Width
.Top = 0
.Bottom = 30
End With
Using g As Graphics = Graphics.FromHdc(hDC)
g.DrawString("TESTER", New Font(Me.Font.Name, 50), Brushes.Red, New Point(0, 0))
End Using
WinAPI.ReleaseDC(myHandle, hDC)
End If
End Sub
The result is this:
http://postimg.org/image/yyg07zf87/
As it would be clear, I want to have whatever if graphics drawn over titlebar and not under, although it's visible that the coords for the drawing are from full form area and not client area. If I doublebuffer the form, nothing is drawn. Any ideas?
Thanks for your patience. Best regards.

Related

VB.NET - Movement Blocked due to Faulty Collision Detection

So, I am making a game for my programming class as part of my final project. I'm just in the planning and experimenting stage at the moment and I decided to get a headstart on graphics and collisions. I first made my program just by experimenting with the Graphics class VB has to offer, instead of using PictureBoxes. Alongside that, I added keyboard input to move an Image around. When I decided to add collision detection through the intersectsWith() method of the Image class, things became weird.
Basically, in my code, the "Player" entity has three different images - which change depending on which way they are facing, which is in turn determined by what key the user presses. Without any collision detection code, the movement and image changing works fine and the image moves about. However, as soon as I add collision detection the player does not move at all, only the way they face changes. This happens even if the player's Image is nowhere near the image I want to test for intersection (a dollar sign). Here's my entire code:
Public Class Form1
Enum DirectionFacing
FORWARDS
BACKWARD
LEFT
RIGHT
End Enum
' Player X position.
Dim pX As Integer = 100
' Player Y position.
Dim pY As Integer = 100
' The direction the player is facing - by default, backward.
Dim dir As DirectionFacing = DirectionFacing.BACKWARD
' The image of the player.
Dim pI As Image = My.Resources.MainCharacter_Forward
' Another image designed to test for collision detection.
Dim dI As Image = My.Resources.DollarSign
Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
If (e.KeyCode = Keys.W) Then
' If they press W, move forward.
dir = DirectionFacing.FORWARDS
pI = My.Resources.MainCharacter_Forward
movePlayer(DirectionFacing.FORWARDS, 10)
ElseIf (e.KeyCode = Keys.S) Then
' If they press S, move backward.
dir = DirectionFacing.BACKWARD
pI = My.Resources.MainCharacter_Behind
movePlayer(DirectionFacing.BACKWARD, 10)
ElseIf (e.KeyCode = Keys.A) Then
' If they press A, move to the left.
pI = My.Resources.MainCharacter_Side
dir = DirectionFacing.LEFT
movePlayer(DirectionFacing.LEFT, 10)
ElseIf (e.KeyCode = Keys.D) Then
' If they press D, move to the right. To make the player face rightward,
' the image can be flipped.
Dim flipped As Image = My.Resources.MainCharacter_Side
flipped.RotateFlip(RotateFlipType.RotateNoneFlipX)
pI = flipped
dir = DirectionFacing.LEFT
movePlayer(DirectionFacing.RIGHT, 10)
End If
End Sub
' Moves the player by a certain amount AND checks for collisions.
Private Sub movePlayer(dir As DirectionFacing, amount As Integer)
If (dI.GetBounds(GraphicsUnit.Pixel).IntersectsWith(pI.GetBounds(GraphicsUnit.Pixel))) Then
Return
End If
If (dir = DirectionFacing.FORWARDS) Then
pY -= 10
ElseIf (dir = DirectionFacing.BACKWARD) Then
pY += 10
ElseIf (dir = DirectionFacing.LEFT) Then
pX -= 10
ElseIf (dir = DirectionFacing.RIGHT) Then
pX += 10
End If
End Sub
Private Sub draw(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim g As Graphics = e.Graphics()
g.DrawImage(dI, 400, 350)
g.DrawImage(pI, pX, pY)
Me.Invalidate()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.DoubleBuffered = True
End Sub
End Class
Basically, every time I press a key and want the image to move, the image doesn't move at all (even when the Player is nowhere close to the dollar sign), but the direction they are facing still changes. How can I keep the player moving and still stop the player from colliding with another image?
Well, the
If (dI.GetBounds(GraphicsUnit.Pixel).IntersectsWith(pI.GetBounds(GraphicsUnit.Pixel)))
will always return False since the GetBounds method does not return the current location of each rectangle. So they will never intersect, and your drawing scene remains the same.
So let's try to solve this problem.
Enum DirectionFacing
FORWARDS
BACKWARD
LEFT
RIGHT
End Enum
' The image of the player.
Dim pI As New Bitmap(My.Resources.MainCharacter_Forward)
' Another image designed to test for collision detection.
Dim dI As New Bitmap(My.Resources.DollarSign)
'The rectangle of the player's image.
Dim pIrect As New Rectangle(100, 100, pI.Width, pI.Height)
'The static rectangle of the collision's image.
Dim dIrect As New Rectangle(400, 350, dI.Width, dI.Height)
Now the IntersectWith function should work in the movePlayer method:
Private Sub movePlayer(dir As DirectionFacing, amount As Integer)
Dim px = pIrect.X
Dim py = pIrect.Y
Select Case dir
Case DirectionFacing.FORWARDS
py -= amount
Case DirectionFacing.BACKWARD
py += amount
Case DirectionFacing.LEFT
px -= amount
Case DirectionFacing.RIGHT
px += amount
End Select
If Not New Rectangle(px, py, pI.Width, pI.Height).IntersectsWith(dIrect) Then
pIrect = New Rectangle(px, py, pI.Width, pI.Height)
Invalidate()
End If
End Sub
Note that, both px and py variables are now locals because we already have pIrect which includes the currect x and y. We replaced the If statement with Select Case as a better approach I believe. We created a new rectangle to check any possible collision, if not, then we update our pIrect and refresh the drawing.
Besides moving the image through the W S A D keys, you also can make use of the &leftarrow; &uparrow; &rightarrow; &downarrow; keys. To intercept them in the KeyDown event, just override the IsInputKey function as follow:
Protected Overrides Function IsInputKey(keyData As Keys) As Boolean
Select Case keyData And Keys.KeyCode
Case Keys.Left, Keys.Up, Keys.Right, Keys.Down
Return True
Case Else
Return MyBase.IsInputKey(keyData)
End Select
End Function
Thus, the KeyDown event:
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
Select Case e.KeyCode
Case Keys.W, Keys.Up
pI?.Dispose()
pI = New Bitmap(My.Resources.MainCharacter_Forward)
movePlayer(DirectionFacing.FORWARDS, 10)
Case Keys.S, Keys.Down
pI?.Dispose()
pI = New Bitmap(My.Resources.MainCharacter_Behind)
movePlayer(DirectionFacing.BACKWARD, 10)
Case Keys.A, Keys.Left
pI?.Dispose()
pI = New Bitmap(My.Resources.MainCharacter_Side)
movePlayer(DirectionFacing.LEFT, 10)
Case Keys.D, Keys.Right
pI?.Dispose()
pI = New Bitmap(My.Resources.MainCharacter_Side)
pI.RotateFlip(RotateFlipType.RotateNoneFlipX)
movePlayer(DirectionFacing.RIGHT, 10)
End Select
End Sub
Again, we replaced the If Then Else statement with Select Case. If you are not supposed to do that, I believe it will be easy for you to revert and use If e.KeyCode = Keys.W OrElse e.KeyCode = Keys.Up Then ....
The Paint routine:
Private Sub draw(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim g As Graphics = e.Graphics()
g.DrawImage(dI, dIrect)
g.DrawImage(pI, pIrect)
End Sub
Finally, don't forget to clean up:
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
pI?.Dispose()
dI?.Dispose()
End Sub
Good luck

Button stays in MouseDown

Well, I'm getting back into GDI, and I came across my old first attempt, which was in c#. I converted it to VB.NET, and saw no errors. However, when I tested it out, the button would stay the color for the MouseDown state until I closed the MessageBox that it opens. Any ideas?
GDI -
Public Class BasicButton
Inherits Control
Public Enum MouseState
Normal
Down
End Enum
Private _mouseState As MouseState = MouseState.Normal
Protected Overrides Sub CreateHandle()
MyBase.CreateHandle()
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim g = e.Graphics
Select Case _mouseState
Case MouseState.Normal
g.FillRectangle(Brushes.Orange, ClientRectangle)
Exit Select
Case MouseState.Down
g.FillRectangle(Brushes.DarkOrange, ClientRectangle)
Exit Select
End Select
MyBase.OnPaint(e)
Dim sf As New StringFormat()
sf.LineAlignment = StringAlignment.Center
sf.Alignment = StringAlignment.Center
g.DrawString(Text, Font, New SolidBrush(Color.White), New Rectangle(0, 0, Width, Height), sf)
End Sub
Private Sub SwitchMouseState(state As MouseState)
_mouseState = state
Invalidate()
End Sub
Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
SwitchMouseState(MouseState.Normal)
MyBase.OnMouseUp(e)
End Sub
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
SwitchMouseState(MouseState.Down)
MyBase.OnMouseDown(e)
End Sub
End Class
Button -
Private Sub BasicButton1_Click(sender As Object, e As EventArgs) Handles BasicButton1.Click
MessageBox.Show("Text")
End Sub
MessageBox.Show is a blocking method that gets called between OnMouseDown and OnMouseUp. Basically, your OnMouseUp code is not called until after the MessageBox.Show method returns.
While not an answer, I believe it is important for you to be aware that creating resources within the Paint method should be done as sparingly as possible - hopefully not at all. Paint is called MANY MANY times per second in some cases.
So for instance where your code reads:
Dim sf As New StringFormat()
sf.LineAlignment = StringAlignment.Center
sf.Alignment = StringAlignment.Center
g.DrawString(Text, Font, New SolidBrush(Color.White), New Rectangle(0, 0, Width, Height), sf)
You are creating a StringFormat, and a SolidBrush, and a Rectangle.
The StringFormat and SolidBrush could be cached (by making them class-level variables). The Rectangle can also be cached by making it a class-level variable and updating it during the Resize event.

How to create translucent effect in visual basic windows forms?

Like the image below:
![The transparency effect i mean ][1]
http://i.stack.imgur.com/ststz.jpg
That effect in vb.You can actually see the background but its not purely transparent .Its translucent afaik.
I give you some ideas:
You can set the BackColor and TransparencyKey Color properties of your form to the same color.
Then assign the transparent image that you want, through handling the Mybase.Paint event, in this way:
Private Sub frmLogin_Paint(ByVal sender As Object,
ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
If Not Me.cObjImagen Is Nothing Then
e.Graphics.DrawImage(Me.cObjImagen, 0, 0, Me.Width, Me.Height)
End If
End Sub
Where 'cObjImagen' is a system.drawing.Image loaded from 'form_load' event, or from ' public sub new() ', for example...
If you need to move the form, this will help you to process the messages correctly:
Private Const WM_NCHITTEST As Integer = 132
Private Const HTCAPTION As Integer = 2
Protected Overloads Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_NCHITTEST Then
m.Result = New IntPtr(HTCAPTION)
Else
MyBase.WndProc(m)
End If
End Sub

How can you create a custom window (not a form object) in VB.net?

As the title states, is it possible / how can you create a custom window to draw onto? Normally, you would just use a form and form controls, but I want my own window with a handle that I'll attach hooks to and handle the paint events and the like. Is this possible? Essentially, I just need a container for my program's image that isn't a Form. If not in VB.Net, is it possible in C#?
EDIT:
I'm just not very fond of how the window draws (even with control over paint event). I removed the form border and the control bar and replaced them with my own functions (to place the max/min/exit buttons, title, form borders + sizing, etc) so the form I'm using is essentially just a floating panel - though with built in hooks that are nice of course. But the form still flickers too much and so I wanted to handle everything myself. I use doublebuffering on all controls I use and I use setbounds to move/resize controls as opposed to setting width/height individually (reduced some of the flicker). I draw the form border in the form's paint event, the rest is drawn as controls (including the form's top bar).
I mostly hate the black boxes that I see when I expand the form (generally don't see that when decreasing window size, but still some small amount of flicker). An alternative method, perhaps a different draw style (in VB 2010) or something, would work as well I guess.
EDIT (again):
The black box issue happens regardless of how many controls are on the form. If I try to manually resize it (the custom empty form control posted below that inherits from Form), using setbounds on each mousemove during a click and drag event (does not occur when not intended, so I know it's not running the sub more than it has to).
EDIT (code):
http://img211.imageshack.us/img211/900/j9c.png
So even on a blank "SimpleForm" (as posted in the first answer") with no controls, when resized to be larger (in the pic, resized northeast), black boxes are drawn under where the form will be drawn. Controlstyles / backbuffering done as posted in the second answer, as well as the createparams posted by Hans. This is what I used to set the form bounds:
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H2000000
cp.Style = cp.Style Or &H2000000
Return cp
End Get
End Property 'CreateParams
Public Sub New(ByRef ContentFolder As String, ByRef x As Integer, ByRef y As Integer, ByRef w As Integer, ByRef h As Integer)
FormBorderStyle = FormBorderStyle.None
'Note, I have tried the original suggested control styles in many combinations
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint
UpdateStyles()
OL = x 'Used for resizing, to know what the original bounds were - especially in maximizing, didn't like the standards maximize call
OT = y
OW = w
OH = h
BackColor = Color.White
BorderColor = New Pen(BarColor.Color)
MinimumSize = New Size(200, 200)
TransparencyKey = Color.FromArgb(255, 255, 0, 128)
CF = ContentFolder
ControlBar = New FormBar(Me, "Explorer woo", CF)
AddHandler Me.Load, AddressOf EF_Load
AddHandler Me.MouseUp, AddressOf EF_MouseUp
AddHandler Me.MouseDown, AddressOf EF_MouseDown
AddHandler Me.MouseMove, AddressOf EF_MouseMove
AddHandler Me.LostFocus, AddressOf EF_LostFocus
End Sub
Public Sub EF_Load(ByVal sender As Object, ByVal e As EventArgs)
SetFormBounds(OL, OT, OW, OH)
End Sub
Protected Overrides Sub OnSizeChanged(ByVal e As EventArgs)
ControlBar.SetBar(Width) 'Sets the width of controlbar to new width, and updates position of the 3 top-right form buttons
If Not (_backBuffer Is Nothing) Then
_backBuffer.Dispose()
_backBuffer = Nothing
End If
RaiseEvent Resized(Me, e) 'Resizes controls in custom handler, in this example, it is unused - with controls, they don't flicker when resized though
MyBase.OnSizeChanged(e)
End Sub
Private Sub SetFormBounds(ByRef l As Integer, ByRef t As Integer, ByRef w As Integer, ByRef h As Integer)
If w < Me.MinimumSize.Width Then
w = Me.MinimumSize.Width
l = Left
End If
If h < Me.MinimumSize.Height Then
h = Me.MinimumSize.Height
t = Top
End If
If l = Left AndAlso t = Top AndAlso w = Width AndAlso h = Height Then Exit Sub
ControlBar.SetBar(w)
SetBounds(l, t, w, h)
'Used for detecting if user coords are on the form borders with L-shaped areas so as to not include too much of the interior of the bar, Borderthickness = pixel width of border
CornerRects = New List(Of Rectangle) From {{New Rectangle(0, 0, BorderThickness, 15)}, {New Rectangle(0, 0, 15, BorderThickness)}, {New Rectangle(Width - 15, 0, 15, BorderThickness)}, {New Rectangle(Width - BorderThickness, 0, BorderThickness, 15)}, {New Rectangle(0, Height - 15, BorderThickness, 15)}, {New Rectangle(BorderThickness, Height - BorderThickness, 10, BorderThickness)}, {New Rectangle(Width - BorderThickness, Height - 15, BorderThickness, 15)}, {New Rectangle(Width - 15, Height - BorderThickness, 10, BorderThickness)}}
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
If _backBuffer Is Nothing Then
_backBuffer = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
End If
Dim g As Graphics = Graphics.FromImage(_backBuffer)
g.Clear(SystemColors.Control)
'Draw Control Box
g.TextRenderingHint = Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit
g.FillRectangle(BarColor, 0, 0, Width, ControlBar.Height)
If ControlBar.Title <> "" Then g.DrawString(ControlBar.Title, ControlBar.Font, ControlBar.FontBrush, ControlBar.TextLeft, ControlBar.TextTop)
g.DrawImage(FormBar.bmpCorners(0), 0, 0) 'Makes transparent corner, very small bitmap created at run-time
g.DrawImage(FormBar.bmpCorners(1), Width - FormBar.bmpCorners(0).Width, 0)
'Draw Control Box buttons top right
If ControlBar.ExitButton.Enabled = True Then g.DrawImage(ControlBar.ExitButton.Img, ControlBar.ExitButton.Rect.X, ControlBar.ExitButton.Rect.Y)
If ControlBar.MaximizeButton.Enabled = True Then g.DrawImage(ControlBar.MaximizeButton.Img, ControlBar.MaximizeButton.Rect.X, ControlBar.MaximizeButton.Rect.Y)
If ControlBar.MinimizeButton.Enabled = True Then g.DrawImage(ControlBar.MinimizeButton.Img, ControlBar.MinimizeButton.Rect.X, ControlBar.MinimizeButton.Rect.Y)
If Not ControlBar.Ico Is Nothing Then g.DrawImage(ControlBar.Ico, 5, 5) 'Draw Control Box icon (program icon) if it is set
'Draw the form border
For i = 0 To BorderThickness - 1
g.DrawLine(BorderColor, i, ControlBar.Height, i, Height - 1)
g.DrawLine(BorderColor, Width - 1 - i, ControlBar.Height, Width - 1 - i, Height - 1)
g.DrawLine(BorderColor, BorderThickness, Height - 1 - i, Width - BorderThickness, Height - 1 - i)
Next
g.Dispose()
e.Graphics.DrawImageUnscaled(_backBuffer, 0, 0)
End Sub
Protected Overrides Sub OnPaintBackground(ByVal pevent As PaintEventArgs)
End Sub
It is not really possible at all, in either language. This isn't a language thing, or even a framework (i.e. WinForms) thing. Rather, it's more because of the design of Windows itself. Essentially, everything in Windows is a window, and the Form class represents a basic top-level window that can be displayed directly on the desktop. If you want a window displayed on the desktop, you need to use the Form class. Moreover, if you want to have a window handle that you can attach hooks to, you'll need to use this class; it's the one with all the necessary plumbing to get that going.
But that doesn't mean it has to look like a default Form object does. The appearance is infinitely customizable. Start by setting the FormBorderStyle property of your form to remove the default window frame/chrome. That will give you a completely blank slate. Then, do like you said and handle its Paint event. Except that when you're wanting to handle the events of a derived class, you should override the OnXxx method directly, instead of subscribing to the events. So you'd have this code:
Public Class SimpleForm : Inherits Form
Public Sub New()
' Alter the form's basic appearance by removing the window frame,
' which gives you a blank slate to draw onto.
FormBorderStyle = FormBorderStyle.None
' Indicate that we're painting our own background.
SetStyle(ControlStyles.Opaque, True)
End Sub
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
' Call the base class.
MyBase.OnPaint(e)
' Paint the background...
e.Graphics.FillRectangle(Brushes.MediumAquamarine, Me.ClientRectangle)
' ...and then the foreground.
' For example, drawing an 'X' to mark the spot!
Using p As New Pen(Color.Navy, 4.0)
e.Graphics.DrawLine(p, 0, 0, Me.Width, Me.Height)
e.Graphics.DrawLine(p, Me.Width, 0, 0, Me.Height)
End Using
End Sub
End Class
Of course, such a window has severe usability problems. For starters, the user has no way to move it around on the screen or to close it. You'll need to handle those things yourself if you're eliminating the default border.
Can you show the method you are using to enable double buffering? Here's an article that addresses this. Perhaps it will help.
https://web.archive.org/web/20140811193726/http://bobpowell.net/doublebuffer.aspx
Basically, the code is like this (from the article):
Private _backBuffer As Bitmap
Public Sub New
InitializeComponents()
Me.SetStyle(ControlStyles.AllPaintingInWmPaint OR _
ControlStyles.UserPaint OR _
ControlStyles.DoubleBuffer, True)
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
If _backBuffer Is Nothing Then
_backBuffer = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
End If
Dim g As Graphics = Graphics.FromImage(_backBuffer)
'Paint on the Graphics object here
g.Dispose()
'Copy the back buffer to the screen
e.Graphics.DrawImageUnscaled(_backBuffer, 0, 0)
End Sub 'OnPaint
'Don't allow the background to paint
Protected Overrides Sub OnPaintBackground(ByVal pevent As PaintEventArgs)
End Sub 'OnPaintBackground
Protected Overrides Sub OnSizeChanged(ByVal e As EventArgs)
If Not (_backBuffer Is Nothing) Then
_backBuffer.Dispose()
_backBuffer = Nothing
End If
MyBase.OnSizeChanged(e)
End Sub 'OnSizeChanged

How to Add Custom Objects in to listbox of VB 2010

I am developing one vb application. In that I have one list box. I want to add different types of Items. Like Different Colored and differently aligned text(Like one item item is right aligned and one more is left aligned). Can you please tell me how can i do the same.
Thanks.
This is how I did it in one of my projects (the original code is in c#):
Public Class ColoringStepCommandListBox
Inherits CommandListBox
Const ItemHeight As Integer = 20
Public Sub New()
listBox.ItemHeight = ItemHeight
listBox.DrawMode = DrawMode.OwnerDrawFixed
End Sub
Protected Overrides Sub OnDrawItem(sender As Object, e As DrawItemEventArgs)
Const textFormatFlags__1 As TextFormatFlags = TextFormatFlags.EndEllipsis Or TextFormatFlags.PreserveGraphicsClipping Or TextFormatFlags.VerticalCenter
Const colorRectangleWidth As Integer = 100, textLeft As Integer = 110
If e.Index >= 0 Then
'Cast the listbox item to your custom type (ColoringStep in my example).
Dim coloringStep = TryCast(listBox.Items(e.Index), ColoringStep)
e.DrawBackground()
'Do custom coloring and rendering, draw icons etc.
Dim colorRect = New Rectangle(2, e.Bounds.Top + 2, colorRectangleWidth, ItemHeight - 5)
Dim innerRect = New Rectangle(colorRect.Left + 1, colorRect.Top + 1, colorRect.Width - 1, colorRect.Height - 1)
e.Graphics.DrawRectangle(Pens.Black, colorRect)
DrawingHelper.DrawGradient(coloringStep, e.Graphics, innerRect, LinearGradientMode.Horizontal)
'Draw the text (this does not happen automatically any more with owner draw modes).
Dim textRect = New Rectangle(textLeft, e.Bounds.Top, e.Bounds.Width - textLeft, e.Bounds.Height)
TextRenderer.DrawText(e.Graphics, coloringStep.ToString(), e.Font, textRect, e.ForeColor, textFormatFlags__1)
e.DrawFocusRectangle()
End If
End Sub
End Class
I got simple solution for this. Below is the code
Private Sub ListBox1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ListBox1.DrawItem
e.DrawBackground()
Dim textFont As New Font(e.Font.FontFamily, e.Font.Size * 4)
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString(), textFont, New SolidBrush(Color.BlueViolet), RectangleF.op_Implicit(e.Bounds))
e.DrawFocusRectangle()
End Sub
Private Sub listBox1_MeasureItem(ByVal sender As Object, ByVal e As System.Windows.Forms.MeasureItemEventArgs) Handles ListBox1.MeasureItem
e.ItemHeight = e.ItemHeight * 4
End Sub
You can add extra code inside ListBox1_DrawItem method to customize Items