Recent

Author Topic: onkeydown event question  (Read 30811 times)

wpflum

  • Sr. Member
  • ****
  • Posts: 287
onkeydown event question
« on: September 02, 2010, 09:39:00 pm »
I tried this a year ago and never got through it so I'll ask again to see if anyone can point me in the right direction.

I'm using a keydown event for a form that I want to send to a general routine in an included program.  I'm trying to keep all of my functions in a file called, surprisingly, Functions.pas  so all I have to do is add 'Functions' to the uses clause and I have the commands I need.

I can use the following on the main form program to figure out what control just had focus

if form1.activecontrol = form1.ControlByName('Controlname') then .....

This works as expected so that if I trap the tab key I can then direct the code to do something based on which tedit it's in.

While looking stepping through the code I can see that the 'Sender' in the FormKeyDown appears to be the form itself so I tried to send that to the function and then use it as the basis for the same if statement but just trying

Checkfield(Sender); in the main program and then

Function Checksender(Sender:Tobject);
Begin
if Sender.activecontrol = Sender.ControlByName('Controlname') then .....

Gets me an error saying something to the effect of there isn't an property or function like that in Sender.

If I try tform(Sender).activecontrol .......

I don't get the error but I also don't seem to get the active control so the if statement fails.

What am I doing wrong????? 

Am I using the Sender object incorrectly??

I just had a thought which I'll try out while waiting to see if someone can answer, I'm going to try to get the active control and send it with the tobject and see if I can work with that, not as neat but maybe it will work.

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: onkeydown event question
« Reply #1 on: September 02, 2010, 10:16:20 pm »
 %) %) %) %) %) %) %) %) %)

Now I'm really confused.

I was playing around and decided to try to copy the TObject into a form variable so I made a form variable and the used

form1 := tform(Sender);

in the function program.

Worked great, then just to be thorough I wrote the same statement using tform(sender). and that worked this time  :o

I'm sure I did something wrong but I really hate it when I don't know WHAT  :(

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: onkeydown event question
« Reply #2 on: September 02, 2010, 11:33:42 pm »
Maybe you should do a safer cast. Something like:

Code: [Select]
if Sender is TForm then begin
   with Sender as TForm do begin
      activecontrol .......
   end;
   end
else
if Sender is TEdit then begin
   with Sender as TEdit do begin
       .......
   end;
end;

if you put a code example of your code it would be easyer to undertand whats wrong in the code...

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: onkeydown event question
« Reply #3 on: September 03, 2010, 04:19:23 pm »
Right now there is no code, I keep changing it, and now I'm back to the Tobhect not working. 

If the sender tobject is a form and you send that as a tobject to another furnction and then use tform(tobject) to force it into a tform object will you have access to the names of the controls on the form directly or will you have to access them indirectly??  What I mean is if I have a form that the key down event is triggered and I send the tobject/tform to a function can I just use the format tform(tobject).controlname where controlname is the name of the control on the form or will I have to do something else.  I think I'm doing something wrong in how I'm trying to access the tobject and thats why it seems to work sometimes then stops. 

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: onkeydown event question
« Reply #4 on: September 03, 2010, 04:36:22 pm »
Maybe this will be a bit clearer on what I'm stuck on.  If I have Form1 with PageControl1, Tabsheet1 with one TEdit1 on it I can access the Tedit1 on the Form1 code page using Form1.Tedit1.   If I send Form1 from the Form1 code page to a function on another code page as Sender:Tobject I can access the Form1 by using tform(Sender).   but I do not see the controls like I do after I add the dot like I do on the Form1 Page.  Are these available and I have to access them some other way or can't I get to them at all???

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: onkeydown event question
« Reply #5 on: September 03, 2010, 05:24:29 pm »
Ok, here is a test program where I'm just trying to access the Tedit field on the form from the keydown event.

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  ComCtrls, StdCtrls,Functions;

type

  { TForm1 }

  TForm1 = class(TForm)
    Edit1: TEdit;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);

  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{ TForm1 }



procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
  );
begin

Form1.Edit1.Caption := 'HI';
MyKeyPress(Sender,Key,Shift);
end;

initialization
  {$I unit1.lrs}

end.
------------------------------------------------------------------------------------------

unit Functions;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils,Dialogs,Forms;
Function MyKeyPress(Sender: TObject; var Key: Word; Shift: TShiftState):Boolean;

implementation
Function MyKeyPress(Sender: TObject; var Key: Word; Shift: TShiftState):Boolean;
begin
if Sender is TForm then
   begin
   tform(Sender).Edit1.Caption := 'BYE';
   end;
end;

end. 

-----------------------------------------------------------------------------------------------

This doesn't work because I get the error:

functions.pas(16,18) Error: identifier idents no member "Edit1"

So how do I correctly access the field in this instance??

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1932
Re: onkeydown event question
« Reply #6 on: September 03, 2010, 05:43:13 pm »
How should unit "Functions" know that Form1 has an Edit1?

Place a
uses Unit1;
below the implementation keyword of unit "Functions".

Then you can access Form1 directly. You don't need the "Sender" parameter then.

Not sure if it is a good idea to place this code in "Functions" though.

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: onkeydown event question
« Reply #7 on: September 03, 2010, 05:55:06 pm »
Since I'm sending the Tform object isn't that info in it someplace?? I don't like the idea of circular references even if it is local.  I tried it and it works but I'd rather keep everything the function needs right in the sent info just to keep it neat.

Where would you put something like this??  It doesn't have to be a 'Functions' include I could put the entire thing in its own separate file and call it KeyHandeling but I think I'd still have the problems. 

The way I like to code is keep as much out of the main program as possible so it's easier to follow the grand scheme of things and then jump to the littler bits to see details.  I just think it's easier like that, but that's just me  ;)

Bill


theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1932
Re: onkeydown event question
« Reply #8 on: September 03, 2010, 06:10:56 pm »
I wouldn't do it like this. I'd separate the Form1 GUI Elements from the worker code in "Functions".
I would not refer to Form1.Edit1 in unit "Functions".

Something like this:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  2. begin
  3. Form1.Edit1.Caption:=HandleKeyPress(Key,Shift);
  4. end;
  5.  
Where HandleKeyPress in unit Functions returns a String in your example.
« Last Edit: September 03, 2010, 06:12:30 pm by theo »

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: onkeydown event question
« Reply #9 on: September 03, 2010, 06:25:16 pm »
I may have to go with something like that but the problem is that I'm dealing with forms that might have 20 or 30 tedit controls so I'd have to have a lot of code on the form page to handle it,  I'm trying to avoid that if at all possible. 

What exactly does a tForm object contain??  Is there anyway I can enumerate the controls from the object itself to give me control??

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1932
Re: onkeydown event question
« Reply #10 on: September 03, 2010, 06:37:21 pm »
Why do you say:
"I don't like the idea of circular references even if it is local."

Your code in "Functions" the way you do it will only work together with your Form1/Unit1 so why not
"uses Unit1"?

Please explain.

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: onkeydown event question
« Reply #11 on: September 03, 2010, 06:47:53 pm »
I'm referencing Functions in Unit1 and Unit1 in Functions so I'd say that is a circular reference.  To me that is sloppy coding.   


What I need is a way to access the TForm/TObject being sent to Functions in a way that I can enumerate the controls and access them from the TForm/TObject itself and not have to have an external reference in Functions to get me there.


theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1932
Re: onkeydown event question
« Reply #12 on: September 03, 2010, 07:04:53 pm »
I'm referencing Functions in Unit1 and Unit1 in Functions so I'd say that is a circular reference.  To me that is sloppy coding.  

Maybe, but in this case, the "sloppy coding" is not the "uses Unit1" but the fact that you reference "Form1"-Components from unit "Functions".
What you intend to do (enumerate components) makes it only more complicated, not better.

As I said above, the clean way is to write functions in unit "Functions" which do not need to know about Form1.
« Last Edit: September 03, 2010, 07:12:56 pm by theo »

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: onkeydown event question
« Reply #13 on: September 03, 2010, 07:20:24 pm »
I'll ask again, what is in a TObject???  If I'm sending the Form as a complete entity to the function then the function isn't referencing unit1 it is referencing the TObject sent to it.  I see that in no way as 'sloppy'.  If you think that is sloppy then that is your opinion and you're welcome to it  ;D and you might be right in the long run but I still prefer to keep my code in units and not on the main form if at all possible.

What I like to see when I look at code is a main program that calls different procedures and functions but has minimum actual logic or coding on it so when I walk through the program I can see that the first thing it does when run is initialize something, display something and then exit. If I have a lot of code in the main program I have to worry about things failing or running incorrectly as a whole and not as a small part.  Again just my preferences.  :)

mas steindorff

  • Hero Member
  • *****
  • Posts: 555
Re: onkeydown event question
« Reply #14 on: September 03, 2010, 07:49:17 pm »
sender is a tobject.  tobject is a common base class that mostly all of the controls are derived from.  It only has basic properties as compared to the controls you use on the form like a tedit.  You can access the "advanced" eleaments of the control by casting (upgrading) the sender to the control with the "as" command.

... but the problem is that I'm dealing with forms that might have 20 or 30 tedit controls so I'd have to have a lot of code on the form page to handle it.

you can assign all of the tedit key down events to the same function.  then all you need is one function.  you can sort out which one is the active one by (simple) looking at the sender's tag or you can dig into the sender's as tedit. properties like top,left or parent to make your selection.

windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

 

TinyPortal © 2005-2018