Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Rechtsklick abschießen (https://www.delphipraxis.net/45588-rechtsklick-abschiessen.html)

DGL-luke 8. Mai 2005 21:08


Rechtsklick abschießen
 
Ich habe in meiner anwendung eine listview mit multiselect und einem poupmenü.

wenn ich jetzt rechts klicke, wird die aktuelle auswahl aufgehoben und das wo ich klicke markiert. das will cih aber nicht. meine aktuelle lösung: ich speichere im onmousemove die selection in einem array of bool. beim onpopup wird das array zurück in die listview geschrieben.
da das aber 1. suboptimal und 2. nicht oop ist, habe ich mir überlegt, dass ich einfach den rechtsklick ausschalte.

das habe ich bis jetzt zustande gebracht(LV ist die listview):

Delphi-Quellcode:
procedure WndProc(Msg:TMessage);
var p:TPoint;
    inLV:boolean;
begin
inherited;
p:=screentoclient(mouse.cursorpos);
inLV:= ( (p.X >= LV.left) and (p.X <= LV.left+LV.width) and (p.Y >= LV.top) and (p.Y <= LV.top + LV.Height) );

if ( msg.msg = WM_RBUTTONDOWN ) and inLV then
 begin
  msg := nil; //geht nicht
 end;
end;
Und jetzt brauche ich eben etwas, das die Message annulliert.
gibt es da was?

DGL-luke 9. Mai 2005 16:53

Re: Rechtsklick abschießen
 
*push*

hallo?

niemand da der mir sowas einfaches sagen kann?

dizzy 9. Mai 2005 16:55

Re: Rechtsklick abschießen
 
Ich meine es gibt WM_NULL (oder war's WM_NONE? Ich glaube eher WM_NULL...)

DGL-luke 9. Mai 2005 16:59

Re: Rechtsklick abschießen
 
EDIT:

bin ich jetzt ganz blöd??????

Delphi-Quellcode:
   {...}
    About1: TMenuItem;
    N2: TMenuItem;
    Umformungen1: TMenuItem;
    procedure LVListMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);

    procedure PMListPopup(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure About1Click(Sender: TObject);
    procedure EUnknownToKeyPress(Sender: TObject; var Key: Char);
  private
    { Private-Deklarationen }
  public
   procedure WndProc(Msg:TMessage);override; //hier deklaration
   procedure WMDropFiles(var AMsg:TWMDROPFILES); Message WM_DROPFILES;

  end;
Delphi-Quellcode:
procedure TForm1.WndProc(Msg:TMessage); //hier implenmentation
var p:TPoint;
    inLV:boolean;
begin
inherited;
p:=screentoclient(mouse.cursorpos);
inLV:= ( (p.X >= LVList.left) and (p.X <= LVList.left+LVList.width) and (p.Y >= LVList.top) and (p.Y <= LVList.top + LVList.Height) );

if ( msg.msg = WM_RBUTTONDOWN ) and inLV then
begin
  msg.Result:=1;
end;
end;
das muss doch gehen??????

er sagt mir aber
Zitat:

[Fehler] U_dragdrop_main.pas(50): E2037 Deklaration von 'WndProc' unterscheidet sich von vorheriger Deklaration

marabu 9. Mai 2005 17:25

Re: Rechtsklick abschießen
 
Hallo Lukas,

du bist auf dem Holzweg. Den Code, der die aktuelle Selektion in deiner Listview aufhebt, musst du selbst geschrieben haben. Der Rechts-Klick verschiebt lediglich den Fokus und lässt die Selektion unangetastet.

Grüße vom marabu

Lannes 9. Mai 2005 18:11

Re: Rechtsklick abschießen
 
Hallo,

was sagt denn die Delphi-Hilfe :)
Zitat:

Mit einer Ereignisbehandlungsroutine für OnChanging können Sie in Abhängigkeit von einer Bedingung die Änderung eines Listenelements verhindern, indem Sie dem Parameter AllowChange den Wert False zuweisen. Der Parameter Item ist das Listenelement, das geändert wird. Der Parameter Change zeigt die Art der Änderung an, die stattfinden soll.
ich glaube das sollte Dir weiterhelfen:
Delphi-Quellcode:
procedure TForm1.ListView1Changing(Sender: TObject; Item: TListItem;
  Change: TItemChange; var AllowChange: Boolean);
begin
  If (GetKeyState(VK_RButton) And $80 <> 0) Then
    AllowChange := False
    else
      AllowChange := True;
end;

TStringlist 9. Mai 2005 18:35

Re: Rechtsklick abschießen
 
@DGL-luke, ansonsten bezüglich der Fehlermeldung
Zitat:

[Fehler] U_dragdrop_main.pas(50): E2037 Deklaration von 'WndProc' unterscheidet sich von vorheriger Deklaration
WndProcs werden durch WindowProc-Variable gepointet und die sind wiederum vom Typ TWndMethod, dh. letzterer sieht dann in etwa ungefähr so aus:

type TWndMethod = procedure(var Message: TMessage) of object;

TeTSuO 9. Mai 2005 19:03

Re: Rechtsklick abschießen
 
Also ich habe das gerade bei mir ausprobiert
wenn ich eine Listbox erstelle ein paar items einfüge und ein Popupmenü zuweise
das ganze dann starte und ausprobiere funktioniert das mit dem Multiselect einwandfrei.
nur wenn ich auf ein frei bleibenden Teil der Listview mit rechtsklicke geht die Auswahl
verloren. hast du was anderes mit der Listview gemacht oder habe ich was falsch verstanden

TStringlist 9. Mai 2005 20:05

Re: Rechtsklick abschießen
 
@DGL-luke,

dein Plan mit dem Verschwindenlassen der WM_RButtonDown-Message funktioniert. Allerdings solltes du das inherited in deinem Code erst nach dem Nullen der Message ausführen. Hab's mal schnell gecheckt, da's mich auch interessierte ...und der Einfachheit gleich die WndProc des ListView-Controls selbst überschrieben:

Delphi-Quellcode:
  ...
  private
    oldLVWindowProc : TWndMethod;
    procedure LVWndProc(var Msg:TMessage); //hier implenmentation
  ...
Delphi-Quellcode:
procedure TForm1.LVWndProc(var Msg:TMessage); //hier implenmentation
begin
  if ( msg.msg = WM_RBUTTONDOWN ) then
  begin
    msg.msg := wm_null;
  end;

  oldLVWindowProc(Msg);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  oldLVWindowProc := ListView1.WindowProc;
  ListView1.WindowProc := LVWndProc;
end;

DGL-luke 9. Mai 2005 21:16

Re: Rechtsklick abschießen
 
ach das hat auch eins?

cool, das macht die sache SEHR viel eleganter.

aber wieso speichert man eigentlich immer die alte wndproc? wenn man sie eh nimmer braucht? nimmt doch nur speicherplatz weg :mrgreen:

werde das morgen ausprobieren, aber heute check ich nur noch schnell alles ab, morgen chemie schulaufgabe...

ps: das war ja jetzt einer der eher nicht gewünschten posts. aber ich bin mir sicher, dass da morgen schon einer was gesagt haben wird, und damit is es dann auch kein doppelpost :mrgreen:

pps: das mit der listbox: ja klar, ne listbox hatte ich auch ursprünglich, aber ich brauch halt drei spalten. und komponentenentwickeln werd ich jetzt nicht anfangen für das fuzzelprojekt.

TStringlist 9. Mai 2005 23:55

Re: Rechtsklick abschießen
 
Zitat:

Zitat von DGL-luke
aber wieso speichert man eigentlich immer die alte wndproc? wenn man sie eh nimmer braucht? nimmt doch nur speicherplatz weg :mrgreen:

Also normalerweise wird die bisherige WndProc auch weiterhin benötigt. Wenn ich eine eigene WndProc schreibe, dann stelle ich die der bisherigen nämlich quasi nur voran. In meiner selbst geschriebenen WndProc kann ich die Messages dann manipulieren oder sonst irgendwie (zusätzlich) darauf reagieren, aber auf die große Masse der Messages werde ich dort nicht eingehen, was heißt: Die meisten Messages reiche ich normalerweise also trotzdem einfach immer nur an die bisherige WndProc durch, um dort dann auch weiterhin normal darauf zu reagieren, wie in deinem Fall ja auch. (Ergo muss diese bisherige WndProc also auch weiterhin gepointet bleiben, und zwar mit einer weiteren Variablen (vom Typ TWndMethod). Normalerweise kann man die dann nennen wie man will. Bei mir jedenfalls beginnen die immer mit so einem kleinen "old" als Namenspräfix..., ...und von daher dann wahrscheinlich auch dein kleines Missverständnis *g*)

DGL-luke 10. Mai 2005 17:17

Re: Rechtsklick abschießen
 
jo, is klar. dachte das inherited; is sowas wie inline;, haut also nur den code der davor steht rein.

EDIT: das mit dem onchanging is wohl besser.
@marabu: nein, ich bin nicht auf dem holzweg. habe das ganze mit einem leeren projekt und einer TListView ausprobiert.

EDIT2: @Lannes: wann wird
Delphi-Quellcode:
$80 <> 0
true?????

EDIT3: selber drffugekommen...das magic word heisst operatorenrangfolge. :)

Lannes 10. Mai 2005 19:39

Re: Rechtsklick abschießen
 
Hallo,
Delphi-Quellcode:
If (GetKeyState(VK_RButton) And $80 <> 0) Then
wird True, wenn die rechte Maustaste gedrückt ist.
Der Status ist im höchsten Bit gespeichert, darum das "And $80 <> 0"

Man könnte genausogut folgenden Code nehmen:
Delphi-Quellcode:
If HiWord(GetKeyState(VK_RButton)) <> 0 Then

DGL-luke 10. Mai 2005 21:27

Re: Rechtsklick abschießen
 
willst dus noch ein bisschen effizienter haben?

Delphi-Quellcode:
If (GetAsyncKeyState(VK_RButton) < 0) Then
man beachte das ASync. und das <0. :stupid:

ps: habs jetzt übrigens geschafft:

Delphi-Quellcode:
procedure TForm1.AusderListelschen1Click(Sender: TObject);
begin
while (LVList.Selected <> nil) do
 LVList.Selected.Delete;
end;

TStringlist 10. Mai 2005 23:16

Re: Rechtsklick abschießen
 
hmmm? Also wenn ich z.B. jetzt mal 10 Zeilen in der ListView selectiere und dann die Maus hinter einer dieser selectierten Zeile platziere, dann bekomme ich in ListView1Changing bei einem Drücken der rechten Maustaste keine Bestätigung mehr dafür, dass eben diese rechte Maus-Button jetzt auch tatsächlich gedrückt ist. Überall woanders schon, aber an einer solchen Stelle nicht. Irre ich mich da etwa?

Delphi-Quellcode:
procedure TForm1.ListView1Changing(Sender: TObject; Item: TListItem;
  Change: TItemChange; var AllowChange: Boolean);
begin // dieses funktioniert leider nicht
  If (GetKeyState(VK_RButton) And $80 <> 0) Then beep; <- hier gibt's dann KEIN Beep
end;

edit: Ich meinte nur, weil das nämlich zufälligerweise auch gleichzeitig noch der ListView-Bereich ist, über dem sich bei einem Rechts-Klick dann auch die Selection der Zeilen ausschaltet.

Lannes 11. Mai 2005 22:11

Re: Rechtsklick abschießen
 
Hallo,
Zitat:

Zitat von TStringlist
...Überall woanders schon, aber an einer solchen Stelle nicht. Irre ich mich da etwa?
...zufälligerweise...

Nein, und ja :?

OnChanging wird nur vor der Selectionsänderung aufgerufen.
Eine Selection wird geändert indem ein anderes oder zusätzliches(Multiselect) Item(Caption) angeklickt wird.
OnChanging wird nicht ausgelöst wenn eine Selection aufgehoben wird.

Fazit :
Nur bei Mausklick auf eine Caption eines Items wird OnChanging ausgelöst und darum kein "Beep"

marabu 12. Mai 2005 06:34

Re: Rechtsklick abschießen
 
Es ist durchaus beeindruckend, wie zäh ihr alle am selbst gestellten Problem dranbleibt und zum Schluss auch eine Lösung hinkriegt. Vom Standpunkt eines Profis aus gesehen ist es aber grober Unfug den Rechtsklick auf eine ListView abzuschalten.

In einem objekt-orientierten GUI gehört zu einer ListView (und nicht nur zu der) ein Kontextmenü, das über einen Rechtsklick zu aktivieren ist. Dabei ist es völlig erwartungskonform, dass die Selektion aufgehoben wird, wenn man nicht auf ein Item, sondern auf die Listview selbst (rechts-)klickt. Im Kontextmenü sind immer nur die Befehle zu sehen, die sich auf das Objekt beziehen. In betrachteten Fall ist das GUI-Objekt dann nicht der Inhalt (ListItems), sondern die ListView selbst. Im Kontextmenü stehen dann Befehle, wie z.B. "Einstellen des Hintergrundes" dieser ListView.

@DGL-Luke: Verstehst du jetzt, was ich mit Holzweg meinte? Hätte ich das hier in meinem ersten posting geschrieben, dann hätte ich diesen thread eventuell abgewürgt - das wollte ich nicht.

Grüße vom marabu

TStringlist 12. Mai 2005 14:19

Re: Rechtsklick abschießen
 
na ja, so ganz unrealistisch war DGL-Lukes Wunsch aber auch wieder nicht. Es kann nämlich schon schlicht unpraktisch sein, dann auch mit dem Rechtsklick immer noch einmal zusätzlich exakt auf die Selektierung zielen zu müssen. Besonders, wenn die selektierte Zeile kurz ist, weil sie nur wenige und/oder schmale Buchstaben hat. Oder man hat mehrere Zeilen selektiert und es sind da ein paar (sehr) kurze dabei. Da darfst du dann beim Rechtsklick auch nicht aus Versehen mal mit der Maus in so eine "Lücke" rutschen.

Sofern eine Selektierung überhaupt da ist, sollte die bei einem Rechtsklick dann imo eben auch immer angesprochen sein. Jedenfalls ist die Konkurrenzsituation, dass man mit einem solchen danebengehenden Rechtsklick dann nämlich nicht die Selektion meint, sondern das Kontroll insgesamt, dazu ja auch eher selten (...auch schon wegen ihrer internen Doppelaktion, die Selektion zu löschen bzw. zu ändern und gleichzeitig damit dann auch noch das Kontextmenü zu starten)...

...Und irgendwelche Standard-Funktionsabläufe sollten in erster Linie aber solche Situationen unterstützen, die ein mehrheitlich klares Übergewicht haben.

Würde man tatsächlich NICHT die Selektion meinen, könnte man in solchen klar selteneren Situationen dann ja auch nochmal einen linken Zusatzklick, zum Aufheben der Selektion, verlangen. Also bloß eine zusätzliche Minimal-Aktion, die dem Handling von Selektionen dann aber durchaus wieder insgesamt mehr Eindeutigkeit und Komfort verschaffen würde.

Ergo: Kleinere Optimierungen an solchen suboptimalen DIN-Abläufen zu versuchen, ist eher legitim und macht ja den besonderen Reiz des Programmierens auch immer irgendwie etwas mit aus...


PS. Diskussionen, die in eine falsche Richtung gehen, lieber frühzeitiger als später korrigieren wollen. Das ist ja dann auch ökonomischer für alle!


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:11 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz