I have developed a very quick replacement for the OLE Container Control that you had in VB6.
I just did it in rush so it just supports basic properties as DisplayType Icon or Content
The content functionality is performed using the Vista feature for content preview. I would have tried using a
WebBrowser control but in new versions of Office, the default is not showing the document on the Browser and
it might be difficult to change the registry in some vista or Win7 environments.
The following picture show the OLEContainer inside a Windows Form.
This is the container with the Display set to content:
And the container with display set to icon:
You can call the CreateLink and you can also use the DoVerb Open.
I have attached the example source code in this post.
ReplaceOLEContainer.zip (100.69 kb)
UPDATE
NOTE: I friend also sent me a link to this article in CodeProject which is very similar: http://www.codeproject.com/Tips/487566/OLE-container-surrogate-for-NET
NOTE: This solution only applies for read-only. If you wan to edit your files, then you need a real ActiveX container. MS used to have a sample OCX called DSOFramer that allows you to do that. Warning: this sample is no longer supported by MS becuase it said to have issues However I have used it in the past and it worked fine in some simple scenarios. I have added the control and its source to this post. There is a commercial product from Edraw http://www.edrawsoft.com/edword.php that is supported by them and has samples for C# and VB.NET
NOTE: Another approach, embed the application in your windows form.
In general what you should do is use the SetParent, SetWindowLong and MoveWindow APIs to embed the application. Something like this:
var filename = openFileDialog1.FileName;
var officeApplicationProgID = "Excel.Application";
var officeApplicationType = Type.GetTypeFromProgID(officeApplicationProgID, false);
dynamic officeApplication = Activator.CreateInstance(officeApplicationType);
officeApplication.Workbooks.Open(filename);
int pid = 0;
GetWindowThreadProcessId(officeApplication.HWnd, out pid);
officeApplication.Visible = true;
//officeApplication.Visible = false;
var process = Process.GetProcessById(pid);
var panel = new Panel();
panel.Location = new Point(0, 0);
panel.Size = new Size(this.Size.Width, this.Size.Height);
var processHandle = process.MainWindowHandle;
SetParent(processHandle, panel.Handle);
SetWindowLong(processHandle, GWL_STYLE, WS_VISIBLE + WS_MAXIMIZE + WS_CHILD);
MoveWindow(processHandle, 0, 0, panel.Width, panel.Height, true);
this.mainBody.Controls.Add(panel);
Figure: Example of technique of hosting Excel inside a Windows Form Application
I have attached a sample project. (Remember to free your resources, and close the excel App before closing your application, I skipped that from this sample)
DsoFramer.zip (463.42 kb)
ExampleOfEmbeddingExcelInWindowsForm.zip (53.76 kb)
In VB6 ActiveX-EXEs or ActiveX OLE Server where used for several
reasons. Sometimes it was performance (because it allowed you to run
your code in another process) and sometimes as way to share resources
between several applications, like connection information, database
connections, mainframe info, etc.
During migration some of this ActiveX-Exes can be migrated as simple
Assembly DLLs, but other require more attention. Specially if they have
global variables that hold state shared by several programs.
In that is your case what are your options then?
1. Convert those ActiveX-Exes to Windows Services.
This option is simple. You modify your migrated assembly to work as a Windows Service. The easier way to do that is:
a) Start Microsoft Visual Studio 2005\2008
b) Go to File\New…\Project… and Select Windows Service
That will generated code like:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
public Service1() { InitializeComponent(); }
protected override void OnStart(string[] args) { }
protected override void OnStop() { }
}
}
c) Add a reference to the Remoting Assemblies: System.Runtime.Remoting;
d) Modify the previous code:
Add two using statements like:
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
Add a simple event log for tracing:
private static EventLog evt = new EventLog(“Application”);
private static string SVC_NAME = “ActiveX Server Example Svc”;
And modify the OnStart and OnStop methods to look like:
protected override void OnStart(string[] args)
{
HttpChannel chnl = new HttpChannel(1234);
ChannelServices.RegisterChannel(chnl,true );
RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyClass), “MyClass.soap”, WellKnownObjectMode.Singleton);
evt.WriteEntry(SVC_NAME + ” Started”);
}
protected override void OnStop() { evt.WriteEntry(SVC_NAME +” Stoppped”); }
Also make sure that MyClass extends MarshalByRefClass
2. Convert those ActiveX-Exes using the Artinsoft ActiveX migration helpers.
Sometimes, you need your migrated application to replicate some of
the original ActiveX EXE \OLE DLL VB6 characteristics. For example you
need your ActiveX-EXE to start just when the first instance is created
and to resemble the VB6 logic for Process creation\destruction.
For that purpose Artinsoft has created some helpers that our
migration tool is able to automatically use in the generated code if it
detects that this functionality is needed.
The code will then be changed from:
Dim myInstance As New MyProject.MyClass
To the following Helper method:
myInstance = MyProjectFactory.Create< MyProject.MyClass>(myInstance);
And destroy calls can be changed to the following Helper method:
myInstance= MyProjectFactory.Dispose<MyProject.MyClass >( myInstance);
The migration tool will modify your ActiveX-EXEs or OLE Servers to
be Windows EXE and the helper will then locate the assembly that
contains the desired Class, create an instance and initilize a Remoting
channel to the desired classes. Settings as SingleUse and MultiUse are
also taken care by the helpers.
3. Other possible alternatives are using WFC and COM+ that I will comment in another post.