This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.

MSDN Magazine

Onstop, Connecting to SQL with ASP, Hiding Images, Passing Values from a Control
Robert Hess
Q How can I detect if a user clicks the browser's Stop button while viewing my Web page?

A Starting with Microsoft® Internet Explorer 5.0, your client-side code can trap the onstop event. This will let you know when the user clicks the Stop button, hits the Escape key, or when the page is being unloaded.
      Trapping the onstop event is handy when your page is performing some process that you want to stop when the user clicks the Stop button. Some processes that users might want to stop include background music, some forms of animation, some image loading, or other lengthy processes. The code in Figure 1 shows how to trap the onstop event.
      You might be more interested in another use for onstop. Sometimes when a user stops a page download it means he is having problems with the download. Perhaps it's a bandwidth problem. In such a case you might want to automatically shift to the low bandwidth version of your site, if you have one, or provide users with some information about a text-only version of your site. Unfortunately, the onstop event usually won't work in this case if the page hasn't loaded far enough to encounter the script that handles the event.
      You could work around this by using framesets or iframes. Since all pages within a frameset will get the onstop event when the Stop button is clicked, it is possible for your table of contents frame to target your main window. If the user clicks the Stop button before that frame is fully loaded, you can trap the onstop event in your contents page and take whatever action you think is appropriate. To see an example of multiple frames catching the onstop event, all you have to do is wrap the code in Figure 1 into a frameset like this one:

  <frameset rows="*,*">
    <frameset cols="*,*">
        <frame src="onstop.html">
        <frame src="onstop.html">
    </frameset>
    <frameset cols="*,*">
        <frame src="onstop.html">
        <frame src="onstop.html">
    </frameset>
</frameset>

      It is important to remember that onstop will also be triggered when the page is unloaded through normal navigation away from the page, so you want to make sure that whatever processing you do takes this into account. The easiest way to do this is to also watch the onbeforeunload event. During normal navigation off a page, the onbeforeunload event will be triggered before the onstop event, so you could easily set a flag or change the function to handle onstop properly.

Q I am trying to use ASP to connect to a SQL Serverâ„¢ database, but the DBMS and Web server are separated by a firewall. I am using a SQL OLE DB driver and I believe that SQL Server is listening on port 1433, but I can't open a connection. Should I be able to just change my connection string from:

  strConn = "Provider=SQLOLEDB; Data Source=NMGWEB1;" & _
          "Initial Catalog=event; User Id=sa; Password="

to this:
  strConn = "Provider=SQLOLEDB; Data Source=NMGWEB1:1433;" & _
          "Initial Catalog=event; User Id=sa; Password="

      If not, how do I tell the OLE DB driver which port to use for communication?

A I checked with a local expert on server connectivity issues. He says that port 1433 is the standard port for SQL TCP/IP connectivity, and it's the port that SQL Server uses by default. So it's likely that the firewall in front of the machine running SQL Server doesn't have this port open. This is the very first thing you should check.
      But there doesn't appear to be any way to indicate in your connection string an alternate port number to use for your connection. Being able to do this wouldn't be a bad idea, since it would hide the port number from the prying eyes of hackers, but you'll have to rely on real security measures instead. Be sure to use strong passwords for whatever account is used to authorize the connection to the database.
      Also, you should think about some of the default logging associated with the sa account. If you can create an appropriately secure self-created user account, you will probably get better performance than you get with the sa account. This will also allow you to set up account-level privileges on that account, while exposing only the minimum set of privileges to the world.

Q I have an absolutely positioned <DIV> block that is initially hidden in my HTML page. When I expand it, I can get it to overlay all elements except a <SELECT> element. Is there anything special about the z-index of <SELECT>?

A Actually, this is a common complaint among Web developers. This behavior of <SELECT> is a side effect of the way the <SELECT> element is rendered in Internet Explorer and Netscape Navigator, and there is no way to prevent it. At least in Internet Explorer it's only the <SELECT> element that has this buggy behavior. The solution that many sites (including microsoft.com) have used is to simply hide any <SELECT> elements on the page any time a floating <DIV> element, such as one that's used for a dropdown menu, is brought up.

Q I have my own ActiveX® user control that's similar to the textbox control. I would like to put my control on an HTML page inside a <FORM> tag. I'm using this code:

  <FORM action="other.asp" method=post id=form1>
    <OBJECT classid="CLSID:B9F6F4B0-384A-4079-AF98-D4DFB174E036"    
        codebase="Project1.CAB#version=1,0,0,0" 
        id=UC style="LEFT: 0px; TOP: 0px" VIEWASTEXT>
        <PARAM NAME="_ExtentX" VALUE="7144">
        <PARAM NAME="_ExtentY" VALUE="714">
        <PARAM NAME="BackColor" VALUE="-2147483633">
    </OBJECT>
    <input type="submit" value="Submit" name="B1">
        <input type="reset" value="Reset" name="B2"> 
</FORM>

      How can I use the control inside the form to send the value from the control to other.asp? I would like to use this ASP code:
  <%Response.Write Request.Form.("MY_CONTROL_NAME")%>

A An ActiveX control can't just simply be included within the processing of a form submit request, but there are ways to allow the values entered in the control (or Java-language applet, or whatever) to be passed along to the server and be processed as though they came from a standard form control.
      Basically, all you need to do is intercept the submit event and copy the appropriate information from your ActiveX control into a hidden form element (see Figure 2).

Q How do I disable the Save Picture As option that pops up when a user right-clicks on an image displayed in their browser?

A It sounds like you want something to protect the images you display on your Web site. The way browsers simply allow free access to all of your images is just a little scary. And I expect it isn't just the Save Picture As behavior, but also Copy, and Set as Wallpaper that you'd like to limit. When you get right down to it, you probably don't want that context menu popping up at all.
      The good news is that starting with Internet Explorer 5.0 you can actually control the menu. There is an event called oncontextmenu that is exposed and that gets fired any time a context menu is about to pop up for an item on the page. If you capture that event and return false, the context menu won't pop up. So you could use

  <img src="images/picture.jpg" oncontextmenu="return false">

and the user will never see a context menu for that item.
      For those who aren't using Internet Explorer 5.0, you can do something tricky with Cascading Style Sheets (CSS):
  <img src="images/clear.gif" width=200 height=142
     style="background:url(images/picture.jpg)">

      Here I'm using the <IMG> tag to display a transparent GIF image of the same height and width as the real image. I then set the CSS background of the image to display the actual picture. This will work in Internet Explorer 4.0.
      Unfortunately, this trick doesn't appear to work in Navigator, but the following variation will:
  <div style="background:url(images/picture.jpg) no-repeat; width:200; 
     height:142">
<img src="images/clear.gif" width=200 height=142>
</div>

This does basically the same thingâ€"it layers the transparent image on top of the one the user wants to copyâ€"but this time by setting the real GIF as the background of the <DIV> rather than the background of the image.
      So what if the user has a version of Internet Explorer or Navigator that supports none of the tricks I just mentioned? I guess you're out of luck. And remember, all the user has to do is view the source of your page in order to find out the URL of the image, and navigate to that file directly. In that case, you won't have any control over access to your images.

Q I have written an app in Visual C++® that will play back a video file (mpg, asf, avi, and so on). One feature I added is the ability to start at a given time using a command-line argument in the form of filename.ext?hh:mm:ss for hours, minutes and seconds, respectively. I have changed the registry on my PC to make my app the default viewer, setting the default key for HKEY_CLASSES_ROOT\mpegfile\Shell\Open to c:\Path\To\My\App.exe "%L".
      The problem is that clicking on one of the files will open my viewer, but if I create a Web page with an anchor set to <a href="video.ext?00:00:05">, the only thing passed to the command line is the path to the file and the file name, not the ?00:00:05 argument. Note that this is written to play videos on the hard drive, not the Internet.
      So, how do I pass a command line via a Web page link?

A Technically, there isn't any reason the data following the file name in an href couldn't be passed on to an executable as the command line, but in reality this doesn't happen. This is most likely a security feature. Consider for example:
  <a href="format.com?c:">Click me</a>

Perhaps very few folks would actually press "Y" to format their hard drive, but it might catch some folks, so you get the idea.
      When an href is used as a link to an executable, essentially everything following the "?" is removed as the browser determines which file it should download and run. But that doesn't mean you're down for the count. The issue isn't how you encode a command line into an href, but rather how you control the functionality of an application that is executed from a Web page. This might sound like the same thing, but it is a little different.
      Perhaps the easiest solution is to implement your application as an ActiveX control. This would allow you to simply put an <OBJECT> tag in your page that identified the application to execute, then <PARAM> tags define how this application is to be initialized. Thus, your application could be launched as:
  <object ...>
    <param name="filename" value="video.ext">
    <param name="startat" value="hh:mm:ss">
</object>

      Of course, there are issues with this solution. For instance, it may not be feasible to turn your particular application into an ActiveX control. In this case an alternative would be to write a new ActiveX control that is essentially just a launcher app, which would be invoked like this:
  <object ...>
    <param name="application" value="app.exe">
    <param name="args" value="filename.ext?hh:mm:ss">
</object>

      If you're not ready to deal with ActiveX and COM, an even simpler (but more roundabout) solution would be to create an application that simply reads in values from a file and takes specific action on them. For example, if you associate this new application with the .loader file extension, then the anchor on your page might look like:
  <a href="videoplayback.loader">Video</a>

And the contents of videoplayback.loader might look like:
  app.exe
filename.ext?hh:mm:ss

      All your app would need to do is read in the first line, use that as the application name to execute, and then read the second line and use that as the command line to pass to the application. You would then use these as parameters for the CreateProcess call.

Q I am trying to form an XML schema in both Microsoft XML Schema format and Document Type Definition (DTD) format.
      My requirements are that the tags in a particular element can be in any order, but they can appear only once. This works using XML Schema (see Figure 3), but not using DTD. Can you tell me if it is possible in DTD format?

A The minOccurs and maxOccurs of the XML Schema format makes this fairly easy and straightforward. According to the DTD folks, it appears that while it is possible to represent this in DTD, it gets a bit verbose. Here is essentially what you need to do:
  <!ELEMENT experience (comment, company, type, country) |
                     (country, comment, company, type) |
                     (type, country, comment, company) |
                     (company, type, country, comment) |
... etc. for, in this case, all 16 possible combinations...
>

Got a question? Send questions and comments to webqa@microsoft.com
Robert Hess is currently the host of "The MSDN® Show" (https://msdn.microsoft.com/theshow) and is a regular contributor to various areas of MSDN.

From the November 2000 issue of MSDN Magazine.