I would like to know how we can use TCanvas in a CLR application (under Visual Studio C++ Express 2008), so how I can integrate ROOT with the .Net Framework 3.5.
I have just seen the page http://root.cern.ch/root/Version51000.news.html, so I know that it’s possible for example in a Win32 application (with MFC). But this kind of structure is not accepted by the CLR application.
I ask that for 2 reasons:
In a CLR application I can use the class TApplication (to maintaining open the TCanvas), but when I use TApplication::Run() my application stops, and I must have to close the TCanvas window to continue to use the application. So if you know a way to open the TCanvas as a DialogBox, please explain to me!!!
I search for many weeks a way to embed a TCanvas in a CLR window, but I cannot find a good and easy solution, if you know a good solution for that explain me, please.
I thank any kind of help!!!
As you have probably already guessed, solving a problem like this with ROOT is like a Jackson homework problem: it is easy once you know the magic steps.
I fought my way through this several months ago and it was only via emails to Axel and Bertrand that I was able to make sense of it. I think the event loop processing has gone through lots of iterations since the ROOT web page you mention. It actually isn’t that hard. There are several things to keep in mind:
WinForms and Win32 use the old rendering technology, which means that ROOT does as well. This means that if you have two TCanvas on a WinForms app at the same and they overlap they will fight for control in (what appears to me to be) non-deterministic ways.
If you are doing WPF, then you will run into the air-space problem – WPF uses the new rendering engine (which is much nicer) and ROOT the old one - the old one, which is low level, always wins - so you can’t put a WPF item on top in a TCanvas.
With that in mind… I’ve done this in C#. I’ve written a set of C++ wrapper generator that creates .NET assempblies that call into all the public ROOT libraries. It isn’t really ready for primetime, however, because… well, I haven’t had the time to devote to it (ROOT is a moving target and I’ve not figured out a good automated way to follow it). However, the technique I use to create a control that holds a TCanvas can easily be lifted from teh project.
On sourceforge, look at the ROOT.NET project (rootdotnet.cvs.sourceforge.net/r … iew=markup).
It has been a while since I actually coded this – but it works just fine. I was using it in a small utility I wrote last night. You can translate direction from the C# that is up there to the modern managed C++.
Things to remember
- TApplication, as you point out, is a little tricky. The object ROOTEventCoordinator (next to the TCanvasControl) has code for that.
- Create a TApplication with no arguments (see the ROOTEventCoordinator’s default ctor).
- Call SetReturnFromRun(true) on your TApplication object.
Keep track of every single TCanvas object you create and display.
During app idle time, better if you may be doing lots of CPU, fire a timer (I fire a timer every 50ms, which seems to be good enough if you are doing animation - like watching a filling TH1F). During idle time call the TApplication::StartIdling, then call TSystem::InnerLoop, and then call TApplication::StopIdling. I’ve been careful to do this in the GUI thread, but Bertrand has assured me this isn’t neceassary. However, when I don’t I do see a random crash every now and then. I’ve seen one or two crashes when I’m trying to update multiple TCanvas’s all at the same time over a long period of time with this scheme - seems like there is a lock out of place somewhere, but it is so infrequent (i.e. once a month) that I’ve never spent time trying to track it down.
I Created a new UserControl to host the TCanvas. I had it totally take over the UserControl – I can then compose it. The design-time experience isn’t all that great, but it works. I’d suggest going the usercontrol direction because you can then deal with the UserControl win32 handle – hand that off to ROOT – and it “just works” (seriously – once I had the above StartIdel, etc., it was minutes until I had a plot displayed).
Feel free to copy and steal all the algorithms you want from the source code I pointed out to you - it is all under the GPL license. You’ll have to translate to managed C++, but that should be pretty darn easy.
And feel free to ask more questions, or if I’ve left out something you think is key post that – then this thread can become a central place of knowledge for the next person that wants to do this.
I found a “solution” to use Root TCanvas, etc… in a Net. Framework application using app.Run() without block the application.
It’s not perfect but just works . And it’s not a embed TCanvas.
Any other contributes or ideas are welcome!!!
PS: You must have to have Root in C:\root.
root+bgw.tar (1.38 MB)