{"id":64413,"date":"2007-07-20T00:53:00","date_gmt":"2007-07-20T00:53:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/07\/20\/how-can-i-create-a-custom-dialog-box\/"},"modified":"2007-07-20T00:53:00","modified_gmt":"2007-07-20T00:53:00","slug":"how-can-i-create-a-custom-dialog-box","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-create-a-custom-dialog-box\/","title":{"rendered":"How Can I Create a Custom Dialog Box?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hey, Scripting Guy! How can I create a custom dialog box that presents the user with two options, and then runs the appropriate subroutine based on the option they chose?<BR><BR>&#8212; AM <\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\"><\/A> \n<P>Hey, AM. Well, today is another day, which is good; after all, yesterday was anything <I>but<\/I> a banner day here in the scripting world, at least not when it comes to important things like baseball and softball. Yesterday morning, for example, the Scripting Editor and her softball team were shellacked 14-2 in a game called after 4 innings due to the \u201cmercy rule.\u201d That was tough: the Scripting Editor is a tad bit competitive, so she wasn\u2019t too pleased about getting beat. On the bright side, however, she did have a fantastic view of the game, particularly of all those ground balls that whizzed by her as she stood in the spot where a <I>real<\/I> second baseman would normally stand. Fortunately, she wasn\u2019t hurt; she didn\u2019t get close enough to any of those ground balls to actually get hit.<\/P>\n<TABLE class=\"dataTable\" id=\"ECD\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note to the Scripting <\/B><B>Ed<\/B><B>itor<\/B>. Just a little good-natured sports humor there. You know how much we all really love you.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<TABLE class=\"dataTable\" id=\"ERD\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Ed<\/B><B>itor\u2019s Note<\/B>. The part about not getting close to those ground balls isn\u2019t true; the Scripting Editor has the bruised shin to prove it. And the part about the good-natured sports humor, well \u2026 the Scripting Editor is well aware of what the rest of the Scripting team thinks of her. Rest assured the feeling is mutual.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Later that day the Scripting Son and his baseball team were shellacked in both ends of a doubleheader, 7-0 and 9-1. The Scripting Son didn\u2019t have any ground balls whiz by him; unfortunately that\u2019s about the only thing that went right for him and the team. (If you\u2019re not a baseball fan we can tell you this much: getting a combined total of 5 hits in two games is not the recommended way to win a doubleheader.) <\/P>\n<P>The net result? During the day the Scripting Editor was in a bad mood, so she didn\u2019t have much to say and pretty much went the entire day without bugging the Scripting Guy who writes this column. That night, the Scripting Son was in a bad mood, so he didn\u2019t have much to say and pretty much went the entire evening without bugging the Scripting Guy who writes this column <\/P>\n<P>You know, come to think of it, maybe it wasn\u2019t such a bad day after all.<\/P>\n<P>Of course, when things are at their darkest there\u2019s only one recourse: you must put your faith in a higher power. You know, a higher power like a Scripting Guy who writes a column that explains how you can create a custom dialog box that presents a user with multiple options and then runs the appropriate subroutine based on the option they chose:<\/P><PRE class=\"codeSample\">Set objExplorer = CreateObject(&#8220;InternetExplorer.Application&#8221;)<\/p>\n<p>objExplorer.Navigate &#8220;file:\/\/\/c:\\scripts\\test.htm&#8221;\nobjExplorer.ToolBar = 0\nobjExplorer.StatusBar = 0\nobjExplorer.Width = 400\nobjExplorer.Height = 250\nobjExplorer.Visible = 1<\/p>\n<p>Do While (objExplorer.Document.All.ButtonClicked.Value = &#8220;&#8221;)\n    Wscript.Sleep 250\nLoop<\/p>\n<p>strSelection = objExplorer.Document.All.ButtonClicked.Value<\/p>\n<p>objExplorer.Quit<\/p>\n<p>Wscript.Sleep 250<\/p>\n<p>Select Case strSelection\n    Case &#8220;Option 1&#8221; \n        Wscript.Echo &#8220;You selected Option 1.&#8221;\n    Case &#8220;Option 2&#8221; \n        Wscript.Echo &#8220;You selected Option 2.&#8221;\n    Case &#8220;Option 3&#8221; \n        Wscript.Echo &#8220;You selected Option 3.&#8221;\n    Case &#8220;Cancelled&#8221;\n        Wscript.Quit\nEnd Select\n<\/PRE>\n<P>We\u2019ll explain how this script works in just a moment; before we do that, however, we have a few other things to talk about. First, neither VBScript nor Windows Script Host provides a built-in method for creating custom dialog boxes; you can kind of, sort of create custom message boxes, but even then you\u2019re limited to using a <A href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/sfw6660x.aspx\" target=\"_blank\"><B>finite set of buttons<\/B><\/A>. Therefore, we need to cheat a little in order to do this: we need to create an HTML file that displays our options, and then have our script call this HTML file rather than call a custom dialog box. In fact, that\u2019s what this line of code is for:<\/P><PRE class=\"codeSample\">objExplorer.Navigate &#8220;file:\/\/\/c:\\scripts\\test.htm&#8221;\n<\/PRE>\n<P>But more on that in a minute. For now, let\u2019s take a look at that HTML file (C:\\Scripts\\Test.htm):<\/P><PRE class=\"codeSample\">&lt;SCRIPT language=&#8221;VBScript&#8221;&gt;\n    Sub OKClicked\n        If UserOption(0).Checked Then\n            ButtonClicked.Value = &#8220;Option 1&#8221;\n        End If\n        If UserOption(1).Checked Then\n            ButtonClicked.Value = &#8220;Option 2&#8221;\n        End If\n        If UserOption(2).Checked Then\n            ButtonClicked.Value = &#8220;Option 3&#8221;\n        End If\n    End Sub<\/p>\n<p>    Sub CancelClicked\n        ButtonClicked.Value = &#8220;Cancelled&#8221;\n    End Sub\n&lt;\/SCRIPT&gt;<\/p>\n<p>&lt;BODY&gt;\n    &lt;input type=&#8221;radio&#8221; name=&#8221;UserOption&#8221; checked=True&gt;Option 1&lt;BR&gt;\n    &lt;input type=&#8221;radio&#8221; name=&#8221;UserOption&#8221;&gt;Option 2&lt;BR&gt;\n    &lt;input type=&#8221;radio&#8221; name=&#8221;UserOption&#8221;&gt;Option 3&lt;P&gt;\n    &lt;input type=&#8221;Button&#8221; value=&#8221;OK&#8221; onClick=&#8221;OKClicked&#8221;&gt;\n    &lt;input type=&#8221;Button&#8221; value=&#8221;Cancel&#8221; onClick=&#8221;CancelClicked&#8221;&gt;\n    &lt;input type=&#8221;hidden&#8221; name=&#8221;ButtonClicked&#8221;&gt;\n&lt;\/BODY&gt;\n<\/PRE>\n<P>What we\u2019ve got here is an HTML file that displays three radio buttons; that\u2019s what these HTML tags do:<\/P><PRE class=\"codeSample\">&lt;input type=&#8221;radio&#8221; name=&#8221;UserOption&#8221;&gt;Option 1&lt;BR&gt;\n&lt;input type=&#8221;radio&#8221; name=&#8221;UserOption&#8221;&gt;Option 2&lt;BR&gt;\n&lt;input type=&#8221;radio&#8221; name=&#8221;UserOption&#8221;&gt;Option 3&lt;P&gt;\n<\/PRE>\n<P>In case you\u2019re wondering, we decided to go with radio buttons for one simple reason: that gives us a little more flexibility (adding additional radio buttons makes for a cleaner user interface than adding a bunch of additional push buttons). Do you need just <I>two<\/I> options? That\u2019s fine; simply delete the tag for the third radio button (the one labeled <I>Option 3<\/I>). Need four options? That\u2019s also fine; just copy the tag for Option 3, paste it to the end of list, and change the label to <I>Option 4<\/I>. Pretty simple stuff when you get right down to it.<\/P>\n<TABLE class=\"dataTable\" id=\"E2E\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. OK, so if you haven\u2019t done much work with HTML maybe this <I>isn\u2019t<\/I> all that simple. In that case, you might want to check out the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/htas.mspx\"><B>HTA Developers Center<\/B><\/A> for an introduction to working with HTML.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>In addition to our radio buttons we also have a pair of regular old buttons, one labeled <B>OK<\/B> and the other labeled <B>Cancel<\/B>:<\/P><PRE class=\"codeSample\">&lt;input type=&#8221;Button&#8221; value=&#8221;OK&#8221; onClick=&#8221;OKClicked&#8221;&gt;\n&lt;input type=&#8221;Button&#8221; value=&#8221;Cancel&#8221; onClick=&#8221;CancelClicked&#8221;&gt;\n<\/PRE>\n<P>As you can see, if and when someone clicks the <B>OK<\/B> button we\u2019re going to run a subroutine named OKClicked; if and when someone clicks the <B>Cancel<\/B> button we\u2019re going to run a subroutine named CancelClicked. And don\u2019t worry; we\u2019ll discuss those two subroutines in just a second.<\/P>\n<P>Before we can do that, however (and yes, there <I>are<\/I> a lot of twists and turns to today\u2019s column, aren\u2019t there?) we need to discuss this line of code:<\/P><PRE class=\"codeSample\">&lt;input type=&#8221;hidden&#8221; name=&#8221;ButtonClicked&#8221;&gt;\n<\/PRE>\n<P>What we\u2019re doing here is adding a hidden control to our HTML page: the control won\u2019t be visible onscreen, but we can still do things like assign it a value. Why do we need a hidden control on our page? Well, technically we don\u2019t; we could have used a different approach in solving this problem. However, using a hidden control makes this whole task much easier to carry out. We have a hidden control that has no value. As you\u2019ll see, our script periodically checks the value of this hidden control. As soon as a value <I>does<\/I> get assigned to the control the script knows that we\u2019ve made a selection in our \u201cdialog box\u201d and then goes ahead and takes action based on that selection.<\/P>\n<P>Which, again, is something we\u2019ll explain in just a moment.<\/P>\n<P>Let\u2019s assume that a user has started your script, something which causes the \u201cdialog box\u201d to appear onscreen. He or she selects one of the radio button options and then clicks <B>OK<\/B>. What happens at that point?<\/P>\n<P>Well, as we noted, clicking the <B>OK<\/B> button causes the OKClicked subroutine to run. Inside that subroutine we simply execute a series of If Then statements to determine which radio button was selected (or, in HTML parlance, which button was checked):<\/P><PRE class=\"codeSample\">If UserOption(0).Checked Then\n    ButtonClicked.Value = &#8220;Option 1&#8221;\nEnd If\n<\/PRE>\n<P>If you\u2019re wondering how this works, all our radio buttons have the same name (UserOption); that\u2019s how we ensure that the buttons work together as a group. In turn, each individual button in a group is automatically assigned an index number: the first button in the group is button 0, the second button is button 1, and so on. All we\u2019re doing here is saying this: If the first button is checked then assign <I>Option 1<\/I> to the value of our hidden control (ButtonClicked). We then repeat this same bit of code for each possible selection.<\/P>\n<P>What if the user clicks the <B>Cancel<\/B> button? Well, in that case we run a different subroutine (CancelClicked) and assign the value <I>Cancelled<\/I> to the hidden control<\/P><PRE class=\"codeSample\">Sub CancelClicked\n    ButtonClicked.Value = &#8220;Cancelled&#8221;\nEnd Sub\n<\/PRE>\n<P>And that\u2019s basically it for the HTML file. Now \u2013 finally! \u2013 let\u2019s turn our attention to the script, which starts out by creating an instance of the <B>InternetExplorer.Application<\/B> object:<\/P><PRE class=\"codeSample\">Set objExplorer = CreateObject(&#8220;InternetExplorer.Application&#8221;)\n<\/PRE>\n<P>After we\u2019ve created an instance of Internet Explorer we then use the <B>Navigate<\/B> method to open the file C:\\Scripts\\Test.htm; we configure the size of the Internet Explorer window (hiding the tool bar and status bar while we\u2019re at it); then we make the whole thing appear on screen by setting the <B>Visible<\/B> property to 1:<\/P><PRE class=\"codeSample\">objExplorer.Navigate &#8220;file:\/\/\/c:\\scripts\\test.htm&#8221;\nobjExplorer.ToolBar = 0\nobjExplorer.StatusBar = 0\nobjExplorer.Width = 400\nobjExplorer.Height = 250\nobjExplorer.Visible = 1\n<\/PRE>\n<P>At this point we start doing some <I>real<\/I> work. To begin with, we have to make sure the script pauses until the user makes a selection in the HTML file. With that in mind we use this line of code to periodically check the value of the ButtonClicked control:<\/P><PRE class=\"codeSample\">Do While (objExplorer.Document.All.ButtonClicked.Value = &#8220;&#8221;)\n    Wscript.Sleep 250\nLoop\n<\/PRE>\n<P>If ButtonClicked has no value (that is, if the value equals \u201c\u201d, an empty string) we simply pause the script for 250 milliseconds and then try again. This continues until the user finally clicks either the <B>OK<\/B> or the <B>Cancel<\/B> button.<\/P>\n<TABLE class=\"dataTable\" id=\"EDAAC\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. What if the user simply closes the Internet Explorer window? That\u2019s going to generate an error and the script will terminate. If you\u2019d prefer that the script come to a more graceful termination you could include some error handling to check for and respond to that condition. But that\u2019s more than we wanted to do today.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>As soon as the value of the ButtonClicked control has changed we store that value in a variable named strSelection, then call the <B>Quit<\/B> method to dismiss our instance of Internet Explorer:<\/P><PRE class=\"codeSample\">strSelection = objExplorer.Document.All.ButtonClicked.Value<\/p>\n<p>objExplorer.Quit\n<\/PRE>\n<P>From there we pause for 250 milliseconds (giving Internet Explorer a chance to close), then use the following Select Case block to take action based on the user\u2019s selection:<\/P><PRE class=\"codeSample\">Select Case strSelection\n    Case &#8220;Option 1&#8221; \n        Wscript.Echo &#8220;You selected Option 1.&#8221;\n    Case &#8220;Option 2&#8221; \n        Wscript.Echo &#8220;You selected Option 2.&#8221;\n    Case &#8220;Option 3&#8221; \n        Wscript.Echo &#8220;You selected Option 3.&#8221;\n    Case &#8220;Cancelled&#8221;\n        Wscript.Quit\nEnd Select\n<\/PRE>\n<P>Obviously these aren\u2019t particularly <I>exciting<\/I> actions, but, needless to say, you can replace our code with pretty much anything you want.<\/P>\n<P>And there you have it, AM. It\u2019s a bit of a workaround and it\u2019s not quite as elegant as creating a true custom dialog box. But it works.<\/P>\n<P>For now, though, it\u2019s time to head to Stanwood High School and another Scripting Son doubleheader. Will it be another quiet night at the Scripting Home? We\u2019ll soon find out.<\/P>\n<P>And no, we won\u2019t discuss the Scripting Editor\u2019s team and its chances of redeeming itself. After all, even a higher power is helpless in the face of <I>some<\/I> things.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I create a custom dialog box that presents the user with two options, and then runs the appropriate subroutine based on the option they chose?&#8212; AM Hey, AM. Well, today is another day, which is good; after all, yesterday was anything but a banner day here in the scripting world, [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[17,3,167,5],"class_list":["post-64413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-internet-explorer","tag-scripting-guy","tag-using-the-internet","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I create a custom dialog box that presents the user with two options, and then runs the appropriate subroutine based on the option they chose?&#8212; AM Hey, AM. Well, today is another day, which is good; after all, yesterday was anything but a banner day here in the scripting world, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64413","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=64413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64413\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=64413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=64413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=64413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}