?
Solved

Component Writing : TGraphicControl with user (keyboard) input

Posted on 2003-03-04
7
Medium Priority
?
405 Views
Last Modified: 2011-09-20
I am writing a network monitoring screen logging component. Due to the speed of the output, I am using TGraphicControl as the main drawing Canvas in the component, which I've provided Line and Page updates for.

I have used the mouse button up msg to detect when and where the user has clicked on the screen. However, to provide a more professional finish, I really need to let the user navigate the captured data with the arrow keys.

I'm aware of the procedure necessary to grab the arrow keys :
PROCEDURE WMGetDlgCode (VAR MESSAGE : TWMGetDlgCode); MESSAGE WM_GetDlgCode;

But I think I need a method of adding/simulating key down events on this (or a sub/child) control, as TGraphicControl doesn't naturally own a window's handle from which to receive WM_KEYDOWN ?!?

Any ideas would be much appreciated.
Many thanks.
Steve
0
Comment
Question by:steve_hsk
  • 4
  • 3
7 Comments
 
LVL 21

Expert Comment

by:ziolko
ID: 8063330
Write WndProc and use AllocateHwnd from Forms unit to get Handle.
ziolko.
0
 
LVL 2

Author Comment

by:steve_hsk
ID: 8064392
Hi ziolko ...

This method appears to work :-)

Have used it before to grab the Window's Caption Control, but for some reason it didn't occur to me here. Needed more coffee ;-)

The points are yours. As a last query, did you have a better way of implementation than below ? (may as well try and make ya work for it :-) ) ...

NOTE : Here for others reference also ...

TYPE TWindowClass = CLASS (TComponent)
PUBLIC
    // Declare Class Control Functions
    CONSTRUCTOR Create(AOwner: TComponent); OVERRIDE;
    DESTRUCTOR  Destroy; OVERRIDE;
PRIVATE
    // Declare Internal Variables
    FForm       : TWinControl;
    FNewProc    : Pointer;
    FOldProc    : Pointer;
    FWinControl : TWinControl;

    // Declare Internal Methods
    PROCEDURE HookedMsgProc (VAR Msg: TMessage);
    PROCEDURE Loaded; OVERRIDE;
    PROCEDURE HookWindow;
    PROCEDURE UnhookWindow;
END;

CONSTRUCTOR TWindowClass.Create(AOwner: TComponent);
VAR tFormParent : TWinControl;
BEGIN
  INHERITED Create(AOwner);
  tFormParent := TWinControl(AOwner);

  WHILE (tFormParent <> NIL) AND (NOT (tFormParent IS TForm)) DO
  BEGIN
        tFormParent := tFormParent.Parent;
  END;

  FForm := tFormParent;

  FNewProc := MakeObjectInstance(HookedMsgProc);
END;

DESTRUCTOR  TWindowClass.Destroy;
BEGIN
    FreeObjectInstance(FNewProc);
    UnhookWindow;
    inherited Destroy;
END;

PROCEDURE TWindowClass.Loaded;
BEGIN
    FWinControl := FForm;
    HookWindow;
    inherited Loaded;
END;

PROCEDURE TWindowClass.HookedMsgProc (VAR Msg: TMessage);
BEGIN
    if (Msg.WParam = VK_UP) or (Msg.WParam = VK_DOWN)then
    BEGIN
        g_tparent.m_FtDataSelection.DrawSelection(Msg.LParam);
    END
    ELSE
    BEGIN
        Msg.Result := CallWindowProc(FOldProc, FWinControl.Handle, Msg.Msg, Msg.WParam, Msg.LParam);
    END;

    INHERITED;
END;

PROCEDURE TWindowClass.HookWindow;
BEGIN
    FOldProc := Pointer(GetWindowLong(FWinControl.Handle, GWL_WNDPROC));
    SetWindowLong(FWinControl.Handle, GWL_WNDPROC, Integer(FNewProc));
END;

PROCEDURE TWindowClass.UnhookWindow;
BEGIN
    IF FOldProc <> NIL THEN
    BEGIN
        SetWindowLong(FWinControl.Handle, GWL_WNDPROC, Integer(FOldProc));
        FOldProc := nil;
    END;
END;
0
 
LVL 21

Expert Comment

by:ziolko
ID: 8065264
Hi steve if You dont mind I'll take a look at it tomorrow morning. I'll rather go to sleep then drink more coffe :-)))
ziolko.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 21

Accepted Solution

by:
ziolko earned 300 total points
ID: 8067967
hmm look ok but persnoally I dont like subcalssing so I would do it that way:
this unit defines TWindowClass

unit Unit2;

interface

uses  Classes, Controls, Messages, Windows;

type TWindowClass = class(TComponent)
private
   // Declare Internal Variables
   FHandle: THandle;
protected
   // Declare Internal Methods
   procedure WndProc(var Message: TMessage);virtual;
   procedure Loaded; override;
public
   // Declare Class Control Functions
   constructor Create(AOwner: TComponent); override;
   destructor  Destroy; override;
   procedure Perform(var Message: TMessage);
end;

implementation

uses Forms;

constructor TWindowClass.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 FHandle:=AllocateHWnd(WndProc);
END;

destructor  TWindowClass.Destroy;
begin
   DeallocateHWnd(FHandle);
   inherited Destroy;
end;

procedure TWindowClass.Perform(var Message: TMessage);
begin
  if FHandle <> 0 then
    WndProc(Message);
end;

procedure TWindowClass.Loaded;
begin
   inherited Loaded;
end;

procedure TWindowClass.WndProc(var Message: TMessage);
begin
  if (Message.WParam = VK_UP) or (Message.WParam = VK_DOWN) then
//    g_tparent.m_FtDataSelection.DrawSelection(Message.LParam);
   Beep(100,40)
end;

end.


this is unit with form definition (single button is on form):
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Unit2;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    dumm: TWindowClass;
  protected
    procedure WndProc(var Message: TMessage);override;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}


procedure TForm1.WndProc(var Message: TMessage);
begin
  if dumm <> nil then
    dumm.Perform(Message);
  inherited WndProc(Message);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  dumm:=TWindowClass.Create(Self);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  dumm.Free;
end;

end.


ziolko.
0
 
LVL 2

Author Comment

by:steve_hsk
ID: 8070315
Job well done ... !

Two different implementations, both which work nicely !

Many thanks Ziolko !

:-)
0
 
LVL 2

Author Comment

by:steve_hsk
ID: 8070327
Nice suggestion, followed by a nice example !

Job well done !

<< have increased my morning coffee intake two-fold ;-)

Many thanks,
Steve
0
 
LVL 21

Expert Comment

by:ziolko
ID: 8070622
glad to be helpfull :-)
ziolko.
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
How to fix display issue, screen flickering issue when I plug in power cord to the machine. Before I start explaining the solution lets check out once the issue how it looks like after I connect the power cord. most of you also have faced this…
SQL Database Recovery Software repairs the MDF & NDF Files, corrupted due to hardware related issues or software related errors. Provides preview of recovered database objects and allows saving in either MSSQL, CSV, HTML or XLS format. Ensures recov…
Suggested Courses
Course of the Month8 days, 7 hours left to enroll

621 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