Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
developer
active.documents
automation
binary.file_format
clipboard.dde
com.add_ins
hosting.controls
internet_other
office.sdks
officedev
officedev.other
outlook.forms
outlook.vba
smarttags
vba
web.components
  
 
date: Mon, 7 Mar 2005 13:57:02 -0800,    group: microsoft.public.office.developer.active.documents        back       


PowerPoint DocumentWindows Collection Issue   
Okay COM Interop C# Experts, here's a toughie:

I'm hosting PowerPoint in a .NET UserControl I created using 
WebBrowserControl.  Note, the important part about this whole deal is 
PowerPoint creates and *runs* a slideshow.  That's why, when you open a PPT 
document in the browser, it's full-screen and moves from page to page with 
clickity clicks.  You can NOT get it into any other mode via any "straight 
forward" means that I'm aware of.

Now, what I show below took me a long time with much sweat and tears to 
figure out.  Basically, you need to do some GetType() and InvokeMember() 
stuff to get the SlideShowView, turn it off with the .Exit() member function 
(via the late-bound Invoke), and then you can get the DocumentWindows object 
via an InvokeMember.  

Note that the DocumentWindows object is a Collection which has, as 
collection members, PowerPoint DocumentWindow object.  Here's how I would 
*expect* to work with these values via any "normal" type means in C#, more or 
less:

using PowerPoint.Interop; (load the PowerPoint Primary Interop Assembly).  
I'm using Office 2003.

PowerPoint.DocumentWindows myDocWindows = (collection gathered via magical 
means to see below);
PowerPoint.DocumentWindow = myDocWindows[1];

That should work, in theory.  In practice, it doesn't

First. let me state that things in this fashion work differently in a Form 
control versus a User Control.  Meaning, if you create a Form and add the 
WebBrowserControl, you'll be able to do stuff you can NOT do if you create a 
Windows Control Library in C#.  With that said, here's basically what I'm 
doing:

In the NavigateComplete2 callback:

private void wbControl_NavigateComplete2(object sender, 
AxSHDocVw.DWebBrowserEvents2_NavigateComplete2Event e)

			//Object Defines for Any Office Application
			//We need these objects for all documents viewed regarless
			//of which application loads the document

			//Create the OFParameters object for use as needed below
			object[] OFParameters = null;
			
			//The "object" is a member of the event as pDisp
			Object o = e.pDisp;

			//Generic "Document" object returned.
			//This is a "late binding" call which gets the object
			oDocument = 
o.GetType().InvokeMember("Document",BindingFlags.GetProperty,null,o,null);

			//Generic "Application" object -- late bound call.
			Object oApplication = 
o.GetType().InvokeMember("Application",BindingFlags.GetProperty,null,oDocument,null);

			//Every generic "Application" object has a "Name" property which
			//describes the program opening the document
			Object oName = o.GetType().InvokeMember("Name",BindingFlags.GetProperty 
,null,oApplication,null);

			//Unnecessary message box to "test" that this callback, 
NavigateComplete2, did in fact fire.
			MessageBox.Show("Viewing Office document with " + oName.ToString());


			if (oName.ToString() == "Microsoft PowerPoint")
			{
				try			//Attempting to handle the errors
				{
					//Unnecessary Message Box to tell us we're withing
					//the PowerPoint block.
					MessageBox.Show("Inside PowerPoint Block");

					//Note:  Everything below, except the CommandBar stuff
					//is done via the "late binding" methods -- including
					//calling member fuctions, etc.

					//Casting each of these object types as their "real" types
					//and using them does NOT work and will generate an error
					//which is NOT caught in this try/catch block.

					//Desired Return Type:  PowerPoint Presentation
					//PowerPoint Presentation Object
					Object pptPresentation = o.GetType().InvokeMember("ActivePresentation", 
BindingFlags.GetProperty, null, oApplication, null);

					//Desired Return Type:  PowerPoint SlideShowWindow object
					Object pptSlideShowWindow = 
pptPresentation.GetType().InvokeMember("SlideShowWindow", 
BindingFlags.GetProperty, null, pptPresentation, null);
			
					//Need the PowerPoint SlideShowView object from the PowerPoint 
SlideShowWindow object
					Object pptSlideShowView = 
pptSlideShowWindow.GetType().InvokeMember("View", BindingFlags.GetProperty, 
null, pptSlideShowWindow, null);
						
					//Important View Property for us:  SlideShowView State
					Object pptSlideShowViewState = 
pptSlideShowView.GetType().InvokeMember("State", BindingFlags.GetProperty, 
null, pptSlideShowView, null);
					
					//Ignore this for now.  I *may* need it later, so keeping
					//it in the code.
					//OFInvokeParams = new Object[1];
					//OFInvokeParams[0] = 0;

					//Late-bound "Invoke" on the Exit() method
					Object pptExitView = pptSlideShowView.GetType().InvokeMember("Exit", 
BindingFlags.InvokeMethod, null, pptSlideShowView, null);

					//Desired Return Type:  Windows from Presentation which represents a 
PowerPoint.DocumentWindows Collection
					//NOTE:  We can not successfully get the Windows until AFTER we shut 
down the SlideShow
					// -- this doesn't work --- PowerPoint.DocumentWindows 
pptSlideShowWindows = 
(PowerPoint.DocumentWindows)pptPresentation.GetType().InvokeMember("Windows", 
BindingFlags.GetProperty, null, pptPresentation, null);
					Object pptSlideShowWindows = 
pptPresentation.GetType().InvokeMember("Windows", BindingFlags.GetProperty, 
null, pptPresentation, null);
					Object oCount = pptSlideShowWindows.GetType().InvokeMember("Count", 
BindingFlags.GetProperty, null, pptSlideShowWindows, null);
					MessageBox.Show("Number of PowerPoint Document Windows is/are " + 
oCount.ToString());
					
********************************NOTHING BELOW THIS AREA 
WORKS********************************************
					//Object pptDocWindows = 
pptPresentation.GetType().InvokeMember("Windows", BindingFlags.GetProperty, 
null, pptPresentation, null);
					//System.Reflection.Binder myBinder;
					//PowerPoint.DocumentWindow myDocWindow;
					//System.Globalization.CultureInfo myCulture;
					
					//myBinder.ChangeType(pptDocWindows, myDocWindow.GetType(), myCulture);

					//Desired Return Type:  Single Window from the Windows Collection.
					//OFParameters = new Object[1];
					//OFParameters[0] = 1;
					//System.Int32 DocIndexValue = 1;
					//Object pptDocumentWindow = 
pptSlideShowWindows.GetType().InvokeMember("_Index", 
BindingFlags.InvokeMethod, null, pptSlideShowWindows, new object[] 
{DocIndexValue});
					 System.Collections.IEnumerator myEnum = 
(System.Collections.IEnumerator)pptSlideShowWindows.GetType().InvokeMember("GetEnumerator", BindingFlags.InvokeMethod, null, pptSlideShowWindows, null);

********************************NOTHING ABOVE THIS AREA 
WORKS********************************************

					//CommandBars ia a collection of CommandBar values
					//Casting works here.  I don't have a clue why.
					CommandBars oCommandBars;
					oCommandBars = 
(CommandBars)pptPresentation.GetType().InvokeMember("CommandBars", 
BindingFlags.GetProperty , null, pptPresentation ,null);

					//Grab the "Formatting" menu as I want it OFF.
					CommandBar oReviewingBar = oCommandBars["Formatting"];

					//Grab the "Drawing" menu (commandbar) as I also want this OFF.
					CommandBar oDrawingBar = oCommandBars["Drawing"];

					//Using "Visible" doesn't work here, so using "Enabled" instead.
					//Turns off both extra Command Bars from the menu.  Only
					//the "Standard" bar is available.
					oReviewingBar.Enabled = false;
					oDrawingBar.Enabled = false;
				}
				catch (Exception myException)
				{
					MessageBox.Show("Error occurred " + myException.Message.ToString());
				}

Note:  First I get the Application, then the ActivePresentation, then the 
SlideShowWindow, then the SlideShowView, then I turn it off with the .Exit() 
method.

Only after that, can I get the DocumentWindows object which is retrieved via 
the "Windows" property of the Presentation object.

Now, the CommandBar stuff works, so I just left it in there for a reference 
in case anyone else wants to see how to do that with PowerPoint.  
You can see some of the stuff I'm trying and commenting out.  Now, you'd 
think that:

Object pptDocumentWindow = 
pptSlideShowWindows.GetType().InvokeMember("DocumentWindow", 
BindingFlags.GetProperty, null, pptSlideShowWindows, new object[] 
{DocIndexValue});

I've also tried:

Object pptDocumentWindow = 
pptSlideShowWindows.GetType().InvokeMember("this", BindingFlags.GetProperty, 
null, pptSlideShowWindows, new object[] {DocIndexValue});

and a few others.

*would* work and return the collection window at index 1 (I'm assuming the 
indexes start at 1 rather than 0 here).

Regardless, the errors I'm getting are "Error occurred Unknown name" (in the 
catch messagebox).  This tells me, and I'm only guessing here, that the 
"name" parameter which is the first parameter in the InvokeMember() function, 
is incorrect. 

However, I'm using the Object Browser part of Visual Studio .NET 2003 to 
view the object via the Primary Interop Assembly, and I don't see any other 
way to "name" this value.

Likewise, for some reason, the objects all return as System._COMObject and 
hence are not really "viewable" via a Quickwatch.  Interestingly enough, Word 
and Excel object cast really well and are viewable.  PowerPoint, however, 
doesn't play well in the COM to .NET interop in that fashion.

Hence, I'm more or less blindly groping for named objects within objects via 
the InvokeMember method.  

WHAT I NEED:
=========

I need a way to get the DocumentWindow object because ultimately, I need the 
ViewType property from that for which I can set it to ppViewTypeNormal and 
hence get a PowerPoint presentation in "normal" view mode hosted within a 
WebBrowserControl in an Internet Explorer session.

Thanks!
---Dan---
date: Mon, 7 Mar 2005 13:57:02 -0800   author:   AmiciDan

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us