Recent

Author Topic: Setting up event handler for manually created component  (Read 5226 times)

PStechPaul

  • Jr. Member
  • **
  • Posts: 76
    • P S Technology, Inc.
Setting up event handler for manually created component
« on: April 29, 2017, 06:00:36 am »
I am attempting to build a test application for the ComDrv32 CPDrv serial port component. I am using code that previously worked using Delphi Pro 4, but it does not seem to work in Lazarus. Here is an article explaining how event handlers can be created and attached to events in various controls:
http://delphi.wikia.com/wiki/Event_Handlers_in_Delphi

My relevant code:
Code: Pascal  [Select][+][-]
  1. type
  2.  
  3.   { TfmSerialTestCPdrv }
  4.  
  5.   TfmSerialTestCPdrv = class(TForm)
  6. ...
  7.     procedure DataReceived(Sender: TObject);
  8.   private
  9.     { private declarations }
  10.   public
  11.     CommSerialPort: TCommPortDriver;
  12.     { public declarations }
  13.   end;  
  14.  
  15. procedure TfmSerialTestCPdrv.FormCreate(Sender: TObject);
  16. begin
  17.   if CommSerialPort = nil then
  18.     CommSerialPort := TCommPortDriver.Create(nil);
  19.   CommSerialPort.OnReceiveData := DataReceived; // ERROR HERE
  20. end;
  21.  
  22. procedure DataReceived(Sender: TObject);
  23.   var       RecvData: byte;
  24.             Str: String;
  25.   begin
  26.     CommSerialPort.ReadByte(RecvData);
  27.     ...
  28.   end;
  29.  

I am getting these error messages:
Code: Pascal  [Select][+][-]
  1. Compile Project, Target: SerialTestCPdrv.exe: Exit code 1, Errors: 3, Hints: 3
  2. serialtestcpdrvmain.pas(124,37) Hint: Local variable "RecvData" does not seem to be initialized
  3. serialtestcpdrvmain.pas(122,13) Note: Local variable "Str" not used
  4. serialtestcpdrvmain.pas(146,35) Error: Wrong number of parameters specified for call to "DataReceived"
  5. serialtestcpdrvmain.pas(40,15) Error: Found declaration: DataReceived(TObject);
  6. serialtestcpdrvmain.pas(147,35) Error: Incompatible type for arg no. 1: Got "Word", expected "TBaudRate"
  7. CPDrv.pas(516,27) Hint: Found declaration: SetBaudRate(TBaudRate);
  8.  
(my code is attached)
You can download ComDrv32 here: http://torry.net/pages.php?s=89

Any ideas? Thanks!
« Last Edit: April 29, 2017, 06:08:27 am by PStechPaul »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Setting up event handler for manually created component
« Reply #1 on: April 29, 2017, 06:26:04 am »
I am not familiar with "ComDrv32 CPDrv serial port component" but look up it's documentation to see what parameters are expected. The compiler states what is wrong, but your pasted code does not match your compilation output (e.g. error lines does not match up).

(so basically you are asking someone else to do the grunt work for you ;-) )

1 You are actually invoking DataReceived routine instead of assigning it to the event property.

to get rid of the first error you need to use:
Quote
CommSerialPort.OnReceiveData := @DataReceived;
.. or compile in mode Delphi

2 The declaration of the eventhandler (parameterlist) does not match as described by the TCommPortDriver class

Code: Pascal  [Select][+][-]
  1. type
  2.   // RX event ( packet mode disabled )
  3.   TReceiveDataEvent = procedure( Sender: TObject; DataPtr: pointer; DataSize: DWORD ) of object;
  4.   // RX event ( packed mode enabled )
  5.   TReceivePacketEvent = procedure( Sender: TObject; Packet: pointer; DataSize: DWORD ) of object;
  6.  

Make sure your implementation matched this as well.

3 Your current event handler implementation is not a procedure of type object as it is not part of an object.

e.g it should read something like:
Code: [Select]
procedure TfmSerialTestCPdrv.DataReceived(....etc

Or make the handler part of any other class/object and assign to that.

4. You are using the wrong assignment (type) for setting the baudrate.

The TBaudrate error is then raised because you do not use one of the predefined TBaudrate declaration which are:
Code: [Select]
  TBaudRate = ( brCustom,
                br110, br300, br600, br1200, br2400, br4800,
                br9600, br14400, br19200, br38400, br56000,
                br57600, br115200, br128000, br256000 );
.. so not just a number, unless you use baudratevalue property which accepts a 'normal' dword.
« Last Edit: April 29, 2017, 07:06:03 am by molly »

PStechPaul

  • Jr. Member
  • **
  • Posts: 76
    • P S Technology, Inc.
Re: Setting up event handler for manually created component
« Reply #2 on: April 29, 2017, 07:58:11 am »
Yes, I finally figured it out. Actually, I was able to install the serial port component as an object to be placed on the form from the components. But then I tried to run it but the main form did not show. I found that a line was missing in the project:
Code: Pascal  [Select][+][-]
  1.   Application.CreateForm(TfmSerialTestCPdrv, fmSerialTestCPdrv);
  2.  

So now it throws a runtime error. It stops on 3668
Code: Pascal  [Select][+][-]
  1. procedure TControl.ReadState(Reader: TReader);
  2. begin
  3.   Include(FControlFlags, cfLoading);
  4.   DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TControl.ReadState'){$ENDIF};
  5.   try
  6.     Include(FControlState, csReadingState);
  7.     inherited ReadState(Reader); // Line 3668 - stops here
  8.   finally
  9.     Exclude(FControlState, csReadingState);
  10.     EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TControl.ReadState'){$ENDIF};
  11.   end;
  12. end;    

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Setting up event handler for manually created component
« Reply #3 on: April 29, 2017, 08:09:54 am »
I found that a line was missing in the project:
Code: Pascal  [Select][+][-]
  1.   Application.CreateForm(TfmSerialTestCPdrv, fmSerialTestCPdrv);
  2.  
You should not have to do that manually. Forms are automatically created when you add them to your project, unless you specifically told otherwise.

Nevertheless, and in case new to lazarus, use the project options form settings. there you can visually add or remove forms in your project to autocreate (or not) by moving them from left to right (or vise verse).

If i would have to guess by your trace you inserted the call to createform at the wrong location (= show dpr/lpr file content) or something else is wrong with streaming as your trace seems to go deep into lcl.

btw: Runtime error 217 means unhandled exception. Don't you have sysutils included (which installs a default handler).

PS: with regards to your first code.

If you do something (manually) like this:
Code: [Select]
CommSerialPort := TCommPortDriver.Create(nil);
then that should be followed by something like this:
Code: [Select]
CommSerialPort.Free;Somewhere in your code where the application gets closed (usually at destroy event of your form) in order to free up the allocated resources used by CommSerialPort.
« Last Edit: April 29, 2017, 08:30:45 am by molly »

PStechPaul

  • Jr. Member
  • **
  • Posts: 76
    • P S Technology, Inc.
Re: Setting up event handler for manually created component
« Reply #4 on: April 29, 2017, 10:26:23 am »
I think there is something wrong with the component. If I just put the component on a form it throws the error when I try to run. It does the same if I create the component manually. But I have used it successfully in Delphi 4.

 

TinyPortal © 2005-2018