July/August 1998
Celebrate a MilestoneDr. GUI's mentioned this before on the Web, but it's an important enough milestone in computing history that it bears repeating in print. The good doctor notes with great glee that our industry has passed an important milestone: computer memory is commonly available for less than U.S. $1 per megabyte. So the memory in a 128-MB machine now costs less than $128. The good doctor remembers paying $300 for 16 MB just a couple of years ago, so this is a big difference indeed! (And it wasn't that long ago that a hard disk was $1 per MB. Come to think of it, Dr. GUI distinctly remembers paying far more than $1 per KB for memory for his Commodore PET and original IBM PC.)
So what should you do about it? Get lots of RAM for your computers. They'll run better—Dr. GUI can't believe how much faster his old P133 is with 80 MB of RAM. And the price is right!
And drink a toast to cheap memory!
Bad, Bad Global DataDear Dr. GUI,
We have a product that uses Internet Explorer (the WebBrowser control) for viewing and printing HTML output. We have found a quirk that, in our humble opinion, is quirky.
If you change the headers and footers in File/Page Setup, the changes take place system wide (I think because they are stored in the registry). We have a situation where two (or more) browser windows are going and if we change the headers or footers in one window, the second window also takes the new settings—and we don't want that to happen.
Can you help?
Cory Riddell
Dr. GUI replies:
Heaven forbid you should find a quirk that wasn't quirky, huh?
As you've noticed, all hosts of the WebBrowser control share the same global Internet settings. For example, changing the headers and footers in File/Page Setup for Internet Explorer 4.0 changes those settings for all applications that are hosting the WebBrowser control.
Most of the global Internet settings do not support a method for automatically saving a set of properties for each WebBrowser host. Certain download options, such as whether to download ActiveX controls, can be overridden and specified on a per-host basis.
The Internet Client SDK (see www.microsoft.com/msdn/sdk/inetsdk/help) documents that WebBrowser hosts can implement the DISPID_AMBIENT_DLCONTROL ambient property on their default dispatch interface to override the global settings for download options.
Knowledge Base article Q183412, "PRB: WebBrowser Control Clients Share Global Settings," provides information about implementing DISPID_AMBIENT_DLCONTROL. You can read this article on Microsoft's Support site (see http://support.microsoft.com/support/kb/articles/q183/4/12.asp). As an alternative, you can send e-mail to MSHELP@microsoft.com with the article ID number in the subject line. You will receive the article in a reply e-mail.
Unfortunately, this won't help in your situation because the headers and footers aren't things that can be changed with this method. Dr. GUI hopes this situation will change in some future version of Internet Explorer.
I Wanna Send Myself an E-mail . . .Dear Dr. GUI,
I am trying to send a message using MAPISendMail function.
The program compiles correctly but gives a linker error (MainFrm.obj: error LNK2001: unresolved external symbol _MAPISendMail@20). (I have included the mapi.h header file.) I have checked the lib directory. It does contain mapi.lib and mapi32.lib files. I am using MAPISendMail in an MFCAppWizard-generated project.
I am using Microsoft Developer Studio and Visual C++ 5.0 on Windows NT 4.0.
Thanks for your help,
Saayan Choudhury
Dr. GUI replies:
If you're not getting enough e-mail, send your own! Actually, sending e-mail to yourself is a great way to test e-mail functionality in your apps—and it keeps you from sending lots of e-mail to others.
The problem is that MAPI32.LIB does not export the Simple MAPI functions. Therefore, in order to use the Simple MAPI functions, you must make a call to LoadLibrary() to load the appropriate DLL (MAPI.DLL or MAPI32.DLL). Then you can call GetProcAddress() to obtain pointers to each of the functions you would like to use.
For more information, please see the topic "Initializing a Simple MAPI Client" in the Microsoft Developer Network Library. For sample code, please see the following article in the Microsoft Knowledge Base: Q171096, "FILE: Simple MAPI Console Application," located at http://support.microsoft.com/support/kb/articles/q171/0/96.asp.
If you're using Microsoft Foundation Classes (MFC) and are trying to send a copy of the current document, note that AppWizard has an option to add a Send command on the File menu. If you forgot, don't despair: there's a MAPI component in the component selection. In version 5.0, you get to this by selecting Add to Project from the Project menu, selecting Components and Controls, and then selecting Developer Studio Components to get to the Components and Controls Gallery. (This is one of the slickest features of Visual C++, and perhaps one of the most underused.)
By the way, if you ever need to know how different AppWizard options generate code, it's easy: just run AppWizard with the different options, and then run WinDiff (supplied with Visual C++) on the projects. The differences are the changes you'll have to apply to your program. Dr. GUI sometimes makes a copy of the AppWizard output for important projects just in case he needs to change some of the AppWizard options.
Positioning Those ControlsDear Dr. GUI,
Is the HTML Layout control the best way to position ActiveX controls properly in a Web page? Are there any other ways to position controls? Also, when I do use the HTML Layout control and view the content using Internet Explorer 4.0, a Security Alert warning message, "An ActiveX object on this page may be unsafe. Do you want to allow it to initialize and be accessed by scripts?" is displayed. Why is this message displayed?
Thanks & Regards,
Jeet Jagasia
Dr. GUI replies:
One of the problems with older versions of HTML is that it was very hard to position elements exactly where you wanted on a page. Internet Explorer 4.0 solves this problem with Dynamic HTML (DHTML), but a solution exists even for Internet Explorer 3.02: the HTML Layout control.
The HTML Layout control is the best way to position ActiveX controls for Internet Explorer 3.02. For Internet Explorer 4.0, the best way to position controls is to use DHTML. DHTML is by far the easiest solution, but in situations where you must support Internet Explorer 3.02, DHTML is not an option because it is supported only by Internet Explorer 4.0 and later. (The browser whose name begins with "N" doesn't support either of these, although it has its own version of DHTML.)
Knowledge Base article Q183977, "SAMPLE: Using HTML Layout content in Internet Explorer 3.02, 4.0," describes a method of modifying HTML Layout control content and displaying pages so that they can be used in either Internet Explorer 3.02 or Internet Explorer 4.0, with no warning message displayed in Internet Explorer 4.0. To do this, the script on the page generates an <OBJECT> tag that loads a second page into the HTML Layout control under Internet Explorer 3.02 and an <IFRAME> tag that loads the same second page under Internet Explorer 4.0.
About those messages: Internet Explorer 4.0 is hardwired to display an initialization and scripting safety warning message if the control has not been marked safe for initialization and safe for scripting.
Using Microsoft Authenticode technology, Microsoft has digitally signed the HTML Layout control (which is available for download through http://activex.microsoft.com/controls/mspert10.cab). By signing the HTML Layout control, Microsoft has taken responsibility for the safety of the control, assuring customers that they know the code comes from Microsoft, that it hasn't been tampered with since publication, and that they can trust Microsoft's assessment that the control is safe to use.
Because the HTML Layout control can be used by third-party developers to host other ActiveX controls, which themselves may not be safe for initialization and/or scripting, the HTML Layout control is inherently unsafe. For this reason, a decision was made to unconditionally warn about safety rather than risk possible code safety problems caused by one or more of the ActiveX controls hosted by the HTML Layout control.
You can find further information about using the HTML Layout control with Internet Explorer 4.0 in the article "The HTML Layout Control and Internet Explorer 4.0" (see http://msdn.microsoft.com/workshop/misc/layout/default.asp).
Where's REGCLEAN? What About Waldo?Dear Dr. GUI,
I've tried to find Regclean.exe in the two locations you noted, but can't. I even have the Visual Basic 5 "Developers Guide" with a CD-ROM that is supposed to have RegClean on it . . . but doesn't. HELP!!
Aaron Morris
Dr. GUI replies:
The latest version of RegClean, 4.1a, is available at either of the two locations listed below:
The first location contains additional information about how RegClean works and known issues in its usage. RegClean has been removed from the Visual Basic CD in favor of having the file downloaded from Microsoft's Web site. You can request that the article be sent to you by using Microsoft's article e-mail service at the following address: mshelp@microsoft.com.
Enter Q147769 as the subject of the e-mail message, and the text of the article describing RegClean usage will be e-mailed back to you. You will still need to connect to one of the links above to download RegClean 4.1a.
HTML References?Dear Dr. GUI,
Microsoft used to publish a Web site dedicated to HTML tags. Is there still such a site and does it spell out DHTML and the new way tags are written in Internet Explorer 4.0? If so, could you please share this URL with myself if not the rest of the world?
Thanks,
"stubear"
Dr. GUI replies:
The Dynamic HTML references (formerly found in the Internet Client SDK) are now part of Site Builder Network (SBN) Workshop. You can view the DHTML references online by going to msdn.microsoft.com/workshop/default.asp. The table of contents contains a link to DHTML, HTML, and cascading style sheets (CSS). Or, you can access the references directly at msdn.microsoft.com/workshop/author/default.asp.
The Great FoxPro/Access DebateDear Dr. GUI,
I need to develop a database application that will be distributed as a freestanding .exe file. I have Microsoft Visual FoxPro 3.0 (developer edition) and the standard Office 97 suite which has Access included in it. I need to decide which one to spend my time learning, FoxPro or Access. Being that I don't know either one I need some advice here. My goal, as I stated, is to develop an application, which I can distribute on floppies, and have the application install itself with a setup.exe extraction and installation procedure. I am not real familiar with the whole process. I don't know if Access that comes in the Office suite is capable of creating this. I do however have the developers package of Visual FoxPro 3.0. I hope you can help me out in my choice. Are they similar so that if I know one I can operate the other? I was told that Access uses Visual Basic for its procedural coding. Is this true? I am just starting and so need a clear answer in layman's terms.
Thank you,
Chris Pratt
Dr. GUI replies:
You bring up several good questions about two of Microsoft's database development tools. Let the good doctor help you to decide which product to prescribe. (Dr. GUI lets you write your own prescriptions? Cool! But just for development tools. . . .)
Both Microsoft Visual FoxPro and Microsoft Access can be used to create a database application that you can distribute on floppies and have the application install itself using a Setup.exe program. (Floppies?)
Microsoft Visual FoxPro Professional Edition gives you the tools to do this. You can create a complete database application, create a Setup program, and distribute it on floppies. Visual FoxPro will create an .exe file as the starting point for your application. It will be a "freestanding" executable in that it does not require Visual FoxPro in order to run. What is required, however, is the Visual FoxPro run-time library (VFP300.DLL), which you are free to distribute if you own the Visual FoxPro Professional Edition and will be installed seamlessly by the Setup.exe program.
Microsoft Access will also allow you to achieve your goal if you have the Office 97 Developer Edition (ODE). The ODE includes all the products found in the Microsoft Office 97 Professional Edition plus the tools you need to create, manage, and distribute office applications. Using Access and the ODE you can create a complete database application and a Setup program, and distribute it on floppies. It will also be a "freestanding" application, in that your clients will not need Microsoft Access installed in order to run your application. It behaves a little differently than Visual FoxPro, however. Rather than creating an .exe, Microsoft Access works exclusively with .Mdb (Microsoft Database) files. The .Mdb is executed using the Microsoft Access run-time library (MSACCESS.EXE). The Microsoft Access run-time library is free to distribute if you own the ODE, and is also installed seamlessly by the Setup.exe program.
So which one does Dr. GUI prescribe? Well, Visual FoxPro is an object-oriented development tool whose core language is Xbase. There are thousands of developers who have an enormous investment in Xbase code and existing applications. Visual FoxPro targets these developers to help ease the move to a 32-bit Windows environment. Visual FoxPro is also a cross-platform product (Visual FoxPro 3.0 is also available for the Macintosh), which may or may not be important to you. (Previous versions of FoxPro were also supported on the MS-DOS and UNIX platforms.) Unfortunately, Visual FoxPro has a rather steep learning curve, and unless you are already familiar with Xbase programming it would not be my first choice for a new database developer. I would recommend Visual FoxPro if you've already invested time and money in existing Xbase applications and are seeking a 32-bit Windows and/or a cross-platform solution.
Microsoft Access, on the other hand, is a product geared toward both the novice and advanced user. It is simple enough for most home users to create quick databases, with little or no programming knowledge, yet sophisticated enough for developers to create complex database applications. Microsoft Access uses the Visual Basic for Applications (VBA) language, which is a subset of the Visual Basic language. The learning curve for using Microsoft Access is quite low, but the learning curve for learning VBA may vary depending on the amount of programming skill you already possess. I would recommend Microsoft Access if you are new to database development, if you are seeking a shorter learning curve, and if you would like to keep programming to a minimum. I would not recommend it if you are seeking a cross-platform environment: Microsoft Access is currently a Windows-only product.
Dr. GUI hopes that with this information you can prescribe for yourself the tools you need.
By the way, you can also develop database apps with Visual C++, Visual Basic, or Visual J++ (not to mention languages from other companies). Or was that more than you needed to know?
How to Catch a Mouse (Event)Dear Dr. GUI,
I am using ActiveX Documents in Visual Basic 5 Service Pack 2 for the first time. I was recently at the Visual Basic developers conference and I saw a demo where it was possible to create HTML text and catch mouse events attached with the text. If a mouse moves over the text, do something. I cannot remember how the guy that demonstrated it used HTMLDocument to do this.
I have created a variable called "obj" that is a pointer to a HTMLDocument object:
Private WithEvents obj as HTMLDocument
The problem is, what do you set it to?
Set obj = ?????????
Also at what point do you set it, InitProperties maybe?
Thank you in advance,
Adam Johnson
Dr. GUI replies:
The demo you saw was probably a Microsoft Internet Explorer Dynamic HTML (DHTML) demo. Internet Explorer generates mouse events such as onMouseOver and onMouseOut for DHTML elements on your Web page. You can trap these events in a Visual Basic application (see the March/April 1998 issue of MSDN News) in one of two ways:
–or–
So what can we set the obj variable to in your code above? The answer is that you cannot set it to anything meaningful inside an Active Document because your Active Document is not hosted by an HTMLDocument object.
If you are creating an ActiveX control you can write the following to get to the containing document. From within the code for the UserControl_Show event:
Set obj = UserControl.Parent.Script.document 'from within ActiveX control
And, if you are hosting the HTML page in your WebBrowser control application, you can use the following code from within the DocumentComplete event:
Set Obj = brwWebBrowser.Document 'from WebBrowser control application
If you really need such mouse events in an Active Document, you can always use the standard Visual Basic MouseMove event.
Visual Basic and Custom InterfacesDear Dr. GUI,
Is it possible to access custom interfaces from within Visual Basic?
Thanks,
Majid Nasab
Dr. GUI replies:
In a word, "Yes." And it's easy. Although we've talked about this on the Web recently in the "Dr. GUI on Components, COM, and ATL" series (Part 6), it's important enough for performance that your question deserves answering again here.
It has been commonly misunderstood that Visual Basic needs IDispatch support when accessing COM objects. (That used to be true, but it hasn't been for several versions now.) To use an interface derived from IUnknown, you must set a reference to the Type Library of the component from the Project/References menu. A type library can be created using the MIDL (Microsoft Interface Definition Language) tool, which is shipped with Visual C++ 5.0.
It is required that only Automation data types be used when describing the custom interface. Here are some of the Visual Basic/Automation-Compatible Datatypes along with the corresponding MIDL types.
Visual Basic | MIDL |
Integer | short |
Long | long |
Single | float |
Double | double |
Byte | unsigned char |
Boolean | VARIANT_BOOL |
String | BSTR |
Variant | VARIANT |
Date | DATE |
Currency | CURRENCY or CY |
Object | IDispatch * |
IUnknown | IUnknown |
Below is the interface section of a sample IDL file created using the Visual C++ 5.0 ATL Com Wizard, which contains a custom IConvert interface for an ActiveX DLL named "Travel." This interface describes two methods for converting from miles to kilometers:
interface IConvert : IUnknown
{
[helpstring("Mi. to Km")] HRESULT MilestoKM([in] double nMiles, [out,retval] double *pVal);
[helpstring("Km to Mi.")] HRESULT KMtoMiles([in] double nKM, [out,retval] double *pVal);
};
After the type library has been created and referenced within Visual Basic, you can dimension a variable of the specific interface type and retrieve a pointer to the interface by using the SET statement. Unless your COM object has a dual interface, you must use early (VTBL) binding and dimension the variable of a specific type, rather than object, because it will have no IDispatch methods. Direct VTBL binding is the fastest method of binding. The downside is that the interface won't be able to be accessed by VBScript or any other client that supports only late binding. The Set statement performs the necessary QueryInterface call for you.
The following Visual Basic code demonstrates this:
Private Sub Form_Load()
Dim x As TRAVELLib.IConvert
Set x = New TRAVELLib.Convert
MsgBox "10 Miles = " & x.MilestoKM(10) & " Kilometers"
Set x = Nothing
End Sub