Re: ROOT used inside MFC MDI app

Valery Fine (fine@bnl.gov)
Mon, 2 Mar 1998 17:39:33 -0500


On 2 Mar 98 at 13:28, William J Deninger wrote:

> From: "William J Deninger" <deninger@uiuc.edu>
> To: "roottalk" <roottalk@hpsalo.cern.ch>
> Subject: ROOT used inside MFC MDI app
> Date: Mon, 2 Mar 1998 13:28:11 -0600

> keywords:
> MS - Microsoft
> MFC - Microsoft Foundation Class
> MDI - Multiple Document Interface
>
>
> >From previous roottalk correspondences, I remember mentioned that
> the WinNT/Win95 port actually has two threads (composing two message
> handling loops): one for the CINT commands, the other for CINT window
> messages.

First is build a WIN32 Console application !!!
Why? By historic reason and because ROOT has a so-called batch mode.
It is very WIN32 console application anyway.

It has 3 threads (the last one was introduced 7 momths ago)

1. Console - initial appl thread
2. Main CINT thread to call CINT
3. Windows - to manage Windows

> One of these (I think) is the initial application thread.

Right, It it thread #1.

> The MFC application itself has a message loop (virtual CWndApp::Run()) which
> can be overloaded in order to change application behavior. The MFC
> message loop traditionally is the application thread because it
> makes no special thread provisions
^

> What I'm trying to do in the simplest of terms is get the ROOT
> canvases attached (as child windows) to the MDI application main
> frame window, and have the all window messaging handled by the same
> application thread message loop.

> The ROOT CINT command thread would be an additional thread worker thread.

See my first remark. The current ROOT is designed as WIN32 Console
application. I doesn't create any console itself. It expects the OS
creates the console (a'la UNIX). Changing things may lead to some
significant change in the WIN32 classes.

>
> Adding WS_EX_MDICHILD to the window style and replacing the NULL
> window handle with the HWND of the mainframe in
> TGWin32WindowsObject::CreateWindowsObject was a failed attempt, but
> I had not combined CWndApp and ROOT message loops. Does anyone in
> ROOTLAND have a suggestion for implementing this, or perhaps know of
> a place I might go for more information?
>

Uhhh, It seems to me it would be not easy.

I have no clue but would like to provide a few tips.

1. TGWin32WindowsObject is derived from TGWin32Object
2. TGWin32Object has the data member:

TWin32CallBackList fWinAction; // List of the callback functions to manage the events tips to let

and the method:
LRESULT CallCallback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

Since you are making WIN32 application I hope you may recognize the
list of the parameter for "CallCallback" is just a "native" WIN32 message.

3. Now I am calling your attention to WIN32_GWIN32.cxx file.

Here one can find the Windows Procedure for all ROOT windows:

LRESULT APIENTRY WndROOT(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//////////////////////////////////////////////////////////////////////////
// //
// Main Universal Windows procedure to manage all dispatched events //
// //
//////////////////////////////////////////////////////////////////////////

if (uMsg == WM_CREATE) return ::OnCreate(hwnd, uMsg, wParam, lParam);
else {
TGWin32Object* lpWin32Object = ((TGWin32Object*)GetWindowLong(hwnd,GWL_USERDATA));
if (lpWin32Object) {
((TGWin32WindowsObject *)lpWin32Object)->StartPaint();
LRESULT ret_value = lpWin32Object->CallCallback(hwnd, uMsg, wParam, lParam);
((TGWin32WindowsObject *)lpWin32Object)->FinishPaint();
return ret_value;
}
else return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}

Just you may call this WinProc for all ROOT MDI you carted it
will (may be ?) live.

4. The last, How to manage the Windows thread ? That's question for you. But
I'd like to call your attention to

unsigned int _stdcall ROOT_MsgLoop(HANDLE ThrSem)
//*-*-*-*-*-*-*-*-*-*-*-*-* ROOT_MsgLoop*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ============
//*-* Launch a separate thread to handle the ROOTCLASS messages
//*-*
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
{

When ROOT is going to create any Canvas it sends the message
IX_OPNWI.
You have to catch the FIRST message and create the object of
CWndApp *ROOT_MDI_Parent = new CWndApp(...),
then call

((TGWin32WindowsObject*)(msg.lParam))->Win32CreateObject();

Very likely you have to supply your own version of

ROOT_MsgLoop(HANDLE ThrSem).

It should not difficaul since it is a simple function, and it belongs
NO class at all.

Hope this helps,
With my regards,
Valery
=================================================================
Dr. Valeri Faine (Fine)
------------------- Phone: +1 516 344 7806
Brookhaven National Laboratory FAX : +1 516 344 4206
Bldg. 510A /STAR mailto:fine@rsgi01.rhic.bnl.gov
Upton, New York, 11973-5000 http://nicewww.cern.ch/~fine
USA

Dr. Valery Fine Telex : 911621 dubna su
-----------
LCTA/Joint Inst.for Nuclear Res. Phone : +7 09621 6 40 80
141980 Dubna, Moscow region Fax : +7 09621 6 51 45
Russia mailto:fine@main1.jinr.dubna.su