Drawing control article in MSDN Magazine

M

Mai-lan [MS]

The MSDN Magazine December issue, which is also available online for the
next three weeks or so at http://msdn.microsoft.com/msdnmag/, has an article
on the Visio drawing control. It does an intro of the control and describes
how a C# winform sample application that uses the control works.

Thanks,
Mai-lan
 
M

Mai-lan [MS]

It also has the sample application available for free download if you want
to check out the working code.

Mai-lan
 
M

Michael

Mai-Lan,
interesting article! (can it be preserved longer then 3 weeks?)
Currently the drawing control only works if you have Visio 2003 installed,
which I have not :-(((
Are there any plans for a run-time distribution licence for Visio Solutions
built using the drawing control?
(i.e. not needing the full Visio license for one specific application?)

Michael
 
S

Scott Metzger

Hi,

Thanks for the bone while we eagerly await the SDK.

I have a few questions.

1) Why do you que up the Shape Added events and then act on those events
when Visio enters into an 'idle' (no events pending mode)?

The only reason I can think of is for performance reasons. If my
assumption is correct, how much will this speed up adding and deleting
multiple objects?

Or is there another reason I fail to see?


2) The public class EventSinkHandler : Visio.IVisEventProc
has an method... Visio.IVisEventProc.VisEventProc

If I were to do this in C++, would my VisEventProc look something like?
VARIANT MyVisEvent::VisEventProc(short nEventCode,
LPDISPATCH pSourceObj,
long nEventID,
long nEventSeqNum,
LPDISPATCH pSubjectObj,
VARIANT vMoreInfo)
: VisEventProc (blah, blah ...)
{
// do my custom processsing here
}

Thank You,
Scott Metzger
 
M

Mark Nelson [MS]

Queuing events until idle is a good programming practice for Visio. The
primary reason is that it allows you to perform any Visio operation. Visio
is not always in a state where it can perform actions. During several
events, Visio can only be used to read information from a drawing - not
change information in the drawing.

The classic example is Delete-from-Delete. Let's say that the user deletes
a shape and you want to automatically delete another shape in response. If
you try to call Shape.Delete inside the Delete event handler, Visio will
through an error. If you queue the delete action until Idle, you can
successfully delete the other shape.
 
S

Scott Metzger

Mark said:
Queuing events until idle is a good programming practice for Visio. The
primary reason is that it allows you to perform any Visio operation. Visio
is not always in a state where it can perform actions. During several
events, Visio can only be used to read information from a drawing - not
change information in the drawing.

The classic example is Delete-from-Delete. Let's say that the user deletes
a shape and you want to automatically delete another shape in response. If
you try to call Shape.Delete inside the Delete event handler, Visio will
through an error. If you queue the delete action until Idle, you can
successfully delete the other shape.


Interesting. Is there any documentation on what is not allowed in
specific events?

This queing of events would seem to be cumbersome and perhaps volatile
for "Before" events. For example a BeforeShapeDelete event. Most
likely you are using this event because you need the actual shape which
is not available in the ShapeDelete event. But if you que these events
up I would expect the OnIdle to occur after Visio has deleted the Shape
and thus your reference to the Shape is now invalid. But then maybe
when using the Drawing Control you actually get a copy of the shape and
can still read its properties.

Thanks,
Scott Metzger
 
M

Mai-lan [MS]

Hi, Michael: There are no plans for a RT distrubtion license for Visio
solutions built using the drawing control. The control license is tied to
the client application since the control is essentially the client app's
functionality wrapped in a component. You will always need the full Visio
client app installed to use one or more custom apps hosting the control.

Thanks,
Mai-lan
 
M

Mai-lan [MS]

Comments below on your IVisEventProc implementation in C++, you're on the
right track...

Mai-lan
--
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
Scott Metzger said:
Hi,

Thanks for the bone while we eagerly await the SDK.

I have a few questions.

1) Why do you que up the Shape Added events and then act on those events
when Visio enters into an 'idle' (no events pending mode)?

The only reason I can think of is for performance reasons. If my
assumption is correct, how much will this speed up adding and deleting
multiple objects?

Or is there another reason I fail to see?


2) The public class EventSinkHandler : Visio.IVisEventProc
has an method... Visio.IVisEventProc.VisEventProc

If I were to do this in C++, would my VisEventProc look something like?
VARIANT MyVisEvent::VisEventProc(short nEventCode,
LPDISPATCH pSourceObj,
long nEventID,
long nEventSeqNum,
LPDISPATCH pSubjectObj,
VARIANT vMoreInfo)
: VisEventProc (blah, blah ...)
{
// do my custom processsing here
}

[mai-lan] You might do something like the following in your event sink
implementation:

STDMETHODIMP CVisioEventSink::VisEventProc(
IN SHORT nEventCode,
IN IDispatch* pSourceObj,
IN LONG nEventID,
IN LONG nEventSeqNum,
IN IDispatch* pSubjectObj,
IN VARIANT vMoreInfo,
OUT VARIANT* pvResult)
{
if (pvResult == NULL)
return E_POINTER;

return E_NOTIMPL;
}
 
S

Scott Metzger

Ok, I am confused now.

When I import the type library there is a class called CVisEventProc.
It has a few contructors and then one function with the following
declaration...
class CVisEventProc : public COleDispatchDriver
{
public:
...
public:
VARIANT VisEventProc(short nEventCode, LPDISPATCH pSourceObj, long
nEventID, long nEventSeqNum, LPDISPATCH pSubjectObj, VARIANT vMoreInfo)
}

I am under the impression that I would create a new class derived from
CVisEventProc which would overide the base classes VisEventProc and also
call the base classes VisEventProc. Is this correct?

Your declaration of VisEventProc has an extra parameter (OUT VARIANT*
pvResult), where did that come from?

Thanks,
Scott Metzger
 
M

Mark Nelson [MS]

There is a decent writeup on this in the help topic for the
MustFlushScopeBeginning event. Visio actually fires additional events to
tell you when it is in a state that restricts actions. If you are inside a
MustFlushScope, you cannot modify the document.
 
M

Mai-lan [MS]

Hi, Scott: I've gotten more feedback from several members of the team on
this. Here's our recommendation (this is related to your other post that
I'll be responding to as well):
How did you import that Visio type library? We recommend using #import if
you are using Visual Studio. We do not recommending using MFC's import
mechanism. The wrapper objects created by MFC import mechanism are late
bound and hence slower. MFC generator also doesn't work well with safe
arrays and Visio has a number of methods that use safe arrays. For more info
on the limitation of the MFC generator, see these links
http://support.microsoft.com/default.aspx?scid=kb;en-us;158451
http://support.microsoft.com/default.aspx?scid=kb;en-us;237554

The IVisEventProc interface is defined in Visio's type library because it
defines a communication protocol with Visio BUT Visio doesn't implement it.
Clients of Visio who use AddAdvise must implement this interface and pass a
pointer to their implementation to Visio. This interface inherits from
IDispatch and hence IUnknown so client implementation must implement the
methods on those interfaces as well as the method in IVisEventproc. Since
the interface is in the type lib your generator may create a wrapper class
for it. Don't use it. It doesn't do anything useful and probably does
something dumb.

The Visio 2002 SDK contains library code that can be used with AddADvise and
implements IVisEventProc for you. In your SDK install its in
Libraries\Cpp\source\addsink.cpp and Libraries\cpp\source\addsink.h.

The Visio 2002 SDK also has a sample that shows how to use this sink class
in an objected oriented way. Its called GenericMFC. The sample does use
Visiwrap (a legacy Visio wrap mechanism that is not as good as #import
because its too visio specific). The differences between Visiwrap and other
wrapper classes is mostly syntactic so it still a good example of how to use
the code in AddSink.h/cpp. The sample is an add-on BUT that's irrelevant
from the event handling part of this. Add-ons are just easy way's to run
code in Visio in C++. The relevant code for event handling purposes are the
creation of the sink class and calls to AddAdvise in the Run method. If
you're not creating an add-on its needs to go in some other method called,
say InitializeEvents. The other important code to look at is its
HandleVisioEvent method. This is a virtual method inherited from the
VEventHandler class defined in AddSink.h. For non-add-ons that use this,
think about something like:


Class MyEventHandlerClass : public VEventHandler {

/* Class must implement HandlevisioEvent method (virtual method in
VEventHandler). A instance of this class must be passed as the event handler
in the call to CoCreateAddonSinkForHandler (defined in Addsink.h). The class
could also have a public method that handles registering for events using
AddAdvise. */ };

-Visio SDK team.

Thanks,
Mai-lan
 
M

Michael

Mai-lan,
thanks for your response. I was afraid of this answer :-(
Is it a technical problem, i.e. the drawing control needs Visio to be
installed for the underlying functionality?
Michael
 
S

Scott Metzger

Mai-lan said:
Hi, Scott: I've gotten more feedback from several members of the team on
this. Here's our recommendation (this is related to your other post that
I'll be responding to as well):
How did you import that Visio type library? We recommend using #import if
you are using Visual Studio. We do not recommending using MFC's import
mechanism. The wrapper objects created by MFC import mechanism are late
bound and hence slower. MFC generator also doesn't work well with safe
arrays and Visio has a number of methods that use safe arrays. For more info
on the limitation of the MFC generator, see these links
http://support.microsoft.com/default.aspx?scid=kb;en-us;158451
http://support.microsoft.com/default.aspx?scid=kb;en-us;237554

Okay, so the light at the tunnel I saw was a train.
The article seems to suggest that its possible to use the Wizard and
write the wrapper to invoke variable-length list params. Is that true?
I have timelines and it may not be feasable to learn how to use #import
by hand and write all those wrapper functions by hand.

How can I find out which methods use safe arrays?
The Visio 2002 SDK contains library code that can be used with AddADvise and
implements IVisEventProc for you. In your SDK install its in
Libraries\Cpp\source\addsink.cpp and Libraries\cpp\source\addsink.h.

I'll take a look at this. I actually have AddAdvise working via the
2002 SDK. But its in a non-OO way and I am using vaoObjectWrap to get a
Visio Application handle. Using vaoObjectWrap is particularly bad, it
looks like I am getting a conflict that prevents me from saving drawings.

I'll look further into the example to see if there is a way to use the
2002 SDK for only the AddAdvise event stuff. One problem I have is that
the 2002 SDK is not friendly with Visual Studio .Net 2003. The project
wizard that sets up all the compiler flags only works with VS 6.0. Do
you know what the compiler flags and #defines are for only bringing in
the AddAdvise stuff?

I'll post more after a thorough analysis of the example.

Thanks,
Scott Metzger
 
M

Mark Nelson [MS]

Exactly. Visio is the drawing control.

--
Mark Nelson
Microsoft Corporation

This posting is provided "AS IS" with no warranties, and confers no rights.


Michael said:
Mai-lan,
thanks for your response. I was afraid of this answer :-(
Is it a technical problem, i.e. the drawing control needs Visio to be
installed for the underlying functionality?
Michael
Mai-lan said:
Hi, Michael: There are no plans for a RT distrubtion license for Visio
solutions built using the drawing control. The control license is tied to
the client application since the control is essentially the client app's
functionality wrapped in a component. You will always need the full Visio
client app installed to use one or more custom apps hosting the control.

Thanks,
Mai-lan

--
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
Michael said:
Mai-Lan,
interesting article! (can it be preserved longer then 3 weeks?)
Currently the drawing control only works if you have Visio 2003 installed,
which I have not :-(((
Are there any plans for a run-time distribution licence for Visio Solutions
built using the drawing control?
(i.e. not needing the full Visio license for one specific application?)

Michael

"Mai-lan [MS]" <[email protected]> schreef in bericht
It also has the sample application available for free download if
you
want
to check out the working code.

Mai-lan
--
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no
rights.
The MSDN Magazine December issue, which is also available online
for
the
next three weeks or so at http://msdn.microsoft.com/msdnmag/, has an
article
on the Visio drawing control. It does an intro of the control and
describes
how a C# winform sample application that uses the control works.

Thanks,
Mai-lan
 
M

Mai-lan [MS]

Hi, Scott: Answers inline below.

--
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
Scott Metzger said:
Okay, so the light at the tunnel I saw was a train.
The article seems to suggest that its possible to use the Wizard and
write the wrapper to invoke variable-length list params. Is that true?
[mai-lan] Most of the methods in Visio that use safe arrays are not variable
list params and must be passed arrays in other languages too. I don't know
if the variable list parameter workaround will work with Visio's methods.
Unless there are actual late bound requirements here, it likely easier to
write wrapper calls using the Visio interfaces for any method that is
actually needed and ignore the rest. If there no need to call them then
there isn't any work to do. Most of Visio safearray methods are performance
oriented or drawing oriented.
I have timelines and it may not be feasable to learn how to use #import
by hand and write all those wrapper functions by hand.
[mai-lan] Note: #import can be used to create wrapper classes for you. To
get it to generate smart pointer wrapper classes, do something like
#import said:
How can I find out which methods use safe arrays?
[mailan] If you used MFC to generate your wrapper classes, it will give you
an error in the generated file each time it encounters one. The error
format is something like:
// method 'DropMany' not emitted because of invalid return type or parameter
type
I'll take a look at this. I actually have AddAdvise working via the
2002 SDK.
[mai-lan] Use that or a variation on it and you should be fine.
Note: The class created for you by your wrapper generator for IVisEventProc
is useless because Visio doesn't implement the IVisEvenProc interface. The
interface is defined in Visio's typelib because it's an important part of
its event handling communication protocol. The code in AddSink.h/cpp
implements the full COM interface for you. Much of the code in
AddSink.h/cpp can be used in C as well as C++ by design.


But its in a non-OO way and I am using vaoObjectWrap to get a
Visio Application handle. Using vaoObjectWrap is particularly bad, it
looks like I am getting a conflict that prevents me from saving drawings.
[mai-lan] Don't use vaoObjectWrapper to get the Application in the control
context. This mechanism works well with standalone Visio because it tries
to connect to or create the standalone Visio application using standards COM
calls provided by the Windows API. If you're in the control context, you
don't want that. Get the application object by navigating back from the
control object using either its .Document or .Window property both of which
have an .Application property.
 
S

Scott Metzger

Mai-lan [MS] wrote:
[mai-lan] Don't use vaoObjectWrapper to get the Application in the control
context. This mechanism works well with standalone Visio because it tries
to connect to or create the standalone Visio application using standards COM
calls provided by the Windows API. If you're in the control context, you
don't want that. Get the application object by navigating back from the
control object using either its .Document or .Window property both of which
have an .Application property.
-----------------

Yes, I can get an Application object via the Drawing Control.

However, the 2002 SDK AddAdvise needs an Application object from the
SDK. This Application object is needed to create the event list for
which the AddAdvise is a member. These "Applications" are different
objects. I have only seen one way to get a "2002 SDK Application"
object and that is via vaoGetObjectWrapper.

Do you know of a way to get a 2002 SDK Application object from a 2003
Typelib imported Application object?
Or, how to create a 2002 SDK EventList object from the 2003 Typelib
imported Application Object?

Thanks,
Scott
 
S

Scott Metzger

Mai-lan [MS] wrote:
[mailan] If you used MFC to generate your wrapper classes, it will give you
an error in the generated file each time it encounters one. The error
format is something like:
// method 'DropMany' not emitted because of invalid return type or parameter
type
------------
[Scott]
I did a search for 'invalid' in all my generated files and didn't get
any hits. I also searched for 'emitted', 'not' and still didn't find
any errors.

Here is what was generated for DropMany...
short DropMany(SAFEARRAY * * ObjectsToInstance, SAFEARRAY * * xyArray,
SAFEARRAY * * IDArray)
{
short result;
static BYTE parms[] = VTS_UNKNOWN VTS_UNKNOWN VTS_UNKNOWN ;
InvokeHelper(0x5c, DISPATCH_METHOD, VT_I2, (void*)&result, parms,
ObjectsToInstance, xyArray, IDArray);
return result;
}

Is that going to work?

Thanks,
Scott Metzger
 
M

Mai-lan [MS]

Hi, Scott: I wouldn't recommend trying to do either one of these approaches. The Visio 2003 SDK will be coming out shortly with the typelibs that you'll need -- it'll be more effective to use that.

Thanks,
Mai-lan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top