Custom checkbox - disabled state color - vb.net

I have a custom checkbox witch allows resizing of the main rectangle. But when I want to set it as disabled, it doesnt gray out like normal checkbox control does. It just stays white.
Here is class for custom checkbox to allow resizing:
Public Class NewCheckBox
Inherits CheckBox
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
'Make the box you check 3/4 the height
Dim boxsize As Integer = Me.Height * 0.75
Dim rect As New Rectangle(
New Point(0, Me.Height / 2 - boxsize / 2),
New Size(boxsize, boxsize)
)
ControlPaint.DrawCheckBox(e.Graphics, rect, If(Me.Checked, ButtonState.Checked, ButtonState.Normal))
End Sub
End Class
Here is how i want to use it:
Private Sub txtFpo_TextChanged(sender As Object, e As EventArgs) Handles txtFpo.TextChanged
If functii.verificaLaser(txtFpo.Text) = True Then
NewCheckBox1.Enabled = False
'NewCheckBox1.ForeColor = Color.DarkGray
End If
I've tried to set the forecolor property, but to no avail.
How can i make the custom control to be greyed out in disabled mode?

I don't see anything in your code that specifies how to paint based on whether the control is disabled or not, so of course it doesn't change. Inactive is one of the ButtonState values so you need to specify that when the control is disabled.
Dim buttonState = ButtonState.Normal
If Me.Checked Then
buttonState = buttonState Or ButtonState.Checked
End If
If Not Me.Enabled Then
buttonState = buttonState Or ButtonState.Inactive
End If
ControlPaint.DrawCheckBox(e.Graphics, rect, buttonState)

Related

How can I apply a MouseHover and MouseLeave to two controls to act as one control?

I have two labels in my form which are placed side-by-side to act as one label. When I hover over the labels, I have a function that fades the labels to different colours, which works well. I am trying to apply the MouseHover and MouseLeave event to both labels, so that when I hover over Label1 and move to Label2 (and vice versa), the function doesn't then fade the colour back to the original colour. Currently, moving between the two labels activates MouseLeave followed by MouseHover again in the new label.
I have tried to add both labels to the event trigger, but this hasn't worked. I have also tried placing both labels in a Panel, but that then doesn't trigger the event.
Private Sub fadeHeaderIn(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseHover, Label2.MouseHover
Call fadeLabel("In")
End Sub
Private Sub fadeHeaderOut(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseLeave, Label2.MouseLeave
Call fadeLabel("Out")
End Sub
If the functionality to change the colour of part of the label existed, I'd not need the two labels, so if there is a better way of doing this altogether, I'm happy to do so. Thanks!
I have also tried placing both labels in a Panel, but that then
doesn't trigger the event.
That should work. The panel would act as the boundaries for both labels. You'll get a MouseLeave, though, when you move from the panel to the labels contained within. To prevent a false trigger, simply check if the mouse is still within the bounds of the panel. You can prevent multiple fade ins when moving from label to label by tracking the faded state with a boolean. It'd look something like this:
Public Faded As Boolean = False
Private Sub fadeHeaderIn(sender As Object, e As EventArgs) Handles Label1.MouseHover, Label2.MouseHover
If Not Faded Then
Faded = True
fadeLabel("In")
End If
End Sub
Private Sub fadeHeaderOut(sender As Object, e As EventArgs) Handles Panel1.MouseLeave
If Not Panel1.ClientRectangle.Contains(Panel1.PointToClient(Cursor.Position)) Then
If Faded Then
Faded = False
fadeLabel("Out")
End If
End If
End Sub
Here's a sample of what has been described in comments.
The Text of a control (here, derived from a standard Label) is split in two sections of the same measure. Each section can have a different color.
The active and inactive colors are custom public properties, they can be set in the designer.
Each section is tracked, meaning that the control is aware of what side the Mouse Pointer is currently hovering.
The size of the text is measured using the TextRenderer.MeasureText method. This size is used to calculate the rectangles that include the sections of text.
The Rectangle.Contains([Point]) method is then used to determine which section of the text the mouse pointer in hovering. [Point] is calculated using the MousePosition property, translated to client coordinates using the Control.PointToClient() method.
When the mouse pointer is moved from one section of text to the other (here, just two sections, more could be defined adding more rectangles), the control is Invalidated, causing a call to the OnPaint method of the control.
If the mouse pointer is not hovering a section of text, base.OnPaint(e) is called (also causing the Paint event to raise), which draws the default text with the default color.
In the OnPaint method, the Graphics region is clipped using the Rectangles that define the text sections. A subsequent call to TextRenderer.DrawText, setting the TextFormatFlags.PreserveGraphicsClipping flag, clips the text in the defined region, so just the section of text that fits in the clipping region is painted.
The Graphics.ExcludeClip() method is used here to define these clipping regions.
The TextFormatFlags.ExternalLeading and TextFormatFlags.TextBoxControl are also used to replicate the default text rendering, so the custom text is rendered in the same relative position.
This is how it behaves:
Custom Control Class to test the functionality:
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
<DesignerCategory("Code")>
Public Class LabelSplitText
Inherits Label
Private m_Text As String = String.Empty
Private m_Sections As RectangleF() = Nothing
Private m_PaintText As Boolean = False
ReadOnly flags As TextFormatFlags = TextFormatFlags.ExternalLeading Or
TextFormatFlags.PreserveGraphicsClipping Or
TextFormatFlags.TextBoxControl
Public Sub New()
InitializeComponent()
End Sub
Private Sub InitializeComponent()
ResizeRedraw = True
End Sub
Public ReadOnly Property ActiveRectangle As RectangleF
Public ReadOnly Property ActiveSide As String = String.Empty
Public Property ActiveColor As Color = Color.White
Public Property InactiveColor As Color = Color.DimGray
Protected Overrides Sub OnLayout(e As LayoutEventArgs)
MyBase.OnLayout(e)
Me.AutoSize = False
m_Text = Me.Text
End Sub
Protected Overrides Sub OnMouseEnter(e As EventArgs)
m_Text = Me.Text
Text = String.Empty
m_PaintText = True
MyBase.OnMouseEnter(e)
Invalidate()
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
m_PaintText = False
Me.Text = m_Text
MyBase.OnMouseLeave(e)
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
Invalidate()
If m_Sections Is Nothing Then Return
Me._ActiveRectangle = If(m_Sections(0).Contains(e.Location), m_Sections(0), m_Sections(1))
End Sub
Protected Overrides Sub OnMouseClick(e As MouseEventArgs)
Me._ActiveSide = If(m_Sections(0).Contains(e.Location), "left", "right")
MyBase.OnMouseClick(e)
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
If Not m_PaintText Then
MyBase.OnPaint(e)
Return
End If
Dim textSize As SizeF = TextRenderer.MeasureText(e.Graphics, m_Text, Me.Font, Me.ClientSize, flags)
m_Sections = GetTextAreaSections(textSize)
e.Graphics.ExcludeClip(Rectangle.Round(m_Sections(1)))
TextRenderer.DrawText(e.Graphics, m_Text, Me.Font, Point.Empty, GetSectionColor(0), flags)
e.Graphics.ResetClip()
e.Graphics.ExcludeClip(Rectangle.Round(m_Sections(0)))
TextRenderer.DrawText(e.Graphics, m_Text, Me.Font, Point.Empty, GetSectionColor(1), flags)
End Sub
Private Function GetSectionColor(section As Integer) As Color
Return If(m_Sections(section).Contains(PointToClient(MousePosition)),
Me.ActiveColor, Me.InactiveColor)
End Function
Private Function GetTextAreaSections(textSize As SizeF) As RectangleF()
If textSize.Width > Me.ClientSize.Width Then textSize.Width = Me.ClientSize.Width
Dim rectLeft = New RectangleF(PointF.Empty,
New SizeF(textSize.Width / 2.0F, Me.ClientSize.Height))
Dim rectRight = New RectangleF(New PointF(textSize.Width / 2.0F, 0),
New SizeF(textSize.Width / 2.0F, Me.ClientSize.Height))
Return {rectLeft, rectRight}
End Function
End Class

OnPaint event not firing

I am overriding the paint event as I need to give a text box an extra property. In this case the extra property is a border colour for a text box. When the User Control which contains the text boxes appears it does not fire the OnPaint event. I've no idea why this is happening.
My code is as follows
CustomTaskBox class
Public Class CustomTextBox
Inherits TextBox
<Browsable(True)>
<Category("Extended Properties")>
<Description("Set TextBox border Color")>
Public Sub New()
Multiline = False
BorderStyle = BorderStyle.None
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Dim buttonPen = New Pen(Color.Firebrick, 3)
Dim buttonRect = New Rectangle(0, 0, Size.Width - 1, Size.Height - 1)
e.Graphics.DrawRectangle(buttonPen, buttonRect)
End Sub
End Class
Main Class
Dim _NewTextBox As New CustomTextBox
_NewTextBox.Name = textBoxName
_NewTextBox.Multiline = multiline
_NewTextBox.Text = textBoxText
_NewTextBox.Top = topForNextControl
_NewTextBox.Left = 17
_NewTextBox.Width = textBoxWidth * widthScaleFactor
_MainContent.Controls.Add(_NewTextBox)
If I recall correctly - you need to useInvalidate(); to notify that control needs to be repainted.

Transparent Overlay

I'm trying to make an application which can overlay my screen with a transparent image in the middle. My goal is to make a crosshair for a game with no crosshair. My thinking is to detect if the active window title matches the game name, and if so display the overlaying crosshair. How would i make a screen overlay? This is my current code:
Private Function GetCaption() As String
Dim Caption As New System.Text.StringBuilder(256)
Dim hWnd As IntPtr = GetForegroundWindow()
GetWindowText(hWnd, Caption, Caption.Capacity)
Return Caption.ToString()
End Function
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If GetCaption() = "Game NameOf" Then
'Display Crosshair
End If
End sub
This methods works for most games but only in windowmode!
Place a picturebox on your Form and maximize yout picturebox
Disable your Windowboarders:
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Set your transperency key to black. Th
Me.TransparencyKey = Color.Black
Set background color to black:
Me.PictureBox1.BackColor = Color.Black
Set your window to foreground:
Me.TopMost = true
Maximize your window:
Me.WindowState = FormWindowState.Maximized
Now you can draw on your Picturebox in a Timer1_Tick or Form1_Paint event. Everything that is not Black will be drawn to your Desktop.
Dim g As = GraphicsPictureBox1.CreateGraphics
...
g.DrawLine(Pens.Red, 10, 10, 200, 200)
Important:
To pass input from mouse and keyboard through your window, your have to add the WS_EX_TRANSPARENT flag while .net creates your form. This can be done by overriding CreateParams proterty:
Const WS_EX_TRANSPARENT As Long = &H20
...
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim SecPerm As New SecurityPermission(SecurityPermissionFlag.UnmanagedCode)
SecPerm.Demand()
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or WS_EX_TRANSPARENT
Return cp
End Get
End Property
Hope I could help you.

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

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.

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