Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Formularübergreifend schreiben


mcbain - Mo 09.05.11 14:00
Titel: Formularübergreifend schreiben
Hallo,
ich nutze die D2010 Touch - Keyboard Kommponente für eine Anwendung, die später auf einem Touch-Screen Monitor laufen muss.
Da der User nicht immer Eingaben machen muss, sondern erst ein Menü durcharbeiten muss, ist das Formular mit dem Keyboard darauf erstmal ausgeblendet.
Erst, wenn der User einen bestimmten Button drückt, erscheint das Keyboard und der User kann seine Daten darüber eingeben. Leider funktioniert das so nicht, da der Focus auf dem Formular mit dem Keyboard liegt und die Edit-Komponente, in der der Text geschrieben werden soll auf einem anderen Formular liegt. Somit schreibt die Tastatur natürlich ins Leere.
Hatte mir bisher überlegt über ein unsichtbares Edit auf dem gleichen Formular zu arbeiten, über onchange, aber das funktioniert natürlich nicht, wenn visible = false ist...eine andere Möglichkeit wäre über Systemweite Hotkeys zu arbeiten, aber ich denke es müsste dafür doch evtl. ne schönere Lösung geben oder?

Wäre nett, wenn mir jemand kurz helfen könnte...


Moderiert von user profile iconGausi: Topic aus Sonstiges (Delphi) verschoben am Mo 09.05.2011 um 14:06


Gausi - Mo 09.05.11 14:06

Das sollte so gehen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
// Unit mit dem Keyboard drauf
// ...
implementation

uses MainUnit;

//...

procedure KeyboardOnClick // OnChange // egal, halt das Event, was aufgerufen wird, wenn der User rumtippt ;-)
begin
  MainForm.MeinEdit.Text := // ...
end;


mcbain - Mo 09.05.11 16:02

Vielen Dank für den Hinweis.

ich habe es nun so gemacht:
auf meiner Form3, auf dem das Keyboard liegt, wird folgendes implementiert:

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm3.FormKeyPress(Sender: TObject; var Key: Char);
begin
   mainform.edit.Text := mainform.edit.Text + Key;
end;


Das funktioniert auch, aber wie realisiere ich das, wenn der Benutzer Tabulator, Delete oder Backspace drückt?
Für Backspace habe ich mir gedacht, müsste folgendes gehen:

Delphi-Quelltext
1:
  mainform.edit.Text := AnsiLeftStr( mainform.edit.Text,Length( mainform.edit.Text)-1);                    


Aber das Problem ist, dass der Tastatur-Cursor ja nicht zwansläufig an der letzten Stelle im mainform.edit.Text steht. Wenn der User den Cursor in die Mitte der Editbox platziert hat, dann muss ja nicht das letzte Zeichen, sondern das direkt nachfolgende Zeichen gelöscht werden. Das gleiche Problem tritt natürlich auf, wenn auf Delete geklickt wird.


jaenicke - Di 10.05.11 09:56

Mit WS_EX_NOACTIVATE als erweitertem Fensterstil sollte es doch auch möglich sein, dass das Fenster mit dem Keyboard nie den Fokus bekommt.


mcbain - Di 10.05.11 13:59

Vielen Dank, ich habe es jetzt so gelöst:

Hier der Code für die Tastatur:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Keyboard;

type
  TForm2 = class(TForm)
    tchkybrd1: TTouchKeyboard;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  protected
    procedure CreateParams(var Params: TCreateParams); override;

  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.CreateParams(var Params: TCreateParams);       //Kein Focus für die Tastatur-Form
//const
//  WS_EX_NOACTIVATE = $8000000;
begin
  inherited;
  Params.ExStyle := Params.ExStyle + WS_EX_NOACTIVATE;
end;

procedure TForm2.FormCreate(Sender: TObject);                     //Keine Titelleiste für die Tastatur-form
begin
  SetWindowLong(Handle, GWL_STYLE, (GetWindowLong(Handle, GWL_STYLE) and not WS_Caption));
  ClientHeight := Height; 
  Refresh;

end;

end.



Die Tastatur.exe wird anschließend in meinem anderen Programm folgendermaßen benutzt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
unit aufruf;

interface

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

type
  TForm2 = class(TForm)
    e1: TEdit;
    e2: TEdit;
    btn1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btn1Click(Sender: TObject);
  private
          { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}



procedure ShowKeyBoard;
Var lngHwnd:THandle;
begin
  lngHwnd := FindWindow(nil'Tastatur');
  If lngHwnd>0 Then
     //PostMessage(lngHwnd, WM_SYSCOMMAND,SC_MINIMIZE,0)
     PostMessage(lngHwnd, WM_CLOSE ,0,0)
  else
     ShellExecute(Form2.Handle, nil, PChar('C:\Data\Tastatur.exe'), '''', SW_NORMAL);
end;

procedure TForm2.btn1Click(Sender: TObject);
begin
   e1.SetFocus;
   ShowKeyboard();
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
   ShowKeyboard();
end;

end.


Diese Unit ruft mir die Tastatur auf, falls die Exe noch nicht läuft, ansonsten beendet das Programm die Tastatur.exe.

Und durch den Tip von jaenicke mit


Delphi-Quelltext
1:
Params.ExStyle := Params.ExStyle + WS_EX_NOACTIVATE;                    


bekommt die Tastatur.exe nie den Focus und man kann sie wie die physische Tastatur verwenden.
Vielen Dank an alle.