Make your own free website on
Microsoft HomeProductsSearchSupportShopWrite Us   Microsoft Home
MSDN Online Top News, Hot Columns Our Featured Theme Archived Buzz, Features April 27, 1998
MSDN logo

Member Services
MSDN library online
Microsoft SDKs
About MSDN
heading: resources
Newsgroups and Chats
Books and Magazines
Events and Seminars
User Groups
Enterprise Development
Hardware Development
Office Development
Controls and Components
Heading: Developer Programs
Windows Logo Program
site builder network
solution provider
Microsoft ISV program

International Sites

Can't find it?

MSDN Flash
MSDN Flash

Archived Material

some links on this page may no longer work

Dr. GUI on COM, Part 6: Using Our Object from Visual Basic and Visual J++

Dr. GUI on components, COM, and ATL
Part 1       Part 2       Part 3       Part 4      
Part 5      

Part 6

download Download this article

So What's That About Windows CE?

Dr. GUI enjoyed himself at the recent Windows CE Developers' Conference in San Jose. But the doc is sorry to say that between the CE DevCon, tax day, and a busy surgery schedule, this column is unfortunately late. Sorry, again.

So what's the deal with CE? Well, remember that you've read here before that Windows CE is a modular operating system. That means that, in addition to shipping in various mobile computers (Handheld PCs, Palm-size PCs, and Auto PCs), you can also use it in various embedded systems—everything from custom mobile solutions to controllers. In other words, there are two primary ways in which you might use Windows CE: you might use it to build a customized OS and apps for an embedded system, or you might write applications, components, or drivers for one or more of the Windows CE–targeted product platforms.

Embedded Systems

Windows CE is an ideal operating system for many embedded systems applications. Each embedded device will use just the parts of the modular Windows CE operating system it needs, and then write applications to use the customized embedded OS. This allows embedded systems developers to minimize memory requirements. Yet the services from which an embedded systems developer can choose are powerful—on top of the multithreaded 32-bit kernel you can put modules to do screen I/O, telecommunications, networking, and more. In other words, Windows CE can help you get your device to market more quickly and with more features.

Targeted Product Platforms

But what if you want to write applications? Each member of the PC Companion family (Handheld PC, Palm-size PC, and Auto PC) represents a targeted product platform—a platform for which you can write custom applications. Each platform implementation, regardless of manufacturer, meets the minimum requirements for that platform, ensuring that you have a consistent API and hardware feature set for which to program.

Vive la difference

While there are many similarities between the platforms (all are based on the Win32 API, for instance), the platforms are different because the hardware is different. For instance, Palm-size PCs don't have keyboards but do have handwriting recognition and special application buttons. Auto PCs have a very small display, no keyboard, and support speech input and output. Obviously, Handheld PC programs won't run (or be useful) on the Auto PC. Less obviously, Handheld PC programs have to be modified to work well on the Palm-size PC. The hardware is different, the user interface is different, so the applications have to be different.

   Back Issues

Search archived articles by keyword

View by Column
View archive contents by article and column type

Write Once, Reuse Again and Again

Just because the user interface is very different, however, doesn't mean that there's not a lot that's the same. That's where you can really take advantage of Windows CE: once you've written an application for the Handheld PC, it's not too hard to port it to take advantage of the Palm-size PC. In fact, if you design your programs carefully, you should be able to port many modules without rewriting them at all. For instance, if you're writing a mail application, the data manipulation will be exactly the same between the Handheld PC and the Palm-size PC. Only the display and user interface will change. Good modular design and implementation will help you be an efficient Windows CE developer.

More Platforms to Target in the Future

In addition to the current targeted product platforms, the PC Companion line, there will be others in the future—and Microsoft invites other companies to create their own targeted product platforms.


One of the strengths of Windows CE is the wide variety of tools available from Microsoft and others, such as Metrowerks. Visual C/C++ is available on all Windows CE platforms, including embedded platforms. In addition, some target platforms have support for Microsoft Foundation Classes (MFC), Active Template Libraries (ATL), Visual Basic, and Visual J++. Microsoft is planning to have broad language and tool support available on all platforms as soon as possible.

A Tale of Two Platform Strategies

It's hard to pass up the opportunity to contrast the Windows CE approach with a certain other company's approach. Now, even this company has four distinct platforms—in addition to their standard platform, they're planning on Enterprise, Personal, and Embedded platforms. Each of these platforms will expose a different API, although they're supposed to be subsets of each other. And each represents a least-common-denominator approach to the target products.

The Windows family strategy is quite different: maximize commonality (the Win32 API) while providing just the feature set needed for each platform. This approach allows vendors to maximize performance (using assembler code if necessary) while taking maximum advantage of the unique hardware features of each platform.

Who will win? Dr. GUI can't tell for sure, but if he was a betting doc, he'd bet on features and performance over religious purity.

Where Do I Sign Up?

Maybe you're thinking that this sounds pretty good—and maybe you want to get in on it. What should you do?

First, relax: Windows CE is based on Win32, so you have a leg up on Windows CE already since you know Win32. And the Windows CE-specific things you learn on one platform will transfer, by and large, to other platforms (so will your code, if you design carefully).

Next, check out your options at (the downloads are at Some of the SDKs are even free! And whether you made it to the conference or not, check it out, including PowerPoint slides and NetShow presentations, at

Back to COM: Where We've Been; Where We're Going

Last time, we implemented a complete COM object. This time, we'll talk about using that object from Visual Basic and Visual J++. (We'll do C and C++ next time.) Some of you have written saying, "I don't care about implementing COM objects; I just want to use them." You now have your wish.

But First, an Update

Brent Rector pointed out something that I overlooked in our object's QueryInterface function. He noticed that I went ahead and set *ppv to NULL without checking to insure that ppv wasn't NULL.

STDMETHODIMP CMyObject::QueryInterface(REFIID iid, void **ppv)
	*ppv = NULL;
	// ...
The good doctor initially argued that that was okay—if ppv was NULL, the result would be a GP fault. You'd surely catch this flaw in testing—and that might be preferable to just returning an error result that would be ignored.

Well, if your object is only an in-process server (that is, a DLL), that might be okay. After all, the process that dies as a result of the GP fault would be the client process, which by all rights should die because it had the audacity to pass a NULL pointer to QueryInterface. How rude! Serves it right! (Besides, Dr. GUI hates taking the time unnecessarily to execute code to check for errors.)

The problem occurs when the object is implemented out-of-process (in an EXE). In that case, the process that dies would be the server process, not the client. And that would not be cool—especially if the server was providing other objects to other processes and/or running stand-alone at the same time. (Having Word crash because some background process passed a NULL pointer to QueryInterface would not be fun.) It would be even worse if the server was on a remote machine.

So, to make a long story short, Dr. GUI's come to agree with Brent that the additional error checking is necessary. So we add a line to our old QueryInterface method, and it becomes:

STDMETHODIMP CMyObject::QueryInterface(REFIID iid, void **ppv)
	if (ppv == NULL) return E_INVALIDARG; // don't crash!
	*ppv = NULL;
	// ...

Using Our Object from Visual Basic

Using our object from Visual Basic couldn't be easier. First, we have to add a "reference" to our object to our Visual Basic project. Using the References... command on the Projects menu, we add the reference by finding our COM object in the list box and checking it.

Then we design a simple form with a button to call each method and a text box to show the current value.

Finally, we write the code necessary to access the object. First, in the general declarations section, we declare a reference to the object:

Private obj As MyObject
We then create the actual object in the Load method for the form:

Private Sub Form_Load()
    Set obj = New MyObject
End Sub

This causes Visual Basic to call CoCreateInstance to create the object.

Now that the object's been created, we add a button handler to call the Func1 and Func2 methods in the default IFoo interface:

Private Sub Func1IncBeep3_Click()
End Sub

Private Sub Func2Set_Click()
    If IsNumeric(Text1) Then obj.Func2 (Text1)
End Sub
To call methods in other interfaces, we have to get access to the interface. We do this by creating a variable of the correct type for the interface, and then setting it to point to the object. (When you do this, Visual Basic actually calls QueryInterface on the object.) To switch interfaces, we use code like this:

    Dim Foo2 As IFoo2 ' switch interfaces
    Set Foo2 = obj
We can then call IFoo2 methods using the Foo2 object reference. Knowing this, we can understand the code for accessing the other methods of the object:

Private Sub Func3BeepGet_Click()
    Dim Foo2 As IFoo2 ' switch interfaces
    Set Foo2 = obj
    Text1 = Foo2.Func3
End Sub

Private Sub GuncBeep_Click()
    Dim Goo As IGoo ' switch interfaces
    Set Goo = obj
End Sub
Finally, we add a button handler for the "Increment Text Box" method:

Private Sub IncTextBox_Click()
    If IsNumeric(Text1) Then Text1 = Text1 + 1
End Sub
It almost couldn't be easier.

If you're a fan of late binding, take note: you could use late binding to access this object, but you'd only be able to access the default (IFoo) interface. Late binding doesn't work well for objects that use multiple interfaces—and it's always slower. (By the way, it might be wise to make IFoo2 the default interface at least, since it implements all of the functionality of IFoo as well as Func3.)

Using Our Object from Visual J++

It's almost as easy to use our object from Visual J++. First, we have to create a special .class file that represents the COM object. We do this with the Java Type Library Wizard on the Tools menu of Visual Studio. Again, we just select our object and check it.

This results in a .class file created in our trustlib directory (in the same subdirectory as other Java classes). Our results window has the import statement we copy and paste into our .java file. It also has a reference to the summary.txt file that contains a Java textual representation of our class library. Do not compile this file; the .class file has already been created.

In our case, the import statement reads "import nonatlobject.*;". We insert this at the top of our .java file.

Once we've done this import, we can create and use the object.

Creating the object is as simple as calling new:

IFoo myObj = new MyObject();
Note that we created a MyObject object but assigned it to an IFoo object reference. We cannot use the object as a MyObject in Visual J++—it doesn't recognize or support the concept of a default interface.

At this point, we can call the IFoo methods:

myObj.Func2(5);	// sets
myObj.Func1();	// increments and beeps
myObj.Func1();	// increments
myObj.Func1();	// increments
If we want to call the IFoo2 or IGoo methods, we have to create new object references and assign the object to them:

IFoo2 myFoo2 = (IFoo2)myObj;
System.out.println("Value is " + myFoo2.Func3() + " (8?)");

IGoo myGoo = (IGoo)myFoo2;
myGoo.Gunc();	// beeps
As you can see, using a COM object from Visual J++ is almost as easy as using it from Visual Basic.

Where We've Been; Where We're Going

This time, we showed how to use our COM object from Visual Basic and Visual J++. Next time, we'll show how to use it from C++ and perhaps even from C.

Comments? Send Dr. GUI e-mail.
Technical questions? Read about our tech-support options.

© 1998 Microsoft Corporation. All rights reserved. Terms of Use.