Note: This question is created to help others find what I could not find, having said that anyone is welcome to propose a better solution than I came up with.
My challenge was to produce a smooth scrolling text stream on a windows form application, in addition the form had other items drawn on it so I had to avoid destroying them in the process.
I tried moving a text box incrementing it with timers and do...loops and so on, also tried using Graphics.DrawString again incrementing the position.
All of them produced a jerky output with the text flashing as it moved.
I Spent several hours googling and browsing probably in the region of 50 different proposed solutions including many in other languages in the hope I might get a clue!
I can't identify which one gave me the clue but I saw several references to Doublebuffer so I googled that (and tried it without sucess!) and finally came up with the idea from here of a manual buffer so I ended up with....(see answer below)
Do
Dim currentContext As BufferedGraphicsContext
Dim myBuffer As BufferedGraphics
' Gets a reference to the current BufferedGraphicsContext.
currentContext = BufferedGraphicsManager.Current
' Creates a BufferedGraphics instance associated with Form1, and with
' dimensions the same size as the drawing surface of Form1.
myBuffer = currentContext.Allocate(BNP1.CreateGraphics, BNP1.DisplayRectangle)
'update test
With myBuffer
.Graphics.Clear(Panel.BackColor)
.Graphics.DrawString("Some Text", [Your Font], Brushes.Blue, xpos, ypos)
End With
myBuffer.Render()
myBuffer.Dispose()
'This bit will need adjusting to suit your layout!
If xpos + Panel.Width < Panel.Left Then xpos = Panel.Right Else xpos -= 1
Thread.Sleep(1)
Loop
This produced a perfectly smooth scroll with a fully adjustable scroll speed using the sleep time and xpos reduction.
As you will probably notice I did this with a Do...Loop in a separate thread it also works in a timer but the scroll speed for some reason (someone can probably explain) is much slower.
Disclaimer: I am not a professional coder so if anyone has suggestions to improve what I have done I will greatly appreciate it (avoid generics such as Option Strict - already on!)
Related
I desperately need help with a game I am making. For a bit of context, i am making a memory game and i have the following piece of code that is being troublesome. I have a bunch of labels on the form, 16 to be exact, with 1 randomly generated symbol placed in each. Each symbol appears in the labels twice.
------------------------------Continued----------------------------------------
'MsgBox("hello") 'used to check if the second inccorect press shows up - it does show but instantly changes colour
'''''''''''''''''NEED SOME CODE THAT PAUSES IT HERE'''''''''''''''
labels(0).ForeColor = Color.DarkRed
sender.ForeColor = Color.DarkRed
End If
flips = 1
End If
End If
tmrmemory.Enabled = True ' starts the timer after the user clicks the first label
End Sub
What's supposed to happen is that when the labels clicked don't match, it should show both the clicked labels for a short period before changing them both back to "DarkRed" which is the colour of the form's background.
I have tried using a timer but then i can't use sender.forecolor=color.darkred because it is not declared globally.
I have also tried using the command Threading.Thread.Sleep(500) but it still doesn't show the second incorrect click. I know that the code i have used works because when i use the message box, i can see both symbols and when the two clicks are correct, it stays.
Threading.Thread.Sleep(500) will actually pause your code for half a second. However during this time it won't do anything, not even refresh your controls. To get the effect you want, you need to call the YourControl.Refresh method before calling Threading.Thread.Sleep to force the control to redraw immediately.
On a side note, I would advise you not to call Threading.Thread.Sleep on UI thread. It will give a feeling of program hang. Instead do your work on a separate thread. You can either do all the work yourself right from creating a separate thread to destroying it, or use the BackgroundWorker control which has all the functionality built in.
Here is the link to an article I wrote a long time ago regarding BackgroundWorker that might be useful for you:
http://www.vbforums.com/showthread.php?680130-Correct-way-to-use-the-BackgroundWorker
Declare a variable outside the sub that stores what label should be flipped when the timer ends.
Label click sets
storedLabel = sender
Timer tick sets storedLabel.ForeColor = Color.DarkRed
I am writing a program, to read a log out to the screen, from a remote server.
the Program adds 1 line to the bottom for each new package is recieves.
Currently i am using a TextBox for the speed, as i get about 600-2200 packages each minutes, and the RTB simply can't follow.
i remove the top line, when the lines[] exceeds 300 lines, to reduce memory usage, and speed reduction.
Problem is i really want the lines color formatted, so its easier to see what it outputs, as the stream goes too fast for most human eyes.
as fare as i know, there is only the Select methode to color text in RTB, however i was wondering, if there was any component that is better to use, then the standart RTB, that was more reliable, then the RTB?
I think the best solution would be to have an intermediate buffer (queue) to store the information gathered from the packages.
Dim _buffer as New List(Of String)
When a new package arrives add it to the end of the buffer:
_buffer.Add("package contents")
Then you could use a timer to read out the contents of the buffer every half a second and colourize the textbox.
Private Event Timer_Tick
Do Until _buffer.Count = 0
rtb.Text += _buffer(0)
'colourise the textbox
_buffer.RemoveAt(0)
Loop
End Sub
You may run into problems reading and writing to the buffer on separate threads in which case you could try using SyncLock but this may get you going for now
I am upgrading user control from vb6 to vb.net.
In the vb6 application I am loading 3000 labels using a label control array.
In vb.net I am doing same but it's taking too much time to load.
In vb6 it's taking 1-2 seconds, but in vb.net it's taking 30-40 seconds for same work.
What is problem? Why does it take too much time in vb.net for same work?
Code is given below, here Led is the label control array.
For l = 1 To 3000
Led.Load(ledCounter)
ColLed.Add(Led(ledCounter))
Led(ledCounter).BackColor = System.Drawing.ColorTranslator.FromOle(LedColor)
Led(ledCounter).Top = VB6.TwipsToPixelsY(15)
Led(ledCounter).Left = VB6.TwipsToPixelsX(15)
Led(ledCounter).Height = VB6.TwipsToPixelsY(LedHeight)
Led(ledCounter).Width = VB6.TwipsToPixelsX(LedWidth)
Led(ledCounter).BorderStyle = Windows.Forms.BorderStyle.None
Led(ledCounter).BackColor = System.Drawing.ColorTranslator.FromOle(LedColor)
Led(ledCounter).Visible = True
Next
In VB6, a label is a windowless (lightweight) control. It doesn't have a window handle and therefore does not exist as far as the OS is concerned. The code behind this control just checks where the mouse is and does some drawing on the parent control.
In VB.NET, however, a label is a full-fledged control that has a window handle and therefore "exists." Creating several thousands of these is a bad idea, because number of available window handles is limited (and because it's slow).
You should revise your design and consider using a grid of some sort.
I am currently in the process of making a snake game using VB.NET... I was just wanting to gather ideas on how to do the body of the snake...
Currently I have a class called SnakeBody which contains the following code:
Public Class SnakeBody
Dim yCoord As Integer
Dim xCoord As Integer
Dim body As PictureBox
End Class
I guess what I am asking is if Dim body As PictureBox a logical thing to put in my class. As in, I am not sure if that is the correct thing to do? To create the actual body of the snake I will have an array of these SnakeBody objects.
If `'Dim body As PictureBox is valid How do I reproduce the same picturebox everytime my snake eats something?
I hop this makes sense... Thanks Alot
Well, it is okay but it is not going to work well in practice. PictureBox is a window, when snakes overlap each other, you'll obscure part of them with a rectangle. You'll essentially see one snake in a rectangle with bits of other snakes peeking out past that rectangle.
Use the form's Paint event to draw the snakes, don't use a control.
Don't use Winforms. Use vb.net and silverlight, you can design a template for the snake , you have silverlights sophisticated built in animation. It will be so much easier and better and it will run on a PC and Mac.
actually i don't know how to add a cube when the snake eat something
try to use System.drawing.graphics to draw cubes ( parts of the snake ) : it's a bit easier
if you want to make the snake moving you should make a script based on this :
REMEMBER : THIS IS ONLY A DIMOSTRATION OF WHAT HAVE THE CODE TO DO :
Dim CubeSelected as integer = 1 ' Selected cube
loop {
if right_key_pressed{
' You have to make this command : cube(number of the cube , direction)
cube(CubeSelected,right) ' Change the selected cube direction
MoveSelect = MoveSelect + 1 ' Select the next cube
Threading.Thread.Sleep(500) ' Wait
}
}
if you press the right key , the cubes will change the direction one for time .
So the snake will make a curve and proceed to the right direction
it's a little more complicated actually , but i hope it helps
This really shouldn't be hard, I just can't figure out how to do it.
I am making a proposal report that needs to have a border around it. The problem is to get the vertical lines on the side. I can't figure out how to get a line to grow and shrink based on the height of the detail section.
I have used Crystal reports and sure wish Microsoft would learn a few things in regards to MS Access report writing!
I am very comfortable with VBA so have no fears there.
You were right, this isn't so hard. The trick is to use 2 variables, top and bottom. In the PageHeader_Format event you set top to Me.Height, and in the PageFooter_Format event you set the bottom to Me.Top - correction, where correction is a fixed amound you use to fix the right length. I´m not sure where this amount comes from, you just have to try a little bit.
In the Report_Page event you can then draw your line from top to bottom.
Another method that nobody has mentioned is the one using the Line method of the report, outlined in Knowledge Base article 210321. I've used this one for years, and it can be used to draw both lines and rectangles. It's quite handy for invoices that have variable height subreports for the invoice details, but need the vertical lines to change according to the height of the main report detail.
No VBA needed.
Make a dummy grouping that is unique to each detail. For that grouping, set footer to yes.
In your new group footer section that you just created, add your line.
In your detail section, select all the relevant fields that can grow and set Can Grow = Yes
Done!
Edit
Off-topic, I agree that Access Reports could learn a lesson or two from Crystal. But Crystal isn't perfect either. [/flamewar]
Try this one.
Right click on the detail bar and select properties. Set the special effect to “Sunken”. This will put kind of a border around the detail section that resizes with the detail section.
I have tried to get a line to dynamically resize but its catch 22, by the time you know the height of the section (In the On Print event) you cant make any changes!
use the page event coupled with me.line and scaleheight / scalewidth.
I draw a box around the whole page with the following. Play with it and see where you end up. It is very handy for making professional reports. If you want a line in a certain place on a report you can use the controls coordinates. like
me.line(Mycontrol.left,mycontrol.top) - (myothercontrol.left+myothercontrol.width, myother control.top + myothercontrol.height)
Private Sub Report_Page()
Me.Line (0, 0)-(scalewidth -30, scaleheight-30), 0, B
End Sub