Array of images VB.NET - vb.net

I am new to VB.NET. I am developing a game in which the user has to guess the name of the image that appears in a picturebox. The user has to enter the answer in a textbox. If it is right, a button appears and changes the image of the picturebox.
I would like the image of the picturebox to change when the next level button is clicked. I want to make an array which will contain all the images with a string as the answer.
How would I go about changing the image to the next in the array after each next level button click?
Thanks

To Load images to array
Dim imgPictures(8) As Image
imgPictures(0) = Bitmap.FromFile("Filename")
To display images.
Dim i as integer = 0
Next Image
myPictureBox.Image = imgPictures(i++)
Previous Image
myPictureBox.Image = imgPictures(i--)
Make sure you are checking for maximum and minimum array values, otherwise you will get indexoutofrange exceptions.

It's hard to tell exactly what parts of the code you need help with, so I'm guessing here. I went in a different direction than #Anuraj, which hopefully is helpful.
Let's say you create an object-based array:
Dim arr(10) As Object
You then create a Sub in your code that will handle the "next level" button's click event:
Private Sub NextLevelButton(ByVal sender As Object, ByVal e As RoutedEventArgs)
'Do Stuff
End Sub
Now replace 'Do Stuff with code that retrieves the next item in the array, and then changes the image in the UI. Obviously, to do this, you'll need to know which item in the array was most recently used. The easiest way to do this is to create a global variable (outside of all subs in your code) which you will replace each time you add a new image to the UI. The value of this global variable will be the index number of the most recently used image in your array. Then, you just increment by one and grab the next image.

Related

How can I create a variable to track which image I have set as the "image" property in a PictureBox?

I am working on creating a short game in which the user moves a picturebox across the form and works toward a set destination. I have been able to change the direction that my character faces on the KeyPress event; however, I am unable to use my timer to animate this picturebox via the changing of an integer variable, and as I am already working inside of the loop that is the timer, I cannot create another loop. As I am a novice programmer, as in extremely new to any coding whatsoever, the method of tracking what picture is currently set in the picturebox is unknown to me, and I have researched it to no avail.
This is how I change the image that initially displays in the picturebox on KeyPress and move the picturebox:
If aKey or leftKey Then
picPlayer.BackgroundImage = My.Resources.PlayerRightStand
'If this is an okay movement, then move
If picPlayer.Left -= speed >= 0 Then
picPlayer.Left -= speed
End If
End If
I have tried this to track what image is currently set as the background of picPlayer:
If picPlayer.BackgroundImage Is My.Resources.playerRightStand Then
image = 1
...etc., but I think there is a gap in my knowledge or a flaw in my logic because I haven't been able to make this work. If anyone can help with this, which I'm sure actually has a very simple answer, I would greatly appreciate your time and answer. Thanks!
What you're trying can't possibly work because My.Resources works by creating a new object every time you access it. That means that even My.Resources.PlayerRightStand Is My.Resources.PlayerRightStand would evaluate to False.
That means that, even your specific issue aside, you should generally not use My.Resources in your general code, but rather assign directly from My.Resources to a field and then use that field in your code, e.g.
Private playerRightStand As Image = My.Resources.PlayerRightStand
That way, you ensure that you only extract that data once and it also means that you can compare the Image property of your PictureBox to that field at any time and get the expected result. So:
If aKey or leftKey Then
picPlayer.BackgroundImage = playerRightStand
'If this is an okay movement, then move
If picPlayer.Left -= speed >= 0 Then
picPlayer.Left -= speed
End If
End If
and:
If picPlayer.BackgroundImage Is playerRightStand Then
image = 1
You might also consider creating an array and putting all your Images in that. You can then use Array.IndexOf to get the index of any specific Image and you might also store the index of the current Image in a field, meaning that you wouldn't have to keep comparing Image references.
I think you should use a variable to store the current status instead of tracking the image. This has a lot of advantages:
You can track a lot of status, even those who are not related to a specific image/animation
You can use the same image for different status
You can code the logic without having all the images/animation, and implement the graphic later
You can change the graphic resources, the images, the names without changing the logic
Since you also have different frames, you may store Arrays as jmcilhinney suggested.
You could use an enum for that:
Public Enum Status
rightStand
leftStand
jumping
crouching
NONE
End Enum
You can store the previous status and the new one (useful to know if you need to change the image, or loop through animation):
Public previousStatus As Status = Status.NONE
Public newStatus As Status = Status.NONE
Then you have the status changing logic (just and example):
Public Sub changeStatus()
If leftKey Then
newStatus = Status.leftStand
ElseIf rightKey Then
newStatus = Status.rightStand
End If
End Sub
And the image modification logic (you'll need more work on this part if you want animations loop):
Public Sub applyImage()
If previousStatus = newStatus Then Exit Sub
Select Case New Status
Case Status.crouching
picPlayer.BackgroundImage = playerCrouching
Case Status.jumping
picPlayer.BackgroundImage = playerJumping
Case Status.leftStand
picPlayer.BackgroundImage = playerLeftStand
Case Status.rightStand
picPlayer.BackgroundImage = playerRightStand
End Select
End Sub

Using a VB.NET variable between different forms

I am trying to use the VB.NET program settings to load a background image for every form every time the form is loaded. So far I've managed to get the program to set the background in one form, and that changes the background for every other form. However, when each form is closed and re-opened while the program is running, the background changes back to the default one. I need to somehow change the background once and load it every time the form is opened, so that it doesn't switch back every time the form is re-opened while the program is running. I think there is some way to do this using the My.Settings in VB.NET, but I'm not sure.
This is the code that changes the background for each form:
Me.BackgroundImage = PreviewBackgroundBox.Image
MainForm.BackgroundImage = PreviewBackgroundBox.Image
LogInForm.BackgroundImage = PreviewBackgroundBox.Image
The PreviewBackgroundBox is used to show the user the image before they apply it, and then when they click apply then the image is taken from the PreviewBackgroundBox and set as the background for all the forms.
Could someone help me with this?
Thanks!
Basically you need a dictionary remembering the image is to be displayed for each form. You could store such a dictionary in a module together with methods to handle the logic involved
Private imageDict As New Dictionary(Of String, Image)
Public Sub SetImage(ByVal formName As String, ByVal img As Image)
imageDict(formName) = img
End Sub
Public Function GetImage(ByVal formName As String) As Image
Dim img As Image
If imageDict.TryGetValue(formName, img) Then
Return img
End If
Return Nothing 'Or return a default image
End Function
Note: Dictionaries store some data and associate it with a key that is used to retrieve this data. Here I would use the form's name as Key. You could also use the form's type GetType(Form1) or Me.GetType() and use a Dictionary(Of Type, Image) instead.
Whenever the user selects another image call SetImage in order to remember it. When a form is opened call GetImage to get the remembered image.

Excel Userform Textbox Constant Set Focus

First of all I would like to thank all of you guys. Maybe you did not notice but you help me to grasp VBA to some level from scratch. I am still in learning process so I may be missing something really simple, please be gentle :)
First of all I would like to give a small backgroud update about my issue. I have been writing a small program to scan incoming parts to my work to be able to keep inventory status. Latest look of the program is like below:
And numbers on the picture are my nightmares lately:
1. Scanned Part Number: This is the textbox where scanner inputs the value. After I receive the input I immidietly convert that data to a variable and clear the textbox value as below:
Private Sub PN_CurrentScan_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Then
EnteredPN = Replace(PN_CurrentScan.Value, Chr(32), "", 1) '<---PN_CurrentScan is the name of text box
EnteredPN = Left(EnteredPN, 12)
PN_CurrentScan.Value = ""
After making some corrections on the scanned data I basically write it to a sheet in the workbook. Then I also have a pivot table in the same workbook which uses this scanned data as source and counts how many parts scanned from each part number.
2. Current Status: This ListBox contains all the part numbers scanned (Coming from the pivot table mentioned above) and waiting to be scanned (Coming from another worksheet). Then it refreshes it self every time a new part is scanned.
3. ListBox Scroll Bar: Since I have very long part number list it is not possible for me to fit everything on the screen that is why listbox creates this scroll bar.
Enough with the background I think :)
So if we come to my concern. Since my collages using cordless scanner to do this operation sometimes they don't have the chance to see the screen so they can not understand if the cursor is on the "Scanned Part Number Text Box" or not. That is why I need focus to be on that box no matter what happens (Of course we can not do anything if warehouse burns down, earth quake or tsunami hits the place but let do not think about those).
WHAT I HAVE TRIED:
First of all I disabled all the remaining objects from properties window
Then I diabled tab stops of all controls:
Dim contr As Control
For Each contr In ScannerInterface.Controls
On Error Resume Next
contr.TabStop = False
Next
ScannerInterface.PN_CurrentScan.TabStop = True
Added setfocus property to all button clicks:
Me.PN_CurrentScan.SetFocus
Added setfocus property to listbox click:
Private Sub CurrentStatus_List_Click()
Me.PN_CurrentScan.SetFocus
End Sub
Added set focus to enter and exit events of listbox however this did not work:
Private Sub CurrentStatus_List_Enter()
Me.PN_CurrentScan.SetFocus
End Sub
Private Sub CurrentStatus_List_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Me.PN_CurrentScan.SetFocus
End Sub
So, with all these counter measures I have managed to improve up to somepoint, only concern remaining is when I click on the scroll bar next to the listbox, text box lose focus and without clicking in the textbox I could not manage to set the focus again. I tried all events with listbox non of them worked. Is there any way to solve this problem or do I need to deal with this? Thanks in advance for your supports.
SOLUTION:
Thanks to #Rory we have managed to solve my problem. As he noticed and explained in the answer below, both my textbox and listbox were in frames. I have tried several setfocus options but I always gave the focus to the textbox. However, solution was to give the focus to the frame which was containing the target textbox:
Private Sub CurrentStatus_Frame_Enter() '<-- Enter event of the frame which contains listbox
Me.PN_CurrentScan.SetFocus '<-- Setfocus to target textbox
Me.Scanned_Frame.SetFocus '<-- Setfocus to frame which contains target textbox
End Sub
Having (eventually) noticed that both of your controls are inside container Frame controls, you can actually use the Enter event of the Frame that contains the listbox to set focus to the Frame that contains the textbox, rather than to the textbox itself.

Get Picture from Worksheet into Excel Userform

I am looking to view an image from the worksheet in an Image control on a userform.
This image will change based on the value on a combobox. I have inserted (Using: Insert -> Pictures) a couple of images into "Sheet1" of my workbook and named them "Picture1" & "Picture2".
I have created the below UserForm:
Form http://im56.gulfup.com/msKyqi.png
And this is the code that I am trying to use in order to load the images from the sheet, but unfortunately, this is not working at the moment.
Private Sub ComboBox1_Change()
UserForm1.Image1.Picture = LoadPicture(Worksheets("Sheet1").Shapes(ComboBox1.Value))
End Sub
Private Sub UserForm_Initialize()
UserForm1.ComboBox1.Clear
UserForm1.ComboBox1.AddItem "Picture1"
UserForm1.ComboBox1.AddItem "Picture2"
UserForm1.ComboBox1.Value = "Picture1"
UserForm1.Image1.Picture = LoadPicture(Worksheets("Sheet1").Shapes(ComboBox1.Value))
End Sub
Every time I run this code I get the below error:
Error http://im43.gulfup.com/YoWvTp.png
Please advise.
I figured it out!
As I am using a UserForm there is a workaround to the issue.
Instead of having the images in the worksheet to then try and load them in the form I tried having them in the UserForm in the first place, here is how.
Create a frame on your userform:
Frame http://im88.gulfup.com/Moy8I6.png
Set the visible property of the frame to "False":
Visible http://im88.gulfup.com/sAIQqh.png
Insert your images by adding a picture control and loading the images, you can add as many images as you need:
Images http://im88.gulfup.com/oas0EQ.png
Name the images:
Name http://im88.gulfup.com/cIO317.png
Drag all the images one over the other into the frame, (you can then move the frame into a corner so it doesn't bother you:
Drag http://im88.gulfup.com/1fOSut.png
Move Away http://im88.gulfup.com/Q1fzKd.png
Next create a picture control, this is what you will use to display the picture based on a selection:
Form View http://im88.gulfup.com/X1UVRB.png
In this example, I am going to use a combobox for the selection. Now insert the below code in to the form which is pretty straight forward:
Private Sub ComboBox1_Change()
' Image1 is the name of the created picture control
UserForm3.Controls.Item("Image1").Picture = UserForm3.Controls.Item(UserForm3.ComboBox1.Value).Picture
End Sub
Private Sub UserForm_Initialize()
UserForm3.ComboBox1.AddItem "Argentina"
UserForm3.ComboBox1.AddItem "Brazil"
UserForm3.ComboBox1.AddItem "Chile"
End Sub
As you will see, the frame with the pictures is Hidden, and the image is changing inside the picture control based on a selection:
Result http://im88.gulfup.com/MSqyHF.png
I think it's the better way to go as opposed to exporting the images from the worksheet to a Temp folder and then loading them back into the picture controls.
The LoadImage() function expects a filename (which can be fully qualified with a drive letter and path). You are getting a type mismatch because it wants a string, and you are giving it an image object.
There is, as far as I know, no simple way to put an image that resides in the current application into an image control. The (hackish) workaround that I know about is to export the image to a file, and then import that same file using LoadImage().
This is the same path you have to go down if you want to embed a chart that updates dynamically into a userform. You export the chart as an image (e.g., a JPEG), and then use LoadImage() to pull the image back into the image control.
I know this post is ancient, but I found my way here. I came up with a slightly different solution to this problem. I have about 30 pictures I need to load based on a combo-box selection. First, all combo-box options (for discussion "XX") are saved to a separate worksheet which is "Very hidden" from the user and loaded into the combobox on userform activation. On the userform a frame was added, and within the frame 30 image-boxes all overlapping perfectly were placed. Each image-box was carefully named "Img_XX" where XX is the simple two-letter identifier.
With this setup it is now possible to iterate through each "Control" (the image boxes) in the Frame and hide them all, except the one with a name that matches the combo-box value. The code in the userform module, within the Combobox_Change() function, looks something like this:
Private Sub ComboBox_Change()
Dim SearchValue as String
SearchValue = me.Combobox.value
Dim Ctrl as Control
For each Ctrl in Me.TestFrame.Controls
If Ctrl.Name Like "img_" & SearchValue Then
Ctrl.visible = True
else
Ctrl.Visible = False
End If
next Ctrl
End Sub
I hope this helps, let me know what you think. :)

How do I print just one or two controls instead of the whole form in Visual Basic

I have a program that gives the user driving directions, I would like the user to be able to print just the directions or just the directions and a map by selecting a corresponding radio button for each option. How can I print just these sections and not the whole form? And how can I use the radio buttons to tell it what to print? Thanks
Updated code:
Private Sub btnprint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnprint.Click
If rbprintall.Checked = True Then
'Ad code to print all here
ElseIf rbprintdirections.Checked = True Then
lbldirections.DrawToBitmap()
lbldirections2.DrawToBitmap()
lbldirections3.DrawToBitmap()
lbldirections4.DrawToBitmap()
Else
MessageBox.Show("You must select one of the above options!")
End If
If you're using Windows Forms, almost all of the built-in controls can be easily rendered to an image using their DrawToBitmap method. If you simply want to print whatever is currently displayed by a control, this is the easiest way to do it. Do note, however, that there are a couple of caveats to what can be drawn this way. See the linked documentation for details.
Printing in the .NET Framework is also made relatively simple by taking advantage of the functionality provided in the System.Drawing.Printing namespace. If you aren't already experienced with this, Google for some tutorials. For example, there's a pretty good article here from the MSDN Magazine.
So, to accomplish your ultimate goal, you'll need to do the following:
When the user clicks "Print", determine which radio button is currently selected.
Create a temporary bitmap and grab a copy of the appropriate control in that bitmap using the control's DrawToBitmap method. (If you need to print multiple controls, create a separate temporary bitmap for each of them, and then print each of them in the next step.)
Draw that image to the printer using the Graphics.DrawImage method in the PrintPage event handler method for a PrintDocument object you've created.
EDIT: I'm not really sure where your question is with regards to the code that you've posted, but I see two primary problems.
In the first block of your if statement, the comment suggests you don't know how to print all of the controls. You have a couple of different options. If you just want to print every control on the form as it appears, you can simply use the DrawToBitmap method of the Form itself. That will create a bitmap of the form's entire client area, including all of the controls it contains.
If there are still some controls on the form that you don't want to print, even when the user chooses "Print All", you'll need to call the DrawToBitmap methods on each individual control. You might set up a loop so that you don't have to write a line of code for every control, but there's not really another good option.
I suspect you're going to have problems with the second elseif block working as you expect it to, also. Recall that I said above you need to create temporary bitmap images, and then draw into those bitmaps? The DrawToBitmap method takes two parameters:
bitmap: a System.Drawing.Bitmap that you want an image of the control to be drawn into
targetBounds: a System.Drawing.Rectangle that describes the bounds of the control that will be rendered
The code you've shown is missing both of those parameters. In this case, the second (targetBounds) is simple—because you want to draw the entire control, all you need to do is specify it's ClientRectangle property for that parameter.
For the first (bitmap) parameter, you need to do as I mentioned above and create a new Bitmap image by declaring a temporary variable. Then, you need to call the DrawToBitmap method with this temporary bitmap specified.
Maybe I can be clearer with an example. Modify your above code to look like this:
'Declare some class-level variables to hold images of the controls to print
Private bmpDirections1 As System.Drawing.Bitmap
Private bmpDirections2 As System.Drawing.Bitmap
Private bmpDirections3 As System.Drawing.Bitmap
Private bmpDirections4 As System.Drawing.Bitmap
Private Sub btnprint_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnprint.Click
If rbprintall.Checked = True Then
'Add code to print all here
ElseIf rbprintdirections.Checked = True Then
'Draw lbldirections control to bitmap variable named bmpDirections1
bmpDirections1 = New Bitmap(lbldirections.Width, lbldirections.Height)
lbldirections.DrawToBitmap(bmpDirections1, lbldirections.ClientRectangle)
'Draw lbldirections2 control to bitmap variable named bmpDirections2
bmpDirections2 = New Bitmap(lbldirections2.Width, lbldirections2.Height)
lbldirections2.DrawToBitmap(bmpDirections2, lbldirections2.ClientRectangle)
'Draw lbldirections3 control to bitmap variable named bmpDirections3
bmpDirections3 = New Bitmap(lbldirections3.Width, lbldirections3.Height)
lbldirections3.DrawToBitmap(bmpDirections3, lbldirections3.ClientRectangle)
'Draw lbldirections4 control to bitmap variable named bmpDirections4
bmpDirections4 = New Bitmap(lbldirections4.Width, lbldirections4.Height)
lbldirections4.DrawToBitmap(bmpDirections4, lbldirections4.ClientRectangle)
Else
MessageBox.Show("You must select one of the above options!")
End If
End Sub
The only thing to remember is that you need to call the Dispose method on each bitmap variable when you are finished using it. The Dispose method "releases the resources owned by the image", which means that it frees up the memory it was using. There's no reason to keep those large-ish images around if you're not going to use them again. So, you should probably do this after the print job is completed. Once you dispose the bitmap object, you will no longer be able to use the image it contained, but you can always create a new bitmap object and assign it to the variable (as shown in the above code) the next time the user clicks print.
Unrelated: There's no reason to test for If x = True. The simpler If x is the same thing, and considered by most programmers to be better style. Effectively, you're doing a double comparison against True, which isn't necessary.