import theserver.*; import java.awt.*; import java.awt.event.*; public class TheControlMultiThread{ int mainThreadID = 0; public int objectThreadID = 0; Frame theWindow; Label nameLabel; Panel thePanel; WindowHandler winEvent; ComObjectThread comThread; public static void main(String args[]){ TheControlMultiThread ComControl = new TheControlMultiThread(); } public TheControlMultiThread(){ //This thread will also have it's own message loop com.ms.com.ComLib.declareMessagePumpThread(); mainThreadID = com.ms.win32.Kernel32.GetCurrentThreadId(); comThread = new ComObjectThread(this); comThread.start(); //we'll initialize the object and start up the connection pt //We should find some way to block the main thead until the com connections are set, but this //is a simple project and I am not going to worry about it. Since we have the id's of both threads //we could define msg that the object thread sends to the main thread saying it's got the connections //setup startGUI(); com.ms.win32.MSG mainThreadmsg = new com.ms.win32.MSG(); while (com.ms.win32.User32.GetMessage(mainThreadmsg, 0, 0, 0)) { com.ms.win32.User32.TranslateMessage(mainThreadmsg); if (mainThreadmsg.message==com.ms.win32.win.WM_QUIT) break; com.ms.win32.User32.DispatchMessage(mainThreadmsg); } System.exit(0); } void startGUI(){ theWindow = new Frame("420 DCOM Project - The Control - Java Imitator"); theWindow.setLayout(new BorderLayout()); //theWindow.setSize(300,300); thePanel = new Panel(); nameLabel = new Label("Kishore Doshi's Java ActiveX Imitator"); thePanel.setLayout(new BorderLayout()); thePanel.add(nameLabel, BorderLayout.CENTER); thePanel.setBackground(Color.green); theWindow.setVisible(true); theWindow.add(thePanel, BorderLayout.CENTER); winEvent = new WindowHandler(theWindow, mainThreadID, objectThreadID); theWindow.addWindowListener(winEvent); } public void ChangeColor(long lNewValue){ //Called from the sink if( lNewValue == 2 ) thePanel.setBackground(Color.blue); else if( lNewValue == 1 ) thePanel.setBackground(Color.red); else //Stick with the default color thePanel.setBackground(Color.green); thePanel.repaint(10); theWindow.repaint(10); } } class ComObjectThread extends Thread{ //Data this thread manipulates TheControlMultiThread theControl; ITheServerComObject theServer; TheSink sink; com.ms.com.ConnectionPointCookie theConPt; public ComObjectThread(TheControlMultiThread theControl){ super(); this.theControl = theControl; //We need to see the main program's public data member for thread ID } public void run(){ //has it's own message loop, manages the object and the connection pt try{ com.ms.com.ComLib.declareMessagePumpThread(); //This is inside the object thread so we set the objectThreadID theControl.objectThreadID = com.ms.win32.Kernel32.GetCurrentThreadId(); theServer = (ITheServerComObject) new TheServerComObject(); //Give the server some time to come up sleep(1000); //setup the connection pt sink = new TheSink(); sink.SetParent(theControl); theConPt = new com.ms.com.ConnectionPointCookie(theServer, sink, Class.forName("theserver.IMySinkID")); com.ms.win32.MSG objectThreadmsg = new com.ms.win32.MSG(); while (com.ms.win32.User32.GetMessage(objectThreadmsg, 0, 0, 0)) { com.ms.win32.User32.TranslateMessage(objectThreadmsg); if (objectThreadmsg.message==com.ms.win32.win.WM_QUIT) break; com.ms.win32.User32.DispatchMessage(objectThreadmsg); } theConPt.disconnect(); com.ms.com.ComLib.release(theServer); Thread.sleep(1000); System.exit(0); } catch(ClassNotFoundException ex){ System.out.println("Could not load the class for the Sink Interface"); com.ms.com.ComLib.release(theServer); System.exit(0); } catch(Exception ii){} } } class TheSink implements IMySinkID{ //Private Objects - Here we hold a reference to the control TheControlMultiThread parentControl; //Methods - No constructor go with the default public void SetParent(TheControlMultiThread parentControl){ this.parentControl = parentControl; } public void RecieveNewData(int lNewValue){ parentControl.ChangeColor(lNewValue); } } class WindowHandler extends WindowAdapter{ Frame theWindow; int mainThreadID; int objectThreadID; public WindowHandler(Frame theWindow, int mainThreadID, int objectThreadID){ this.theWindow = theWindow; this.mainThreadID = mainThreadID; this.objectThreadID = objectThreadID; } public void windowClosing(WindowEvent evt){ theWindow.dispose(); //kill the worker thread with the objects first com.ms.win32.User32.PostThreadMessage(objectThreadID, com.ms.win32.win.WM_QUIT, 0, 0); try{ Thread.sleep(1000); } catch(Exception ii) {} //now kill the main thread com.ms.win32.User32.PostThreadMessage(mainThreadID, com.ms.win32.win.WM_QUIT, 0, 0); } }