{"id":6263,"date":"2007-04-23T16:05:00","date_gmt":"2007-04-23T16:05:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2007\/04\/23\/controls-on-the-fly-matt-gertz\/"},"modified":"2024-07-05T14:47:46","modified_gmt":"2024-07-05T21:47:46","slug":"controls-on-the-fly-matt-gertz","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/controls-on-the-fly-matt-gertz\/","title":{"rendered":"Controls on the fly (Matt Gertz)"},"content":{"rendered":"<h2><font face=\"Cambria\" color=\"#365f91\" size=\"5\">Controls on the fly (Matt Gertz)<\/font><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">So last week, I posted up a simple \u201cMaze\u201d game, in which you navigate through a virtual environment similar to the old \u201cMyst\u201d game.<span>&nbsp; <\/span>The way I\u2019d coded it, though, it didn\u2019t actually have any \u201cgame\u201d to it \u2013 you just walked around.<span>&nbsp; <\/span>In this post I\u2019ll add some state to it (which, after all, is pretty much all that defines a game, beyond being fun) &#8212; things to interact with.<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">There are a number of ways I could implement environmental objects in the game, but I think I\u2019ll take this opportunity to discuss how to add controls on the fly.<span>&nbsp; <\/span>I could add a bunch of controls to my form and just make them visible or enable them as needed, but that could be a lot of controls on the form that generally aren\u2019t being used <span>&nbsp;<\/span>&#8212; creating controls as needed makes better sense.<span>&nbsp; <\/span>Creating a control on the fly is incredibly simple in Visual Basic, and it\u2019s also very easy to handle events on those controls.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">First, let\u2019s check to see if we need to add a control.<span>&nbsp; <\/span>In the previous code, I had an empty method called \u201cAddExceptionalInfo,\u201d called on each transition, which we\u2019ll fill up now.<span>&nbsp; <\/span>Let\u2019s say that, when the user gets to square (1,1) and looks down (regardless of his\/her compass orientation), they\u2019ll see a gerbil.<span>&nbsp; <\/span>(Please note that I don\u2019t have a gerbil fixation; it\u2019s just that the GIF was handy from my post two weeks ago.)<span>&nbsp; <\/span>So, we start out with:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> x = 1 <span>AndAlso<\/span> y = 1 <span>AndAlso<\/span> z = 0 <span>AndAlso<\/span> att = Attitude.Down <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Now we\u2019ll add the gerbil:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> gerbilPictBox <span>As<\/span> <span>New<\/span> PictureBox<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>gerbilPictBox.Image = <span>My<\/span>.Resources.walter1<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>gerbilPictBox.Left = 400<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>gerbilPictBox.Top = 400<\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">The control exists, but is not on the form yet.<span>&nbsp; <\/span>To do that, we just execute the following lines of code:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Me<\/span>.Controls.Add(gerbilPictBox)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>gerbilPictBox.BringToFront()<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">which adds the gerbil to the form and makes sure that it\u2019s on top of the navigation labels.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">So far, so good.<span>&nbsp; <\/span>If you navigate to (1,1) and look down, you\u2019ll see a gerbil.<span>&nbsp; <\/span>However, when you look up again, the gerbil is still in front of you, floating in mid-air!<span>&nbsp; <\/span>Clearly, we need to get rid of the gerbil when we\u2019re looking in a different direction.<span>&nbsp; <\/span>Fortunately, I can navigate through my list on controls and get rid of the inappropriate one.<span>&nbsp; <\/span>I\u2019ll add the following code to the top of the same method:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; First, clean up any controls left behind:<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> oldControls() <span>As<\/span> Control<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>oldControls = <span>Me<\/span>.Controls.Find(<span>&#8220;TempGerbil&#8221;<\/span>, <span>True<\/span>)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> oldControls.GetLength(0) &gt; 0 <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Me<\/span>.Controls.Remove(oldControls(0))<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>If<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">which will look through the form\u2019s controls, return an array of any that have the key \u201cTempGerbil,\u201d<span>&nbsp; <\/span>and then remove the first element from that array (which should only have one element anyway if I\u2019ve done my job properly \u2013 in shipping code, I\u2019d add a check here to make sure).<span>&nbsp; <\/span>Then, in the code where I create the gerbil, I just add the line:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>gerbilPictBox.Name = <span>&#8220;TempGerbil&#8221;<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">so that the previous code will find it when entering the function.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">So, now the gerbil will only appear when you look down in (1,1), and will go away when you look up.<span>&nbsp; <\/span>But, let\u2019s say that it\u2019s important to the game to collect the gerbil.<span>&nbsp; <\/span>(This is starting to sound a lot like \u201cZork,\u201d I realize\u2026)<span>&nbsp; <\/span>To support that, we\u2019ll need to handle events on the gerbil.<span>&nbsp; <\/span>First, let\u2019s create a state variable as a member of the form:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> hasGerbil <span>As<\/span> <span>Boolean<\/span> = <span>False<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">And we\u2019ll add an event handler which changes the state when the gerbil is acquired (i.e., double-clicked):<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Private<\/span> <span>Sub<\/span> Gerbil_DoubleClick(<span>ByVal<\/span> sender <span>As<\/span> <span>Object<\/span>, _<\/span><\/p>\n<p class=\"MsoNormal\"><span>ByVal<\/span><span> e <span>As<\/span> System.EventArgs)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Me<\/span>.hasGerbil = <span>True<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Me<\/span>.Controls.Remove(sender)<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Note that I don\u2019t have to search for the control to remove, since the value of \u201csender\u201d is the control that fired the event, which will be the gerbil control.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Now, we\u2019ll update our gerbil creation code so that we don\u2019t see a gerbil if we\u2019ve already picked it up:<\/font><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> x = 1 <span>AndAlso<\/span> y = 1 <span>AndAlso<\/span> z = 0 <span>AndAlso<\/span> att = Attitude.Down <span>Then<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> hasGerbil = <span>False<\/span> <span>Then <\/span><span>&#8216; Have we already picked it up?<\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">And finally, to connect the double-click event handler to the gerbil control, we just need one line of code in the gerbil creation code, right before we add it to the form:<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>AddHandler<\/span> gerbilPictBox.DoubleClick, <span>AddressOf<\/span> Gerbil_DoubleClick<\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">And that\u2019s it!<span>&nbsp; <\/span>The player can pick up the gerbil by double-clicking on it, and carry it off to wherever having a gerbil would make game sense.<span>&nbsp; <\/span><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">This was a quick-n-dirty code-up to demonstrate adding controls; I\u2019ve appended the full code to this post.<span>&nbsp; <\/span>Obviously, you could clean it up to support multiple controls appearing in squares, dropping things you\u2019ve picked up, using one control with another via dragging controls (as in my post two weeks ago), and so on. <span>&nbsp;<\/span>In a \u201cprofessional\u201d program I\u2019d actually create an array of all of the interesting objects (such as gerbils) which would include their location &amp; name, and which would be scanned in the \u201cAddExceptionalInfo\u201d so that I didn\u2019t have to special-case individual instances as I\u2019ve done here &#8212; this would also help me support dropping inventory in new locations, etc, since the coordinates wouldn&#8217;t be hard coded.<span>&nbsp; <\/span>However, all of the complicated bits are already coded here, and as you can see, they\u2019re really not that complicated at all when using Visual Basic.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">I\u2019m going to try to think of a non-gaming topic for next time \u2013 talk to you then!<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&#8211;Matt&#8211;*<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/MSDNBlogsFS\/prod.evol.blogs.msdn.com\/CommunityServer.Components.PostAttachments\/00\/02\/24\/96\/84\/Maze.zip\">Maze.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Controls on the fly (Matt Gertz) So last week, I posted up a simple \u201cMaze\u201d game, in which you navigate through a virtual environment similar to the old \u201cMyst\u201d game.&nbsp; The way I\u2019d coded it, though, it didn\u2019t actually have any \u201cgame\u201d to it \u2013 you just walked around.&nbsp; In this post I\u2019ll add some [&hellip;]<\/p>\n","protected":false},"author":258,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[22,195],"tags":[101,165],"class_list":["post-6263","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-matt-gertz","category-visual-basic","tag-matt-gertz","tag-vb2005"],"acf":[],"blog_post_summary":"<p>Controls on the fly (Matt Gertz) So last week, I posted up a simple \u201cMaze\u201d game, in which you navigate through a virtual environment similar to the old \u201cMyst\u201d game.&nbsp; The way I\u2019d coded it, though, it didn\u2019t actually have any \u201cgame\u201d to it \u2013 you just walked around.&nbsp; In this post I\u2019ll add some [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/6263","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/258"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=6263"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/6263\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=6263"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=6263"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=6263"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}