Unit TIRobotInterfaces; { This is how the robot and the host application communicate. Note: We use these interfaces in the strict and correct way. An interface is immutable. If you want something different, create a new interface with a new name and GUID. We cheated some with the interfaces in the ActiveX control, but we're not going to do that here. All functions should be called from the main/GUI thread. } Interface Type { Presumably this will correspond to a menu item. } IRobotAction = Interface(IUnknown) ['{02FB5F72-F3F4-465D-9C96-350C3A886734}'] // Is is what you would display in the caption property of a menu item, // button, etc. The return value is valid as long as this action // exists. Once you release your pointer to this action, you should no // longer keep the pointer to the description. Function Description : PChar; StdCall; // Call this when the user selects the menu item. You should call this // from the main/GUI thread. Procedure Perform; StdCall; End; IRobotCallbacks = Interface(IUnknown) ['{38059879-8DAF-4588-8D78-E1B17F8389A2}'] // The robot will call this each time it creates a new window. The main // program might use this to set the always-on-top property of the // window. Procedure NewWindow(Handle : LongWord); StdCall; // The robot will periodically check for upgrades. If and when a newer // version of the library is available we will call this procedure. Procedure OldVersion; StdCall; End; // The right way to implement this is to have the same object implement // this interface and IRobotCallbacks, then to call SetCallbacks on that // object. The right way to use this is to listen to SetCallbacks, and // see if the parameter supports this interface. IRobotCallbacksAction = Interface(IUnknown) ['{0F1F8D4F-3503-46D8-9802-4E3CE8C76079}'] // The robot will call this each time someone double clicks on an // alert, or performs a similar action. Procedure PerformSymbolAction(Symbol : PChar); StdCall; End; IRobotMain = Interface(IUnknown) ['{4422ED99-020A-465D-955F-EFC9A8990092}'] // Call this to receive events from the robot. The robot can only have // 0 or 1 callback objects. If you call this more than once, only the // last one counts. If you call this with Nil, the robot will stop // making callbacks. Procedure SetCallbacks(Callbacks : IRobotCallbacks); StdCall; // Call this before GetNextAction to make sure you are getting the first // action from the list. Call this as many times as needed, to iterate // through the list multiple times. Procedure ResetActionList; StdCall; // Call this to iterate through the list of actions. At the end of the // list you will receive Nil as the result. Function GetNextAction : IRobotAction; StdCall; // Use this to save or restore the layout of the windows. This // information is always saved in the registry. Use Location to specify // which key to use. Use '\' to seperate keys in a path. For example, // 'Software\Advanced Stock Alerts Client\Robot' will make a sub-key // called "Robot" under the // 'HKEY_CURRENT_USER\Software\Advanced Stock Alerts Client' key which // is already used by TI Pro. The root key will always be // HKEY_CURRENT_USER. // // Note: It is safe to call these at any time. If you call SaveLayout // at an inappropriate time, it will be ignored. If you call // RestoreLayout at an inappropriate time, the request will be stored // until we can satisfy it. Procedure SaveLayout(Location : PChar); StdCall; Procedure RestoreLayout(Location : PChar); StdCall; Procedure ShutDown; StdCall; // Call this before showing the main window. It will set the icons for // all windows. Procedure SetIconHandle(Handle : LongWord); StdCall; // Call this before showing the main window. It will set the parent // of each window. This can allow you to use the Delphi style of // windows where minimizing the main window minimizes all windows, // and there is only one window in the task bar. Procedure SetApplicationHandle(Handle : LongWord); StdCall; End; // This contains new features which are not implemented by some older // versions of the DLL. IRobotMain1 = Interface(IRobotMain) ['{6D2C9941-1CDC-4007-8529-4998E7A7B734}'] // This can only be called once. Procedure SetTDALogin(Username, Password : PChar); StdCall; End; IRobotMain2 = Interface(IRobotMain) ['{85CA6049-5408-44FD-AB63-FFD8D0A771BC}'] // The standard dialog boxes fail in QuoteTracker. They should works // everywhere else. Ideally QT would set a special value. But it's // late for that, so now every other program must call this. Procedure AllowNormalDialogBoxes(Value : Boolean); StdCall; End; // This is meant to be a simple wrapper around the Screen variable. The // main program might want to list all of the windows that are available. // For a simple program it could get that info from the Screen variable. // The screen variable for each DLL and for the main program only contains // the windows created by that DLL or program. IRobotWindowList = Interface(IUnknown) ['{5DE79C95-55CF-4A36-988C-6C30EF772AF4}'] Function GetWindowCount : Integer; Function GetWindowName(I : Integer) : PChar; // This pointer is valid until the next call to get window name. Function WindowVisible(I : Integer) : Boolean; Function WindowFloating(I : Integer) : Boolean; Function WindowMinimized(I : Integer) : Boolean; Procedure ShowWindow(I : Integer); // This will do nothing if the window cannot be found. End; // Try to load the library. Return Nil on failure. Function GetRobotMain(FileName : String) : IRobotMain; // Try to convert to the latest version. If we have an old version of the // library, this will return Nil. Function GetRobotMain1(Robot : IRobotMain) : IRobotMain1; Function GetRobotMain2(Robot : IRobotMain) : IRobotMain2; Implementation Uses SysUtils, Windows; Function GetRobotMain(FileName : String) : IRobotMain; Type TInitProc = Function : IRobotMain; StdCall; Var HInstLib: HMODULE; InitProc : TInitProc; Begin HInstLib := 0; Result := Nil; Try HInstLib := LoadLibrary(PChar(FileName)); If HInstLib <> 0 Then Begin InitProc := GetProcAddress(hInstLib, 'GetIRobotMain'); If Assigned(InitProc) Then Result := InitProc End Except Result := Nil; End; If (HInstLib <> 0) And Not Assigned(Result) Then FreeLibrary(HInstLib) End; Function GetRobotMain1(Robot : IRobotMain) : IRobotMain1; Begin If Supports(Robot, IRobotMain1) Then Result := Robot As IRobotMain1 Else Result := Nil End; Function GetRobotMain2(Robot : IRobotMain) : IRobotMain2; Begin If Supports(Robot, IRobotMain2) Then Result := Robot As IRobotMain2 Else Result := Nil End; End.