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.
Related
New to Access (still), have only basic VBA skills.
I've got 3 subforms (subfrm_PackingSteps1 , subfrm_MetalDetection and subfrm_Weights - the first 2 are continuous and the other one is single form) within a main form (frm_daily_packing_record) that users go through and input data. The user should be able to input data in no particular order, and only at the end there would be a button to confirm that the user is ready to save this form.
I'd like to have this button on the main form that checks each control (in main form and subforms) for empty values. I found and adjusted a code to check the recordset of one of the continuous forms (see below), but I can't figure out:
how to include a code that checks each control instead of manually adding all of them (I've used a function before that utilises the Tag property, but can't add it to this)
how to keep the button in the main form while checking the controls/recordsets in the other subforms.
Thanks in advance.
Private Sub ConfirmBtn_Click()
Dim blnSuccess As Boolean
blnSuccess = True
Me.Recordset.MoveFirst
Do While Not Me.Recordset.EOF
If IsNull(Me.pc) Or IsNull(Me.InnerP) Then
blnSuccess = False
Exit Do
End If
Me.Recordset.MoveNext
Loop
If blnSuccess = True Then
MsgBox "You may proceed to save this record"
Else
MsgBox "You still have some empty fields to fill in!", vbCritical + vbOKOnly, "Empty Fields!"
End If
End Sub
I personally don't like this because it is too code-heavy and can easily break when the form is modified.
Instead may I suggest doing it slightly different, for each field have vba code .ondirty or .onupdate and do the validation checking right as the user is actually on that field.
This has 2 benefits, it is creating the validation when you are creating each form field and it STOPS the user right when their first mistake or bad data is entered. The last thing I want is to enter 50 fields, scroll to the bottom, submit fails then scroll back and try to find where the mistake was. If validation is done while the user it doing the actual data entry, when you get to the bottom you should have valid data and the submit should succeed without further testing.
Less code to debug and timely messages to the user if an error is caught!
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 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.
So basically what the title says. I want to make a program where you click a button, and then another button shows up, and then if you click the next button in a certain amount of time you get a point.
This is what I found in another thread, but this also makes the timer count down before the second button even shows up, even though this code is after the code making the next button show up.
Do While DoWhileBool = True
Select Case DirectCast(Sender, Button).Name
Case "ClickHere2"
If TimeCount > 0 Then
MultCount += 1
End If
Case "ClickHere3"
If TimeCount > 0 Then
MultCount += 1
End If
This is not the full code by any means, but I just wanted to show what I tried that doesn't work for having a button click event in an if statement inside another button click method.
Edit: I ended up figuring it out partially but pretty much all of what I was asking thanks to the help of the answer:
NumButTim.Stop()
If TimerVar <> 0 Then
MultCount += 1
MultCounter.Text = MultCount
MultCounter.Refresh()
End If
NumButTim.Start()
TimerVar = 5
'Do Until TimerVar = 0
' TimerVar = Timer1.ToString
' TimeCounter.Text = Timer1.ToString
' TimeCounter.Refresh()
'Loop
End Sub
The commented section was where I was trying to get a textbox to show the countdown time, but it doesn't work. I'm sure I could figure it out if I wanted to, but I've moved on to other things. Thanks to the person who answered it, he probably led me to the right answer.
Sidenote: I don't use visual basic anymore, but the idea I had that this was a part of was sort of a mix of clicker game num pad typing and letter key typing and the typing would increase a multiplier for a while. Never really finished that idea and I don't even know if what I had made in that game even exists anymore because my external hard drive went kaput before I had transferred all the old files onto my current computer.
From what i understand of your question, this is how i would do it:
Add a timer, and 2 buttons to the form
On form load, you want to set the interval on the timer, so something like this:
Timer1.Interval = 1000 'Set the interval to 1 second
Then when you click on the first button show the second button, so on button1 click:
Button2.show() 'Show the second button
Timer1.Start() 'Start the timer, so they have 1 second from now
And in button 2 click, you want to do your event, add a point etc:
points += 1
Then to make the second button dissapear, (timeout) after a certian amount of time, you change the interval of the timer1. If the button wants to show for 1 second, set the interval to 1000 (milliseconds)
Then in timer1.tick add this code:
timer1.Stop() 'Stop the timer so that its not ran again and again
Button2.Hide() 'Hide the second button
MsgBox("You was too slow!!") 'Tell the user they missed it, or your code..
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