Search the Community
Showing results for tags 'object'.
Found 1 result
-
This might be answered somewhere around here, but I simply cannot find it. The scenario In order to avoid using Application.ProcessMessages when uploading a heap of data to an external device (which takes time), I'm currently learning more about threads. I have done this a little bit before, but never with an object that has events. I am using the CPDrv TCommPortDriver (ComDrv32) component for communicating with a serial port. I have used this a lot, and am quite familiar with it. I just haven't used it in a thread before, When I create the component manually, I don't have the luxury of having the IDE set the event system up for me behind the scenes. This is what I am trying to do now. Before I paint myself into a corner, I would very much appreciate if someone would confirm that I am doing it the right way – or let me know if I am on the wrong track. I have searched through several web sites, picking up bits and pieces here and there, and this is what I have come up with: My code I have defined a type for the "on receive data" event procedure (TCommPortReceiveData). In the definition of the thread, I use this type when declaring the event procedure (CommPortReceiveData). The lines I find relevant for this question are commented. unit Upload; interface uses System.Classes, System.SysUtils, CPDrv, TeCom, TeComStdRegs; type TCommPortReceiveData = procedure(Sender: TObject; DataPtr: Pointer; DataSize: Cardinal) of object; // Type for receive data event procedure TUploadThread = class(TThread) private CommPortDriver1 : TCommPortDriver; // Declare an identifier for the TCommPortDriver object AbortUpld : Boolean; ProgressVal : Word; FName : string; PortNo : Byte; ModAddress : Byte; ModType : Cardinal; CommPortReceiveData : TCommPortReceiveData; // Declare the receive data event procedure procedure SendTelegram(TxTelegram : tcBuffer; TxTelegramLength : Word); procedure Execute; override; public constructor Create(AOwner : TComponent; FileName : string; PortNumber : Byte; Address : Byte; ModuleType : Cardinal); reintroduce; destructor Destroy; procedure AbortUpload; function Progress : Word; end; In the constructor, I create the object CommPortDriver1, and link the receive data event to my event procedure: constructor TUploadThread.Create(AOwner: TComponent; FileName: string; PortNumber : Byte; Address : Byte; ModuleType : Cardinal); begin inherited Create(false); AbortUpld := false; FName := FileName; PortNo := PortNumber; ModAddress := Address; ModType := ModuleType; CommPortDriver1 := TCommPortDriver.Create(AOwner); // Create COM port driver object CommPortDriver1.OnReceiveData := CommPortReceiveData; // Link event to procedure end; Now, in the code example above, I would have expected to type CommPortDriver1.OnReceiveData := @CommPortReceiveData; , to set the address of the procedure in CommPortDriver1.OnReceiveData. But then I get the error "Incompatible types: 'TReceiveDataEvent' and 'Pointer'" Finally, I write the event procedure itself, using the same parameters as the object's definition of the event: procedure CommPortReceiveData(Sender: TObject; DataPtr: Pointer; DataSize: Cardinal); // Event handler for received data var i : Word; RxBuffer : tcBuffer; begin if (DataSize > 0) then begin Move(PByteArray(DataPtr)[0], RxBuffer[0], DataSize); ... It compiles, and I may make it work. By I'm toggling between "That wasn't so bad" and "This can't really be it, can it?" One thing I find odd is I can't declare the event procedure as procedure TUploadThread.CommPortReceiveData(Sender: TObject; DataPtr: Pointer; DataSize: Cardinal); // Event handler for received data var i : Word; RxBuffer : tcBuffer; ... When I do that, I get the error "Declaration of 'CommPortReceiveData' differs from previous declaration". I guess that this has something to do with the way the procedure has been declared in the TUploadThread type. A quick sanity check would be greatly appreciated. When I get this working properly, I intend post something for others to use as an example.