C# and OLEFormat.Object?

  • Thread starter Thread starter Mark
  • Start date Start date
M

Mark

I have a C# add in that inserts a custom active x control
into a worksheet.

Once the object is inserted i can locate the object
through both Shapes and Worksheet.OLEObjects. What I
can't do is figure out how to use the object
programatically.

I added a reference to the object in the Visual Studio
project by importing the object OCX. The reference shows
up as Interop.ActiveXLib and my objects methods and
properties are shown in the object browser under both
interop.ActiveXLib.ImyControl and
interop.ActiveXLib.myControlCtlClass.

I have tried various arrangements of casting the object
returned from both Shapes and Worksheet's OLEFormat.Object
trying to get something that I can use directly with no
success:

ActiveXLib.myControlCtlClass mc =
(ActiveXLib.myControlCtlClass) shape.OLEFormat.Object;

I am writting the add in Visual Studio .Net and it is
running in Excel 2002 Service Pack 1.

What I want to do is to be able to use:
mc.myControlMethod(doIT).

Thanks for the help

Mark
 
Hi Mark,

Thanks for posting in this group.
What is the error message when you convert shape.OLEFormat.Object to
ActiveXLib.myControlCtlClass?
I think may be you can use the typeof operator to determine the type of
shape.OLEFormat.Object.
Maybe you can try to use ActiveXLib.ImyControl to get this interface.
Do you make sure that this object is a ActiveXLib.myControlCtlClass type?

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Content-Class: urn:content-classes:message
| From: "Mark" <[email protected]>
| Sender: "Mark" <[email protected]>
| Subject: C# and OLEFormat.Object?
| Date: Fri, 24 Oct 2003 08:53:01 -0700
| Lines: 32
| Message-ID: <[email protected]>
| MIME-Version: 1.0
| Content-Type: text/plain;
| charset="iso-8859-1"
| Content-Transfer-Encoding: 7bit
| X-Newsreader: Microsoft CDO for Windows 2000
| Thread-Index: AcOaRudJlQHTzFPER3avOahP1Ww40A==
| X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
| Newsgroups: microsoft.public.dotnet.languages.csharp
| Path: cpmsftngxa06.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:193841
| NNTP-Posting-Host: TK2MSFTNGXA12 10.40.1.164
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| I have a C# add in that inserts a custom active x control
| into a worksheet.
|
| Once the object is inserted i can locate the object
| through both Shapes and Worksheet.OLEObjects. What I
| can't do is figure out how to use the object
| programatically.
|
| I added a reference to the object in the Visual Studio
| project by importing the object OCX. The reference shows
| up as Interop.ActiveXLib and my objects methods and
| properties are shown in the object browser under both
| interop.ActiveXLib.ImyControl and
| interop.ActiveXLib.myControlCtlClass.
|
| I have tried various arrangements of casting the object
| returned from both Shapes and Worksheet's OLEFormat.Object
| trying to get something that I can use directly with no
| success:
|
| ActiveXLib.myControlCtlClass mc =
| (ActiveXLib.myControlCtlClass) shape.OLEFormat.Object;
|
| I am writting the add in Visual Studio .Net and it is
| running in Excel 2002 Service Pack 1.
|
| What I want to do is to be able to use:
| mc.myControlMethod(doIT).
|
| Thanks for the help
|
| Mark
|
 
Hi Jeffrey,

The error message i get is "Specified Cast is not valid".
The type of shape.OLEFormat.Object.GetType().FullName;
is System.__ComObject.

I don't know how to dereference System.__ComObject to get
its actual type. (If I did then I might know how to get
to the object that I want to use).


If possible can you please post an example of how this
cast should made in order to work with the actual object?

Thanks

Mark
-----Original Message-----

Hi Mark,

Thanks for posting in this group.
What is the error message when you convert shape.OLEFormat.Object to
ActiveXLib.myControlCtlClass?
I think may be you can use the typeof operator to determine the type of
shape.OLEFormat.Object.
Maybe you can try to use ActiveXLib.ImyControl to get this interface.
Do you make sure that this object is a
ActiveXLib.myControlCtlClass type?
 
Hi Mark,

So far as I know, the cast you used will not work for you because .Net can't retrieve the type information from Interop when you use cast in code
directly. There is no any metadata for the interoped com control so that .Net don't know how to cast this object for you. From my experience, I'd
suggest you can use .Net reflection method to dynamically obtain the type information during runtime and then call the method you want.

Assume there is one user control (ProgID is "Project1.UserControl1") which has one public method Test. Test method only pop-up one window with
"hello world". After the registration to the system, you can use the codes below to execute it.

[C#]
Type t = Type.GetTypeFromProgID("Project1.UserControl1");
Object o = Activator.CreateInstance(t);
t.InvokeMember("Test", BindingFlags.InvokeMethod, null, o, null);

[VB.net]
Dim t As Type = Type.GetTypeFromProgID("Project1.UserControl1")
Dim o As Object = Activator.CreateInstance(t)
o.Test()

In C#, you have to use InvokeMember to execute the Test method. But in VB.net, you can use the o.Test syntax to use the method.

Please note in VB.net, if you type "o.", the IntelliSense window will not tell you there is one Test method for the object because the Test method
information is retrieved from Project1.UserControl1 control at runtime. At coding-time, there is no enough type information making IntelliSense to
find the Test Method.

Furthermore, for your scenario, the control object may have been loaded to the same process with excel worksheet so that you may modify the
Activator.CreateInstance to Activator.GetObject.

Please feel free to let me know if you have any questions.

Does this answer your question? Thank you for using Microsoft NewsGroup!

Wei-Dong Xu
Microsoft Product Support Services
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Wei-Dong Xu,

Thank you for your help. We are soooo close. Your
suggestions allow me to get a little farther.

I am confused by the Activator.GetObject call. The second
parameter is a URL. Since the control that I want to talk
to is in the same instance of Excel as the add in I don't
know what to use for this argument.

// Programatically add the object to the spreadsheet
Microsoft.Office.Interop.Excel.Shape shape =
ws.Shapes.AddOLEObject(
"MyDomain.MyCtl.1",
Type.Missing,
false,
false,
Type.Missing,
Type.Missing,
Type.Missing,
1, 1, 300, 300);

// Create argument to pass to control's method.
object [] args = {(object) "SomeArgument"};

// Get type of control
Type abCtl1Type = Type.GetTypeFromProgID(
"MyDomain.MyCtl.1");

// What do I use for the second argument if the instance
of abCtl1Type is the instance I automatically inserted
into the spreadsheet with the AddOLEObject call above?

ActiveXLib.MyCtlClass abCtl1Obj =
(ActiveXLib.MyCtlClass) Activator.GetObject
(abCtl1Type, ?????);

abCtl1Type.InvokeMember("OpenApplication",
BindingFlags.InvokeMethod, null, abCtl1Obj, args);

Thanks

Mark
-----Original Message-----
Hi Mark,

So far as I know, the cast you used will not work for you
because .Net can't retrieve the type information from
Interop when you use cast in code
directly. There is no any metadata for the interoped com
control so that .Net don't know how to cast this object
for you. From my experience, I'd
suggest you can use .Net reflection method to dynamically
obtain the type information during runtime and then call
the method you want.
Assume there is one user control (ProgID
is "Project1.UserControl1") which has one public method
Test. Test method only pop-up one window with
"hello world". After the registration to the system, you
can use the codes below to execute it.
[C#]
Type t = Type.GetTypeFromProgID("Project1.UserControl1");
Object o = Activator.CreateInstance(t);
t.InvokeMember("Test", BindingFlags.InvokeMethod, null, o, null);

[VB.net]
Dim t As Type = Type.GetTypeFromProgID ("Project1.UserControl1")
Dim o As Object = Activator.CreateInstance(t)
o.Test()

In C#, you have to use InvokeMember to execute the Test
method. But in VB.net, you can use the o.Test syntax to
use the method.
Please note in VB.net, if you type "o.", the IntelliSense
window will not tell you there is one Test method for the
object because the Test method
information is retrieved from Project1.UserControl1
control at runtime. At coding-time, there is no enough
type information making IntelliSense to
find the Test Method.

Furthermore, for your scenario, the control object may
have been loaded to the same process with excel worksheet
so that you may modify the
 
Hi Mark,

Thank you for replying and the codes!

From my understanding to your issue now, I'd suggest you can use Activator.CreateInstance in this scenario. It will be appreciated you tell the
result.

Please feel free to let me know if you have any further questions.

Does this answer your question? Thank you for using Microsoft NewsGroup!

Wei-Dong Xu
Microsoft Product Support Services
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Wei-Dong Xu

I have tried multiple calls to CreateObject and none
appear to let me access the current instance of the
object. I don't get an exception so i am assuming that i
am creating a new object in all cases.

Here is sample code of what i am doing.

// Programatically add the object to the spreadsheet
Microsoft.Office.Interop.Excel.Shape shape =
ws.Shapes.AddOLEObject(
"MyDomain.MyCtl.1",
Type.Missing,
false,
false,
Type.Missing,
Type.Missing,
Type.Missing,
1, 1, 300, 300);


// Get type of control
Type abCtl1Type = Type.GetTypeFromProgID(
"MyDomain.MyCtl.1");

// I'm not sure what the first agument should point to;
// the ActiveXLib, or something having to do with Excel.
// ActiveXLib works in this call.
// Microsoft.Office.Interop.Excel does not work here
ObjectHandle obj = (ObjectHandle) Activator.CreateInstance(
"Interop.ActiveXLib",
abCtl1Type.FullName);

ActiveXLib.MyCtlClass abCtl1Obj =
(ActiveXLib.MyCtlClass) obj.Unwrap();

abCtl1Obj.MethodToDisplaySomethingInControl("String to
display");

No exception is thrown and nothing is displayed in the
visible control. Since I don't get an exception I assume
a new hidden control has been instantiated. PLEASE PLEASE
PLEASE PROVIDE A TESTED EXAMPLE OF HOW TO CALL THE
EXISTING OBJECT.

Thanks

Mark

-----Original Message-----
Hi Mark,

Thank you for replying and the codes!

From my understanding to your issue now, I'd suggest you
can use Activator.CreateInstance in this scenario. It will
be appreciated you tell the
 
Hello Mark,

In addition to the advice given by Wei-Dong Xu and Jeffrey Tan, you should
be aware that .NET controls are not dependable on anything other than
WebForms, WindowsForms, and IE. The Microsoft Knowledge Base article

311334 INFO: ActiveX Control Containers That Support .NET Controls
http://support.microsoft.com/?id=311334

discusses this behavior and limitation.

This limitation may be superceded in the future.

--------------------
X-Tomcat-ID: 335647672
References: <[email protected]>
<[email protected]>
<[email protected]>
MIME-Version: 1.0
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
From: (e-mail address removed) (Wei-Dong Xu [MSFT])
Organization: Microsoft
Date: Tue, 28 Oct 2003 10:29:02 GMT
Subject: RE: C# and OLEFormat.Object?
X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
Message-ID: <[email protected]>
Newsgroups: microsoft.public.dotnet.languages.csharp
Lines: 14
Path: cpmsftngxa06.phx.gbl
Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:194640
NNTP-Posting-Host: TOMCATIMPORT1 10.201.218.122

Hi Mark,

Thank you for replying and the codes!

From my understanding to your issue now, I'd suggest you can use
Activator.CreateInstance in this scenario. It will be appreciated you tell
the
result.

Please feel free to let me know if you have any further questions.

Does this answer your question? Thank you for using Microsoft NewsGroup!

Wei-Dong Xu
Microsoft Product Support Services
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

Regards,
Chris Jensen[MSFT]

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

Are you secure? For information about the Microsoft Strategic Technology
Protection Program and to order your FREE Security Tool Kit, please visit
<http://www.microsoft.com/security>.
 
Hi Chris,

The ActiveX control is C++ not a .Net. The add in that is
trying to talk to it is written in C#. I did not think
this was a problem. Please let me know if I am mistaken?

Thanks

Mark
-----Original Message-----
Hello Mark,

In addition to the advice given by Wei-Dong Xu and Jeffrey Tan, you should
be aware that .NET controls are not dependable on anything other than
WebForms, WindowsForms, and IE. The Microsoft Knowledge Base article

311334 INFO: ActiveX Control Containers That Support .NET Controls
http://support.microsoft.com/?id=311334

discusses this behavior and limitation.

This limitation may be superceded in the future.

--------------------
X-Tomcat-ID: 335647672
References: <[email protected]>
<[email protected]>
<[email protected]>
MIME-Version: 1.0
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
From: (e-mail address removed) (Wei-Dong Xu [MSFT])
Organization: Microsoft
Date: Tue, 28 Oct 2003 10:29:02 GMT
Subject: RE: C# and OLEFormat.Object?
X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
Message-ID: <[email protected]>
Newsgroups: microsoft.public.dotnet.languages.csharp
Lines: 14
Path: cpmsftngxa06.phx.gbl
Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:194640
NNTP-Posting-Host: TOMCATIMPORT1 10.201.218.122

Hi Mark,

Thank you for replying and the codes!

From my understanding to your issue now, I'd suggest you
can use
Activator.CreateInstance in this scenario. It will be appreciated you tell
the
result.

Please feel free to let me know if you have any further questions.

Does this answer your question? Thank you for using Microsoft NewsGroup!

Wei-Dong Xu
Microsoft Product Support Services
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

Regards,
Chris Jensen[MSFT]

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

Are you secure? For information about the Microsoft Strategic Technology
Protection Program and to order your FREE Security Tool Kit, please visit
<http://www.microsoft.com/security>.


.
 
Hi Mark,

Thank you for replying!

I'd suggest that you can build one marco for your inserted ActiveX control, then you can all the macro in your add-in. In this way, you don't need to
retrieve the object type information of the inserted ActiveX control.

Please feel free to let me know if you have any further questions.

Does this answer your question? Thank you for using Microsoft NewsGroup!

Wei-Dong Xu
Microsoft Product Support Services
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Wei-Dong Xu,

Are you saying that it is impossible to get hold of the
actual object from the add in code that i showed you
before?

I don't understand how a macro helps here. I don't see an
obvious API to create or call such a macro from my C# add
in.

I think you are saying that i should do something like;

application.buildNamedMacroCall("macroName",
stringWithMacroCommands)

application.callTheNamedMacroJustCreated()

PLEASE PROVIDE AN EXAMPLE.

Thank You

Mark
-----Original Message-----
Hi Mark,

Thank you for replying!

I'd suggest that you can build one marco for your
inserted ActiveX control, then you can all the macro in
your add-in. In this way, you don't need to
 
Hi Wei-Dong Xu,

Are you saying that it is impossible to get hold of the
actual object from the add in code that i showed you
before?

I don't understand how a macro helps here. I don't see an
obvious API to create or call such a macro from my C# add
in.

I think you are saying that i should do something like;

application.buildNamedMacroCall("macroName",
stringWithMacroCommands)

application.callTheNamedMacroJustCreated()

PLEASE PROVIDE AN EXAMPLE.

Thank You

Mark
-----Original Message-----
Hi Mark,

Thank you for replying!

I'd suggest that you can build one marco for your
inserted ActiveX control, then you can all the macro in
your add-in. In this way, you don't need to
retrieve the object type information of the inserted ActiveX control.

Please feel free to let me know if you have any further questions.

Does this answer your question? Thank you for using Microsoft NewsGroup!

Wei-Dong Xu
Microsoft Product Support Services
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.


.
..


-----Original Message-----
Hi Mark,

Thank you for replying!

I'd suggest that you can build one marco for your
inserted ActiveX control, then you can all the macro in
your add-in. In this way, you don't need to
 
Hello Mark,

Try the following example, based onthe Microsoft Knowledge Base article
302902:

Add a Project Reference to the Micosoft Excel PIA
Add the following to the Usings
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
Change the declaration of the applicationObject to
private Excel.Application applicationObject;


private void MyButton_Click(CommandBarButton cmdBarbutton,ref bool
cancel)
{
try
{
//Get the workbooks collection.
Excel.Workbooks objBooks_Late =
(Excel.Workbooks)applicationObject.GetType().InvokeMember( "Workbooks",
BindingFlags.GetProperty, null, applicationObject, null );

//Get the active workbook.
object[] Parameters;

Excel.Workbook objBook_Late = objBooks_Late[1];

//Get the worksheets collection.
Excel.Sheets objSheets_Late = objBook_Late.Worksheets;

//Get the first worksheet.
Excel.Worksheet objSheet_Late = (Excel.Worksheet)objSheets_Late[1];

// Get workbook
// TEST LINE #1
Microsoft.Vbe.Interop.VBProject obVBP = objBook_Late.VBProject;

// More Code that creates and inserts strings into a
VBIDE.VBComponent code module.
//¡­¡­
//¡­¡­
}

catch(Exception ex)
{
System.Windows.Forms.MessageBox.Show("Why this Error?: "
+ ex.Message);
}

}

Chris Jensen (Microsoft)
 
Back
Top