Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Cursor / Fokus / Marierung fuer Memo sperren


mick - Mo 24.01.05 01:39
Titel: Cursor / Fokus / Marierung fuer Memo sperren
hi.

lese im forum dazu verschiedene dinge, vielleicht kann mal jmd. hier tacheles schreiben ;-) :

habe ein memo, moechte aber nicht, dass man da reinklicken kann mit der maus und dann dort der cursor erscheint. ueberhaupt soll da der cursor nicht zu sehen sein.

readonly ist aktiviert (hat mit obigem auch nix zu tun) und enabled soll das teil auch bleiben.
panel darunter soll nur die notloesung sein. wie funzt das mit setfocus? hatte da etwas gelesen, aber braeuchte code, da es bei mir nicht klappt.


danke + ciao,
mijozi.

Moderiert von user profile iconAXMD: Titel geändert.


patrick - Mo 24.01.05 10:40

wenn du keinen cursor haben willst, kannst du auch direkt in ein panel schreiben.
da kann der user von haus aus keinen cursor setzen :wink:


mick - Mo 24.01.05 11:24

hi.

danke, aber ich befuerchte, ich muss auf den "komfort" eines memo zurueckgreifen...

ciao,
mijozi.


patrick - Mo 24.01.05 13:39

ok die idee mit dem panel ist folgende.
du setzt irgendwo ein panel auf dein form und setzt die eigenschaften
BevelInner und BevelOuter auf bvNone
dann löscht du noch die caption des panels.
damit sollte dein panel unsichtbar sein.
jetzt fügst du am memo diesen code ein:

Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.Memo1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Panel1.SetFocus;
end;

damit wird das panel, sobald die maustaste gedrückt wurde.

das panel einfach mit der eigenschaft visible:=false zu versehen, fällt übrigends flach, weil man keine "unsichtbaren" panels fokusieren kann.


mick - Mo 24.01.05 15:20

hallo patrick,

der trick ist gut! aber:
leider funktioniert noch die rechte maustaste auf dem memo. und wenn ich zuvor mit links gedrueckt einen text markiere (zuerst sehe ich da nicht) und dann die rechter maustaste druecke (und das auswahlmenue erscheint), dann sehe ich auch den zuvor unsichtbar markierten text...

ciao,
mijozi.


Karlson - Mo 24.01.05 18:46

Ein Panel nehmen, bis borderstyle := bsnone "unsichtbar" machen, auf dieses Panel dein Memo setzen, und dann das Panel auf enabled := false stellen.


mick - Mo 24.01.05 22:40

auch keine schlechte idee. aber jetzt funzt die scrollbar nicht mehr!
gibt es eine alternative zum memo mit all o.g. funktionen und praemissen?

ciao,
mijozi.


patrick - Di 25.01.05 10:29

welche scrollbar, von welcher komponente, bei welcher aktion? :?


mick - Di 25.01.05 10:46

die scrollbar des memo. diese kann ich bei verwirklichung des vorschlags von karlson nicht mehr verwenden.
vielleicht sollte man tatsaechlich auf ein richedit ausweichen (ohne panel darunter). bei mousedown und focusumsetzung kann ich dann naemlich - wenn ich das richtig sehe - auch die rechte maustaste nicht mehr verwenden (aber leider immer noch den cursor reinsetzen - naja).

ciao,
mijozi.


Gausi - Di 25.01.05 11:01

Ist vielleicht auch keine besonders elegante Lösung, aber es müsste gehen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
// globale Variable
var oldControl:tWinControl;

//[...]
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
    oldControl:=Form1.ActiveControl;
end;

procedure TForm1.Memo1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    Form1.ActiveControl:=oldControl;
end;


mick - Di 25.01.05 11:29

hm, versteh ich nicht. bin aber auch kein "profi"...

ciao,
mijozi.


Lossy eX - Di 25.01.05 11:33

Wie wäre es, wenn du das TMemo ableitest. Also in Delphi auf "Neu...". Dann auf "Komponente" (Das gelbe Zahlrad). In dem volgenden Dialog kannst du den Klassennamen und den Vorfahren eintragen. Wenn du dann das Grundgerüst von deiner Klasse hast könntest du diese erweitern.

Ich würde vorschlagen, dass du die Message WM_SETFOCUS überschreibst. In dieser Message kannst du dann recht einfach das wechseln des Focuses verhindern.

Das würde dann so aussehen.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
unit Blah;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
  // Keine Ahnung welche Units überflüssig sind. Musst selber mal schauen.

type
  TMyMemo = class(TMemo)
  protected
    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  end;

implementation

procedure TMyMemo.WMSetFocus(var Message: TWMSetFocus);
begin
  Windows.SetFocus (Message.FocusedWnd);
  Message.Result := 0;
end;



Diese Unit müsstest du dann nur noch in ein Package installieren und dann kannst du es als Komponente benutzen. Installieren kannst du das über "Komponente" -> "Komponente installieren..."

Das wäre jedenfalls die beste Möglichkeit, da man das Problem direkt beim Schopfe packt.

PS: Wenn du das als Komponente machst würde es sich evtl. auch anbieten, diese Focusunterdrückerei an eine Booleanproperty zu hängen und es an und ausschaltbar zu gestalten. Aber das nur mal so am Rande.


mick - Di 25.01.05 11:48

das schaut sehr professionell aus. ist es das auch? oder koennen damit probleme auftreten? muss das mal versuchen.

ciao,
mijozi.


Gausi - Di 25.01.05 11:51

Erklärung zu meiner Idee:

Wenn man auf dem Memo die Maus drückt, wird ja das Ereignis OnMouseDown der Memo ausgelöst. In diesem setze ich die "ActiveControl" auf ein anderes. Dann kann das Memo nicht aktiviert werden, weil ich - sobald der User es aktivieren möchte - direkt ein anderes aktiviere. Also z.B. ein EditFeld, oder ein Button oder sonstwas.

Ist nur noch das Problem, welche Kontrolle ich aktiviere. Am besten wäre es ja, wenn ich die letzte aktive nehme. Und die merke ich mir in OldControl und setze die immer dann, wenn sich über der Form die Maus bewegt, also in Form1.OnMouseMove.


Lossy eX - Di 25.01.05 12:02

Ich denke mal schon, dass das Profesionell ist. ;-) Ich habe mich lediglich vor die Bearbeitung durch die VCL gesetzt. Der VCL sage ich "Keine Sorge ich mach dat schon" (Message.Result := 0) und Windows sage ich, dass ich den Focus gerne auf etwas anderes gesetzt hätte.

Speziell wenn man ganz eigene Komponenten entwickelt wird man früher oder Später über direkte Messageabarbeitung nicht herum kommen. Das macht aber auch nichts. Dafür sind sie ja schließlich da. Die VCL macht intern auch nichts anderes. Und so hat es noch den Vorteil, dass es direkt an der Quelle sitzt. Da alle Komponentenauswahlmethoden (Mit Tastatur, Maus, etc.) auf SetFocus basieren wird davon keine mehr auf diese Komponente anwendbar sein.


mick - Di 25.01.05 12:14

Gausi hat folgendes geschrieben:
Erklärung zu meiner Idee:

Wenn man auf dem Memo die Maus drückt, wird ja das Ereignis OnMouseDown der Memo ausgelöst. In diesem setze ich die "ActiveControl" auf ein anderes. Dann kann das Memo nicht aktiviert werden, weil ich - sobald der User es aktivieren möchte - direkt ein anderes aktiviere. Also z.B. ein EditFeld, oder ein Button oder sonstwas.

Ist nur noch das Problem, welche Kontrolle ich aktiviere. Am besten wäre es ja, wenn ich die letzte aktive nehme. Und die merke ich mir in OldControl und setze die immer dann, wenn sich über der Form die Maus bewegt, also in Form1.OnMouseMove.



ich muss bloed nachfragen:
mein memo liegt natuerlich auf der hauptform (form1). wenn ich die maus dann ueber das memo bewege, wird dann nicht auch TForm1.FormMouseMove ausgeloest? oder leost das nur aus, wenn ich direkt ueber den hintergrund der form fahre und nicht ueber eine ihrer komponenten (hier: z.b. memo)? dann koennte deine idee naemlich funktionieren.

ciao,
mijozi.


patrick - Di 25.01.05 13:41

die lösung von Lossy eX ist wohl die eleganteste.
ich hätte aber auch noch was zu der anderen idee und dem rechtsklick-problem:
man kann ja einfach dem memo ein leeres popupmenü zuweisen. damit würde man auch kein popupmenü mehr sehen.
aber die lösungen werden immer "dreckiger"
ich würde auf jeden fall die Lossy eX nehmen. ist das sauberste


Lossy eX - Di 25.01.05 14:29

@Patrick: "ich würde auf jeden fall die Lossy eX nehmen." Hey. Mich gibts nur einmal und ich bin bereits vergeben. ;-)

Spaß bei Seite. Das PopupMenu würde bei mir natürlich auch angezeigt werden. Und viel Schlimmer es würde sogar funktionieren. Aber auch das kann man unterdrücken. Einfach die Methode zu der Klasse hinzufügen.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
protected
  procedure WMContextMenu(var Message: TWMContextMenu); message WM_CONTEXTMENU;
...
implementation

procedure TMyMemo.WMContextMenu(var Message: TWMContextMenu);
begin
end;

Dadurch würde die Message nicht mehr an die VCL gesendet und somit würde kein Popup erstellt werden.


mick - Di 25.01.05 16:04

fein, fein. das aehnelt immer mehr kunst anstelle informatik... ;-)
(oje, welche pseudo-pathetischer quatsch von mir!)

ciao,
mijozi.


patrick - Mi 26.01.05 00:13

mick hat folgendes geschrieben:
fein, fein. das aehnelt immer mehr kunst anstelle informatik... ;-)

bei mir gab es da noch nie einen unterschied. :angel: :mrgreen:

Zitat:
Hey. Mich gibts nur einmal und ich bin bereits vergeben.

jetzt bin ich aber eifersüchtig... :nut:


mick - So 27.02.05 22:41

nachtrag: funzt alles wunderbar. danke!

ciao,
mijozi.