basically, I'm using a Graphics class to draw some text on the screen (ProgressBar with text) okay, and I want the given TextColor to blend with the progress bar, so that when the progress bar starts sliding beneath the text, the text color blends with it. (i would assume a form of XOR copying of the color codes, or something to that effect)
Either way, I don't know enough about the GDI in order to get the DrawString() to blend my Text over the dual color background (much they way they do in all setup progress bars etc.)
that sort of helped. I can play with it a bit, but what I'm looking for is this:
Now in my component here is my text code:
VB.NET:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
If m.Msg = 15 AndAlso _showtext Then
PaintText(Me.CreateGraphics())
End If
End Sub
Private Sub PaintText(ByVal dc As Graphics)
Dim pct As String = (Me.Value * 100 \ Me.Maximum).ToString & "%"
Dim sz As System.Drawing.Size = TextRenderer.MeasureText(pct, Me.Font)
Dim pt As New System.Drawing.PointF((dc.VisibleClipBounds.Width \ 2) - (sz.Width \ 2), _
(dc.VisibleClipBounds.Height \ 2) - (sz.Height \ 2))
Dim sb As New SolidBrush(Color.FromArgb(_alpha, _tcol.R, _tcol.G, _tcol.B))
'TextRenderer.DrawText(dc, pct, Me.Font, pt, Color.White)
dc.DrawString(pct, Me.Font, sb, pt)
End Sub
This was quite a hack, because the "OnPaint" method that you can override is only called when ControlStyles.UserPaint is set, which then eliminates the background progress bar and you have to draw it yourself. I didn't want to, so I trapped the WndProc() msg to basically write my "Additional" code for the writing of the text. I've added user selected color and alpha for the text, but in only helps some, it doesn't "invert" the colors as in the above picture.
now If i have to do all the painting to get the same effect as the above image, cest la vie, but I would think that would be unnecessary. I though about trying to do a Region.Xor() but the issue i'm having there is:
Defining a "Memory" region, painting to a "Memory" canvas, etc. In Delphi there was the "Canvas" class which was a memory DC and you could paint to your hearts content, and only when you wanted it visible could you copy it to a screen DC. the Graphics class has no constructors so I can't seem to find a parallel in VB.net.
Anyway, any suggestions would be helpful,
Thanks for your explanation of what you are trying to do. I suspect you have more experience in programming than me, but I have spent a lot of time playing around with GDI+ graphics so perhaps I can offer a few ideas for what they are worth.
1. First of all, in GDI+ you can draw anything to a bitmap in memory. For example:
VB.NET:
Dim bmp As Bitmap
Using g As Graphics = Graphics.FromImage(bmp)
g.DrawImage... and so on
End Using
Then of course you can use the Paint event or the OnPaint method to copy the bitmap to the screen.
2. Some Windows Forms controls, among them ProgressBar, have a DrawToBitmap method which copies the control surface straight into a bitmap. You might find this useful.
3. I can think of several ways to draw contrasting text. For example, you could define a GraphicsPath and use the AddString method to draw the string. Then loop through the path's PathPoints, connecting up the dots with ControlPaint.DrawReversibleLine. My experience with this is that it is complicated, extremely slow and the result is illegible [appropriate smiley].
4. I think the best way to get the effect you want is to use clipping. For example, calculate a clipping rectangle from the ProgressBar's value, width and height. Set the Graphics.Clip to the blue area and draw the text on it in white. Then set the clip the white area, and draw the same text over it in black. Perfect, isn't it? (I hope so, I haven't tried it!)
5. A final note. Results in GDI+ are affected by several graphics properties. The ones you might want to use here are:
For any image which changes rapidly, use Form.DoubleBuffered=True (much easier than SetStyles). Probably it won't matter for the small area of the progress bar.
Have a play with this custom control that inherits ProgressBar:
VB.NET:
Imports System.ComponentModel
Public Class TextProgressBar
Inherits ProgressBar
Private g As Graphics
Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs)
MyBase.OnHandleCreated(e)
g = Graphics.FromHwnd(Me.Handle)
End Sub
Protected Overrides Sub OnHandleDestroyed(ByVal e As System.EventArgs)
g.Dispose()
MyBase.OnHandleDestroyed(e)
End Sub
<EditorBrowsable(EditorBrowsableState.Always), Browsable(True)> _
Public Overrides Property Font() As Font
Get
Return MyBase.Font
End Get
Set(ByVal value As Font)
MyBase.Font = value
End Set
End Property
Private Const WM_PAINT As Int32 = &HF
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
If m.Msg = WM_PAINT Then
TextOverlay()
End If
End Sub
Private Sub TextOverlay()
Dim r1 As RectangleF = Me.ClientRectangle
r1.Width = CSng(r1.Width * Me.Value / 100)
Dim reg1 As New Region(r1)
Dim reg2 As New Region(Me.ClientRectangle)
reg2.Exclude(reg1)
Dim text As String = Me.Value.ToString & "%"
Dim textsize As SizeF = g.MeasureString(text, Me.Font)
Dim x As Single = (Me.ClientRectangle.Width - textsize.Width) / 2
Dim y As Single = (Me.ClientRectangle.Height - textsize.Height) / 2
g.Clip = reg1
g.DrawString(text, Me.Font, Brushes.White, x, y)
g.Clip = reg2
g.DrawString(text, Me.Font, Brushes.Black, x, y)
reg1.Dispose()
reg2.Dispose()
End Sub
End Class
Short explanations; looking out for WM_PAINT messages in WndProc enables to react on the controls otherwise hidden Paint event. An additional graphics instance is created when control has a window handle, and this is used after control has painted the regular bar. As VicJ mentioned the graphics can be clipped for regions, enabling to draw same text with different brushes appearing only in the specified regions. Font property was also unhidden again.
Sample image:
That worked beautifully, and I like the idea of maintaining the graphics handle internally to my stuff instead of always trying to "me.creategraphics()" or listen to the OnPaint method.
Now I'm on to the Marquee mode, I just don't like the way they implement it. But that will be for later.
Thanks!
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.