How to draw amount of blocks of the progressbar in VB.NET? - vb.net

Progressbar has a maximumm is 10.
So I need to draw ten block without fill color before running progress.
Edit: added code
Public Class MyProgressBar
Inherits ProgressBar
Public Sub New()
Me.ForeColor = Color.Red
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
For i as integer = 1 to 10
Dim g As Graphics = e.Graphics
Dim widthScale As Integer = Me.Width/10
g.DrawRectangle(Pens,Me.Left+(i*widthScale ),Me.Top, Me.Width / 10, Me.Height)
End For
End Sub
End Class
I try override OnPaint() but it's not working.

There are number of ways to do this. The simplest would be to create a transparent image of the boxes and put it on top of a regular progress bar.
Or you could create an array of text boxes, and play with their position, border and background until they look the way you want.
A more powerful way to do graphics is with the built-in .net graphics object. There's a brief introduction here

Related

How to Draw Highlight Behind Richtextbox

Using this code, it draws the highlight on the text, which makes the text somehow blur?
Public Class HighlightableRTB
Inherits RichTextBox
Private LineHeight As Integer = 15
Public Sub New()
HighlightColor = Color.Yellow
End Sub
<Category("Custom"), Description("Specifies the highlight color.")>
Public Property HighlightColor As Color
Protected Overrides Sub OnSelectionChanged(ByVal e As EventArgs)
MyBase.OnSelectionChanged(e)
Me.Invalidate()
End Sub
Private Const WM_PAINT As Integer = 15
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_PAINT Then
Dim selectLength = Me.SelectionLength
Dim selectStart = Me.SelectionStart
Me.Invalidate()
MyBase.WndProc(m)
If selectLength > 0 Then Return
Using g As Graphics = Graphics.FromHwnd(Me.Handle)
Dim b As Brush = New SolidBrush(Color.FromArgb(50, HighlightColor))
Dim line = Me.GetLineFromCharIndex(selectStart)
Dim loc = Me.GetPositionFromCharIndex(Me.GetFirstCharIndexFromLine(line))
g.FillRectangle(b, New Rectangle(loc, New Size(Me.Width, LineHeight)))
End Using
Else
MyBase.WndProc(m)
End If
End Sub
End Class
How can one draw the rectangle highlight behind the text of the richtextbox?
As you already guessed, the text is not really "blurry"... it's the yellow rectangle which is painted over it that makes it looks that way.
This is not going to be easy. In fact, I have a solution, but it's not something I would recommend... if I had anything else to say. But I haven't, so here's one way to deal with this issue:
You can paint the text... over the text. It doesn't remove the text which already exists... but paints over it. If your coordinates are a little bit off, it'll look like crap, but if you get the exact right place it'll work like a charm. An awful, hacky charm:
Using g As Graphics = Graphics.FromHwnd(Me.Handle)
Dim b As Brush = New SolidBrush(Color.FromArgb(50, HighlightColor))
Dim line = Me.GetLineFromCharIndex(Me.SelectionStart)
Dim loc = Me.GetPositionFromCharIndex(Me.GetFirstCharIndexFromLine(line))
g.FillRectangle(b, New Rectangle(loc, New Size(Me.Width, LineHeight)))
TextRenderer.DrawText(g, Me.Text, Font, New Point(-2, 1), ForeColor) ' this is the important line!
End Using
This is 100% a hack, though, and I sure hope that somebody with more sense than I chime in. The position I wrote (-2, 1) should do the trick, but if somehow it doesn't, you can get rid of the transparency to hide your shame by replacing Color.FromArgb(50, HighlightColor) by Color.FromArgb(255, HighlightColor). It won't be that obvious since the text will only reveal this dirty trick when someone selects it (try it!).
Have fun!

Custom rounded button with outline

I am tring to create a custom button width rounded corner and a white outline which follows its shape. On the OnPaint event I've added the following code.
Public Class RoundedButton
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Dim grPath As GraphicsPath = New GraphicsPath(FillMode.Winding)
grPath.AddArc(0, 0, ClientSize.Height, ClientSize.Height, 90, 180)
grPath.AddLine(grPath.GetLastPoint, New Point(ClientSize.Width - grPath.GetLastPoint.X * 2, 0))
grPath.AddArc(New RectangleF(grPath.GetLastPoint, New Size(ClientSize.Height, ClientSize.Height)), 270, 180)
grPath.CloseFigure()
Me.Region = New Region(grPath)
Dim mypen As New Pen(Color.White, 2)
mypen.Alignment = PenAlignment.Inset
e.Graphics.DrawPath(mypen, grPath)
End Sub
End Class
If I try to use it in a form, it works only if Backcolor property is set to Transparent. If not I can't see the pen path.
I would like to change the backcolor without loose the rounded white border of the pen.
I would like to obtain something like this:
With all projects that you want custom buttons, it is usually easiest to curve a PictureBox with a picture of your button, then using your coding language (VB.NET, C#, C++) to add an on click function to make the action.
Here is a mini example using VB.NET:
Private Sub pictureBox1_Click(sender As Object, e As EventArgs) Handles pictureBox1.Click
Process.start("http://stackoverflow.com")
End Sub
Hope I helped,
Matt

Resize Form from the Drawn Shape of Panel - VB.NET

I'm trying to make a form resizable based on dragging a custom shape drawn at the corner of the panel. I have a code which works fantastic if it's drawn in the main form, but if I'm trying to draw it at the corner of a panel it doesn't work, I cannot resize the form. The code is optimized to be drawn in the form, could someone help me and update it to work in a panel too?
Protected Overrides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
If m.Msg = &H84 Then
Dim pos = Me.PointToClient(New System.Drawing.Point(m.LParam.ToInt32() And &HFFFF, m.LParam.ToInt32() >> 16))
If pos.X >= Me.Width - grab AndAlso pos.Y >= Me.Height - grab Then
m.Result = New IntPtr(17)
End If
End If
End Sub
Private Const grab As Integer = 14
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Dim rc = New System.Drawing.Rectangle(Me.Width - grab, Me.Height - grab, grab, grab)
ControlPaint.DrawSizeGrip(e.Graphics, System.Drawing.Color.FromArgb(250, 250, 250), rc)
End Sub
It looks like this:
Here
I managed to solve the problem by building my own custom control using GDI to paint the shape as standalone control, instead of painting it to an already built control, such panel.

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 can I set a form to have a transparent background

I am struggling to get my form to have a transparent background in vb.net
Currently in the form New I set
Me.SetStyle(ControlStyles.SupportsTransparentBackColor, true)
But still the form shows up as having the default grey background
Can anyone help??
EDIT: I need the controls on the form to be visible so I don't think setting the opacity to 0 will work
EDIT: I tried the transparency key solution but it doesn't work. I have a circular image with a black background. OnPaint I set the transparency key to the img pixel at 0,0, this then leaves me with circular image (which I want ) It hides the black background but I am still left with the default grey rectangle of the form.
below is the code I have -
Public Sub New()
Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
Me.BackColor = Color.Transparent
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.Timer1.Start()
End Sub
Private Sub frmWoll_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim img As Bitmap = CType(Me.BackgroundImage, Bitmap)
img.MakeTransparent(img.GetPixel(2, 2))
Me.TransparencyKey = img.GetPixel(2, 2)
End Sub
Use TransparencyKey for transparent form.
eg.
TransparencyKey = Color.Red
Button1.BackColor = Color.Red
Now run the form you will find that the button1 has a hole in it.
So using this method you can create a mask image in paint for which part has to be transparent and apply that image to form and voila the form is now transparent.
Edit:
Sorry for late reply.
Following is your code modified to suit your requirement
Public Sub New()
Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
Me.BackColor = Color.Transparent
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Dim img As Bitmap = CType(Me.BackgroundImage, Bitmap)
'img.MakeTransparent(img.GetPixel(2, 2))
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Me.TransparencyKey = img.GetPixel(2, 2)
End Sub
Set Form's TransparencyKey color property same as form's Background color property
There are a few methods you could use.
Use the forms TransparencyKey
Override OnPaintBackground (WM_ERASEBKGND)
Override WndProc and handle the paint messages (WM_NCPAINT, WM_PAINT, etc)
I recommend overriding the window procedure to get optimal results.
Me.Opacity = 0
Be warned that:
This is for the entire form, rather than just the background. There are work-arounds to make certain parts more opague.
It's only psuedo-transparency where it takes a snapshot of what's behind it. It's smart enough to know when you move the form, but not when you move other transparent objects on top of the form.