Solved

Embedded Frames do not receive Shortcut key input

Posted on 2006-07-17
19
1,021 Views
Last Modified: 2010-04-05
Dear Experts,

I am using TFrames in Delphi 7.

At application's main form create I create my Frames all descent from TBaseFrame.
These frames then get's showed and hide on the appropriate button's onclick() events.

The problem I have here is there are 2 frames which have a TListView component on it.
I have created an action to select / deselect all items in the TListView components.
The shortcut key for these actions are CTRL+A.

Ok, when I show my first Frame the CTRL+A is working but when showing the second and hiding the first the input still goes to the first (hidden) frame.

How can I force the keyboard input to the visible Frame?

Thanks in advance!
0
Comment
Question by:Marius0188
  • 11
  • 4
  • 3
  • +1
19 Comments
 

Author Comment

by:Marius0188
ID: 17126923
I should also mention that I have tried:
SetFocus()
BringToFront()
SentToBack()
and it's not working.
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 17127562
Make KeyPreview = True on your form. This will make sure your form receive the Key pressed before all other controls. The in OnKeyDown, OnKeyUp, OnKeyPress handle the events.
0
 

Author Comment

by:Marius0188
ID: 17130398
Can you maybe please show me the code for OnKeyDown, OnKeyUp and OnKeyPress events to effectively forward all key strokes to a TFrame?

Thanks so far!
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 17131526
Example:

parent form:
------------------------------------------------------
uses Unit2;

procedure TForm1.FormCreate(Sender: TObject);
var
  Frame2 : TFrame2;
begin
  Frame2 := TFrame2.Create(Self);
  Frame2.Parent := Panel1;
  Frame2.Align := alClient;
  Frame2.Show;
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
var
  i : Integer;
begin
  for i := 0 to Self.ComponentCount - 1 do
    begin
      if (Self.Components[i] is TFrame) then
        if ((Self.Components[i] as TFrame).Visible) and ((Self.Components[i] as TFrame).Name = 'Frame2') then
          begin
            // frame is visible
            (Self.Components[i] as TFrame).Perform(WM_KEYDOWN, ord(Key), 0);
          end;
    end;
end;

-------------------------------------------------------------------------------
frame:
-------------------------------------------------------------------------------

type
  TFrame2 = class(TFrame)
  private
    { Private declarations }
    procedure OnKeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN;
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

{ TFrame2 }

procedure TFrame2.OnKeyDown(var Msg: TWMKeyDown);
begin
  ShowMessage(IntToStr(Msg.CharCode));
end;
0
 
LVL 6

Expert Comment

by:House_of_Dexter
ID: 17133604
procedure PassKeyToFrame(aParent: TWinControl; aKey: TWMKey; var aHandled: Boolean );
var
  a_iIndex: integer;
begin
  for a_iIndex := 0 to aParent.ControlCount -1 do
  begin
  {we loop through all the children}
    if aParent.Controls[a_iIndex] is TBaseFrame then
    begin
      aHandled := TBaseFrame(aParent.Controls[a_iIndex]).HandleKey(aKey);
      if aHandled then
        break;
    end;
    if aParent.Controls[a_iIndex] is TWinControl then
{if its a WinControl...meaning it can be a Parent to other controls...we loop
 through them, and so and so on.}
      PassKeyToFrame(TWinControl(aParent.Controls[a_iIndex]), aKey, aHandled);
  end;
end;

procedure TForm1.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  PassKeyToFrame(Form1, Msg, Handled);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Frame1 := TBaseFrame.Create(Self);
  Frame1.Parent := Panel1;
end;


type
  TBaseFrame = class(TFrame)
    Label1: TLabel;
    Button1: TButton;
  private
    { Private declarations }
  public
    { Public declarations }
    function HandleKey(aKey: TWMKey): boolean;
  end;


{ TBaseFrame }

function TBaseFrame.HandleKey(aKey: TWMKey): boolean;
begin
  Result := Visible;
  if Result then
    ShowMessage('rcvd');
end;
0
 

Author Comment

by:Marius0188
ID: 17133759
Thanks all so far.

1. May I ask why does the visible Frame not automatically receive keystrokes?
Why does it feel like I have to hack it (or something like that) in order to work normal?
If one frame is hidden and another frame is visible isn't it logical that the hidden one should not respond to keystrokes
but instead the visible one? Can someone please explain to me why?


2. I have quickly looked over all the comments and it feels to me there should be a simple more elegant way of handling this. Please understand I am not being difficult. :)
a) But can't I just force a Frame to be the ActiveControl of my MainForm?
The comments if not complex at all but like I said. If embedding Frames in a TForm is should behave like any other control? Or not?

0
 
LVL 6

Expert Comment

by:House_of_Dexter
ID: 17134012
procedure EnableFrame(aFrame: TFrame; aEnable: boolean);
begin
  aFrame.Visible := aEnable;
  aFrame.Enabled := aEnable;
  if aFrame.Enabled then
    if aFrame.CanFocus then
      Form1.ActiveControl := aFrame;
end;

when you make the Frame Not Visible...also set it Not Enabled ...that should stop it from getting keyboard input
0
 

Author Comment

by:Marius0188
ID: 17135164
I have tried enabling and disabling the frame according to it's visible state.
Have also set ActiveControl but still it's not working.

0
 

Author Comment

by:Marius0188
ID: 17135177
Maybe I should mention.
On my MainForm I have a TPanel which is Parent control of Frames.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:Marius0188
ID: 17135199
Just for testing purposes I have set
the Frame.Parent := nil when hidden.

Then the Key stokes are working fine but obviously lots of errors.
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 17136391
In my example I used

Form1.KeyPreview := true;
Frame.Parent := Panel1;
0
 
LVL 21

Expert Comment

by:ziolko
ID: 17136652
try this:
PostMessage(valid_handke_here, WM_ACTIVATE, WA_ACTIVE, 0);

ziolko.
0
 

Author Comment

by:Marius0188
ID: 17136737
Hi All,

I have tried everything so far to get the Frame to be the active control.
Nothing is working.
Maybe if I show my code you will understand better.



procedure TfrmMain.SetCurrentFrame(const Value: TBaseFrame);
begin
  If Assigned(CurrentFrame) then
  begin
    If CurrentFrame = Value then Exit;
    CurrentFrame.Enabled := False;
    CurrentFrame.Hide;
  end;

  FCurrentFrame := Value;

  CurrentFrame.Enabled := True;
  CurrentFrame.Parent := panMain;
  CurrentFrame.Align := alClient;
  CurrentFrame.Show;

  CurrentFrame.LoadData;

  frmMain.ActiveControl := CurrentFrame;

//  frmMain.ActiveControl := CurrentFrame;
//    frmMain.FocusControl(CurrentFrame);
//  CurrentFrame.BringToFront;
//  CurrentFrame.SetFocus;
 
end;
0
 
LVL 6

Expert Comment

by:House_of_Dexter
ID: 17139220
Can I see the code that you are executing on Ctrl + A

Are you using an ActionList?
0
 

Author Comment

by:Marius0188
ID: 17174804
Yes I am using a TActionList and assign my shortcuts via actions properties.
0
 

Author Comment

by:Marius0188
ID: 17175289
This is the code executed on the action which have the shortcut: CTRL+A.
-----------------------------------------------------------------------------------------
procedure TAnalyzeFrame.actSelectAllExecute(Sender: TObject);
begin
  inherited;
  Busy := True;
  Try
    Case tbtnSelectAll.Tag of
      0:
        begin
          tbtnSelectAll.Tag := 1;
          lsvDownloads.SelectAll;
        end;
      1:
        begin
          tbtnSelectAll.Tag := 0;
          lsvDownloads.ClearSelection;
        end;
    end;
  Finally
    Busy := False;
  end;
end;
-----------------------------------------------------------------------------

Please note that there are another frame with similar action to select all in it's TListView.
0
 
LVL 6

Accepted Solution

by:
House_of_Dexter earned 125 total points
ID: 17178094
k...do you have an actionlist for each frame?

If so...  ActionList1.State :=  asSuspended for the disabled frame; and   ActionList1.State :=  asNormal for the visible frame;

This will stop the ActionList from grabbing Shortcuts...

0
 

Author Comment

by:Marius0188
ID: 17178179
Yes the 2 Frames giving problems each have their own TActionList.

Ok I will test your example and let you know.

Thanks!
0
 

Author Comment

by:Marius0188
ID: 17178442
OK thanks House of Dexter.

It worked!
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now