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
Related
I have a problem with the snippet of the code I have got to extend and improve. It is not my original code and I cannot change the logic that much of it, just to be clear.
I have one main form called MDIServer, which has a timer set for every second. In Timer.Tick I have some other code which works fine (timer is running okay). Newly, I had to check there, if one form is Active and if so, change some stuff (labels text and tags) in that form and refresh it.
I add there this code:
If IsActiveForm("frmName") Then
frmName.ChangeSomething()
End If
The Sub ChangeSomething is, how you can see, located in the form I want to refresh and do the changes. In that function I simply change the label text and tags of few controls.
My question is: Form is not refreshing => labels are not visible changed, why?
I think I tried already almost anything with Refresh() function in the ChangeSomething() function or in the timer after I called this function. Also I tried to add there new timer (in frmName) and do the changes there, which works perfectly with
Label.Text = "something new"
Label.Refresh()
So I guess problem is somewhere with the refreshing form from Timer in different form. I also tried to do it with my own InvokeReguired() function etc...
P.S. When I am debugging the code, labels and tags are changing and every single function which has to be called, is called, but it is just not visible on the form itself.
EDIT Info
formName is not declared in MDIServer explicitely and in this case and many other cases, forms are used as default instances. Timer is from System.Windows.Forms.Timer. Also MDIServer is not a MDIParent of the formName and I cannot use Me.ActiveMdiChild Is. Lets just say, these two forms are not dependent on each other in any way.. and everything is done through name of the form (default instance, so nothing like Dim frm As Form and frm = frmName).
I would be really glad for any tip or anything :D
Thanks guys,
Vojta
So, I fixed my problem after some research and the problem was (expected) that I am not calling the subroutine ChangeSOmething() for one specific instance of the form frmName. So I had to change my code, that I will call it exactly for the instance which is active and visible.
New code looks like this:
Dim frmCollection = Windows.Forms.Application.OpenForms
Dim listfrmname = frmCollection.OfType(Of frmName).ToList()
If listfrmName.Count > 0 Then
Dim tmpFrm As frmName = listVZT15.Last()
tmpFrm.ChangeSomething()
End If
I also could not use combination of frmCollection.OfType(Of frmName).Any and frmCollection.Item("frmName"), because when I was closing the form and opening again, it created new and new instances (I dont know, why it is not closing the old one, but like I said, it is not my code). So the logic is, to list all open forms of the needed type, and then take the last instance from that list and for that instance call the subroutine. Also Me.Refresh() is placed in the subroutine ChangeSomething() itself.
Thanks everyone for help, it surely helped me to understand, how the instances works here.
I have a simple userform for entering data into a macro:
Everything works fine, except for one thing - I want the commandbuttons at the bottom to get focus, after the textboxes are populated from a different form which pops up when either textbox is clicked.
Stepping through the code this does indeed happen, but somehow focus is returned to the textbox before the code ends.
Googling about a bit, it seems that the issue may be that there is a frame around the textboxes, but I can't find any way to actually solve the problem.
The code for the two textboxes is next to similar, and looks like this:
Private Sub tbxTil_Enter()
DATA_TO_CALENDAR = Me.tbxTil.Value
DatePickerForm.Show
Me.tbxTil.Value = Format(DATA_FROM_CALENDAR, "dd.mmm. yyyy")
If Me.cmdOk.Enabled Then
Me.cmdOk.SetFocus
Else
Me.cmdAvbryt.SetFocus
End If
End Sub
Assuming the problem is what I believe it is, is there any way to set the focus to an element outside the frame you are currently in? If not, what is the actual issue with my code?
I had searched a lot how to display a Msgbox that will not wait the user input (pressing ok or cancel).
I found 3 solutiuons to this.
1- Display the MsgBox() in another thread or using BackgroundWorker()
2- Create a form that display the message, then closed the form by a timer and use it instead of Msgbox()
3- Using the API MessageBoxA()
Let say I have a loop from 1 to 100, and I want display a message for the i(counter)
When I test above 3 ways, I found that this is not the right way of doing it, I don't need a msgbox() to close by it self after showing the message, because that will display 100 dialog.
What I realy want is to display ONLY 1 MsgBox() and change the text accordingly.
I managed to do this using a a Form() as class and I did it using Application.DoEvents
I know it can be done using BackgroundWorker or Threading since alot of people advice against using Application.Doevents
Here is my code
Dim oWW As New WaitWindow With {.TopLevel = True,.TopMost = True,.StartPosition = FormStartPosition.CenterScreen}
oWW.Show(Me)
For i = 1 to 100
Threading.Thread.Sleep(500) ' Just to slowdown execution
oWW.SetMessage("Counter = " + i.ToString)
Next
oWW.Dispose()
Public Class WaitWindow
Sub SetMessage(ByVal Message As string)
lbl_message.Text = Message
Application.DoEvents
End Sub
End Class
WaitWindow is not more than a Form base class with a label (lbl_message)
That code works fine (display WaitWindowForm on center of currently displayed form only once, then I change the text)
I have 3 questions :
1- How to display the WaitWindowForm in the top right corner of my working form?
2- Is it possible to display the normal MsgBox() or MessageBox.Show() only once, then capture the text displayed and change it?
3- Which one is suitable for my issue (BackGroundWorker or Threading) and what the code in WaitWindow class I post will be if I decided to use Backgroundworker or Threading instead of Application.DoEvents (Changing the label text not showing new form with new text) ?
3 questions in one post.. humm.. who cares, I am not the one who will answer lol :)
Thanks in advance.
I think the issue that you're really encountering is that you're trying to use a message box for something it's not suited for. If you want to have text that constantly changes just add a text box in the upper right corner of your application and adjust it every time a new message needs to be shown.
You can also look up dialogu windows (search ".showdialog() vb.net" in google) might help as well.
I have the below snippet of code:
'Handle level specific properties
Select Case ScoreCard.CurrentDifficulty
Case 1
intImageCount = 2 'This is the number of images to show at any given time on screen +1
'debug
ScoreCard.CurrentDifficulty = 6
Case 2
intImageCount = 3 'This is the number of images to show at any given time on screen +1
Case 3
intImageCount = 5 'This is the number of images to show at any given time on screen +1
Case 4
intImageCount = 2 'This is the number of images to show at any given time on screen +1
Case 5
intImageCount = 5 'This is the number of images to show at any given time on screen +1
Case 6
frmLevel3_HouseOfMirrors.Show()
Me.Close()
Return
End Select
When case 6 is executed frm3_HouseOfMirrors.Show() executes and my new form opens. Me.close executes as well but my problem is that the script then gets to the return line. Isn't me.Close() suppose to stop all execution of code on the current form and unload its self from memory?
Just call frmLvl3_HouseOfMirrors.ShowDialog() instead of .Show(), this will stop the execution of code until the new form is closed.
Or if you want to cancel the execution of the rest of code try the Exit instruction. You have to detect you want to finish and add it outside this Sub, because .Close() didnt stop the execution of code.
No, the "close" method just closes the form, but the program execution will continue. If you want to stop code execution until a form is closed, you could make it modal.
In VBA it would look like this:
frmLevel3_HouseOfMirrors.Show vbModal
Isn't me.Close() suppose to stop all execution of code on the current form and unload its self from memory?
No. Close does exactly what it says: it closes the visual, interactive representation of the form.1 It doesn’t affect code execution directly. It does make sure that Form_Closing and then Form_Closed are called, however. But the rest of the code execution is unaffected; in particular, the current method runs through normally. After that, other methods on the form may or may not be called as necessary (and, as mentioned, Closing and Closed will be called).
1 And, yes, it releases the form’s resources unless the form was shown via ShowDialog rather than plain Show.
I have a form with a few buttons which execute code when pressed like running validations on the database.
Some code can run for a few minutes so is there any way to show the time remaining or a message to display the % of process completed?
Or pop out a message when code evaluation starts and the message should disappear once code running is completed?
What you are probably looking for is a "Progress Bar".
I've used the Microsoft ProgressBar control (you can find it under Insert->ActiveX Control), and it's not that hard to use. Just set the value of it to a percentage (as an integer, not a decimal).
'foo, being the ProgressBar
me.foo = 70 '70%
There is some good info here on another method: http://www.granite.ab.ca/access/progressbar.htm
In order to do this the "normal" way, you'd need to run your validation in another thread and have it report its progress back to the UI thread. However, I don't believe VBA supports any kind of multithreading.
If your validation routines involve a loop, or even just many separate discrete operations, you can try inserting a DoEvents statement in between loop iterations (or operations), and then have your progress display updated periodically (say, in an Application_OnTime event handler).
I usually have a form I name frmProgress or whatever, with a cancel button and a label for displaying a status message. Then embedded in the form code I have a boolean called bCancel, and when you hit the cancel button it simply sets bCancel as true.
Also in this code I have a routine called ShowPercDone( Idx , NumIdc ) where Idx is the step the code is on, and NumIdc is the number of steps the code will take (assuming each step takes the same amount of time). This works well when I'm running through a for loop, but basically any time I want to display a status update I just call the routine in the form with my message, which I should add runs the doevents command for me.
So that's how the status form works. In the macro I run, I start out by just calling frmProgress.show (0) so that it lets you click the cancel button. Then in my loop when I update the status message I then check frmProgress.bCancel and if it's true I exit out of the macro.
Hope that helps.
Finally to be simple i decided to use the method given here
http://oreilly.com/pub/h/3330#code