Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Multiselect mit Strg + Maus (wie?) (https://www.delphipraxis.net/94670-multiselect-mit-strg-maus-wie.html)

Alter Mann 25. Jun 2007 12:27


Multiselect mit Strg + Maus (wie?)
 
Hallo,

um das mehrfache selektieren von Elementen zu unterstützen, dachte ich mir
machst es wie allgemein üblich mit Strg+(linker)Maustaste.

Doch nun nach einigen Versuchen, stellt sich die Frage: Wie macht man das?

Das setzen eines Flags zum Beginn der Auswahl stellt nich das Problem dar, sondern
eher die Hürde festzustellen wann ist die Auswahl beendet.

Hat jemand Ideen bzw. ein Lösungsvorschlag?

Gruss

SirThornberry 25. Jun 2007 12:30

Re: Multiselect mit Strg + Maus (wie?)
 
ich versteh nicht so recht das Problem. Wird mit der Maus etwas angeklickt und die Strg-Taste ist nicht gedrückt, so wird das angeklickte selektiert und alles andere deselktiert. Ist die Strg-Taste gedrückt wird das deselektieren einfach weg gelassen.

Alter Mann 25. Jun 2007 18:10

Re: Multiselect mit Strg + Maus (wie?)
 
Das Problem ist, das nur bei gedrückter Strg-Taste mit der Maus selektiert wird und das ist bei jedem mir bekannten
Programmen so. Aber egal.

Wenn ich also vereinfacht ausgedrückt mir ein Flag bastel welches beim ersten drücken der Maustaste, den Shiftstate auswertet und bei gedrückter Strg-Taste gesetzt wird.

Delphi-Quellcode:
...
    iMultiSelect : Boolean; // fortlaufene Merhfachauswahl 1-10
    mMultiSelect : Boolean; // manuelle Mehrfachauswahl 1, 3, 6, 12 usw.
    iButton      : Boolean; // Auswahl mit linker Maustaste, wird zwischen gespeichert,
                             // da in MouseMove kein Button übergeben wird
...

procedure  TCalendarControl.MouseDown(Button: TMouseButton;
                                       Shift: TShiftState;
                                       X, Y: Integer);
begin
  iButton := Button = mbLeft;
  if iButton and FOptions.MultiSelect and not mMultiSelect and (ssCtrl in Shift) then
   mMultiSelect := True;
  inherited;
end;
Damit weiß ich also, der User will etwas Mehrfach auswählen und kann in MouseUp entsprechend reagieren.

Delphi-Quellcode:
procedure  TCalendarControl.MouseUp(Button: TMouseButton;
                                     Shift: TShiftState;
                                     X, Y: Integer);
var
  I, J, FMin : Integer;
begin
  iButton := False;
  if Button = mbLeft then
  begin
    if FWeekNumbers then FMin := 1
                    else FMin := 0;

    if iMultiSelect or mMultiSelect then
    begin
      if not (ssCtrl in Shift) and iMultiSelect then iMultiSelect := False;
      for J := 0 to FMaxWeeks do
      begin
        for I := FMin to FMax do
        begin
          if TCalenderEntry(FWeeks[J][I]).MouseInRect(X, Y) then
          begin
            if FMultiSelDates.IndexOf(TCalenderEntry(FWeeks[J][I])) = -1 then
            FMultiSelDates.Add(TCalenderEntry(FWeeks[J][I]));
          end;
        end;
      end;
      if iMultiSelect then DoMultiSelect(FMultiSelDates);
      Invalidate;
    end
...
Bis hierher funktioniert die Sache ja auch, die gewälten Elemente werden in die Liste FMultiSelect eingetragen.
Erfolgt jedoch die Auswahl mit zusätzlich gedrückter Strg+Taste wird jedesmal bei der Auswahl mit der Maus
KeyUP mitaufgerufen...

Delphi-Quellcode:
procedure  TCalendarControl.KeyUp(var Key: Word; Shift: TShiftState);
begin
  if mMultiSelect and not (ssCtrl in Shift) then mMultiSelect := False;
  inherited KeyUp(Key, Shift);
end;
und das Flag mMultiSelect wird gelöscht, weil Shift(warum auch immer) kein ssCtrl mehr enthält.

Nun verstanden?

SirThornberry 25. Jun 2007 18:38

Re: Multiselect mit Strg + Maus (wie?)
 
Zitat:

Das Problem ist, das nur bei gedrückter Strg-Taste mit der Maus selektiert wird und das ist bei jedem mir bekannten
Programmen so. Aber egal.
ich kenne es anders (siehe windows-explorer etc.).
Klickt man etwas an wird es selektiert. Ist während des MouseDown die Strg-Taste nicht selektiert wird die vorherige Selektierung entfernt.

Aber ich glaube ich versteh dein Problem nicht und wir reden aneinander vorbei.

Alter Mann 25. Jun 2007 23:19

Re: Multiselect mit Strg + Maus (wie?)
 
So, So,

Zitat:

(siehe windows-explorer etc.)
Warum sollte ich etwas anklicken was ich nicht haben will und die anderen Sache hinterher erst mit Strg+Maus deselektieren.
Ich kann sie auch auch gleich mit Strg+Maus auswählen(probier mal, aber nichts anderes vorher machen, auch kein Strg+A).

Ansonsten schönen Tag noch.

Gruss

SirThornberry 26. Jun 2007 07:42

Re: Multiselect mit Strg + Maus (wie?)
 
das verhalten bleibt doch gleich (gerade probiert). Wenn man etwas anklickt ohne das Strg gedrückt ist wird nur das angeklickte Selektiert und alles andere was zu diesem Zeitpunkt eventuell selektiert war wird deselektiert. Ist Strg gedrückt wird die Selektierung des angeklickten negiert.

ibp 26. Jun 2007 09:27

Re: Multiselect mit Strg + Maus (wie?)
 
@sirT: das funktioniert schon seit ewigkeiten. :wink:

dann lass doch die flag-rückstellung weg im onkeyup!

imho brauchst du nicht ständig die strg-taste gedrückt halten. du kannst sie auch jedesmal vor der maustaste drücken. nur wenn du ohne strg-tste die mausaktion durchführst, dann wird die auswahl wieder aufgehoben und nur das eine element selektiert.

vielleicht reicht das ja...

Delphi-Quellcode:
procedure  TCalendarControl.MouseDown(Button: TMouseButton;
                                       Shift: TShiftState;
                                       X, Y: Integer);
begin
  iButton := Button = mbLeft;
  {if iButton and FOptions.MultiSelect and not mMultiSelect and (ssCtrl in Shift) then
   mMultiSelect := True; }

  // multiselekt nur true wenn zusätzlich auch ctrl gedrückt ansonsten false...
  mMultiSelect := iButton and FOptions.MultiSelect and not mMultiSelect and (ssCtrl in Shift);

  inherited;
end;

SirThornberry 26. Jun 2007 10:24

Re: Multiselect mit Strg + Maus (wie?)
 
Also ich hab mal fix eine Testkomponente programmiert und die funktioniert eigentlich Windowsüblich:
Delphi-Quellcode:
unit uExampleCtrl;

interface

uses
  windows, classes, graphics, controls;

type
  TExampleCtrl = class(TCustomControl)
  private
    fStati : Array[0..5] of Boolean;
  protected
    procedure Paint(); override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

implementation

{ TExampleCtrl }

constructor TExampleCtrl.Create(AOwner: TComponent);
var
  lCount : Integer;
begin
  inherited Create(AOwner);
  ZeroMemory(@fStati, SizeOf(fStati));
  SetBounds(0, 0, 300, 300);
end;

procedure TExampleCtrl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  lIndex : Integer;
begin
  inherited;
  lIndex := X div (Width div 3) + Y div (Height div 2) * 3;
  if (ssCtrl in Shift) then
    fStati[lIndex] := not(fStati[lIndex])
  else
  begin
    ZeroMemory(@fStati, SizeOf(fStati));
    fStati[lIndex] := True;
  end;
  Invalidate();
end;

procedure TExampleCtrl.Paint;
var
  lCountX,
  lCountY,
  lIndex,
  lPartHeight,
  lPartWidth : Integer;

begin
  lPartHeight := Height div 2;
  lPartWidth := Width div 3;

  Canvas.Brush.Color := clWhite;
  Canvas.FillRect(Rect(0, 0, Width, Height));
  Canvas.Brush.Color := clBlue;
  for lCountY := 0 to 1 do
  begin
    for lCountX := 0 to 2 do
    begin
      lIndex := lCountX + lCountY * 3;
      if fStati[lIndex] then
      begin
        Canvas.FillRect(Rect(lCountX * lPartWidth, lCountY * lPartHeight, (lCountX + 1) * lPartWidth, (lCountY + 1) * lPartHeight));
      end
      else
      begin

      end;
    end;
  end;

  Canvas.Pen.Color := clBlack;
  Canvas.MoveTo(0, Height div 2);
  Canvas.LineTo(Width, Height div 2);

  Canvas.MoveTo(lPartWidth, 0);
  Canvas.LineTo(lPartWidth, Height);
  Canvas.MoveTo(lPartWidth * 2, 0);
  Canvas.LineTo(lPartWidth * 2, Height);
end;

end.

Alter Mann 26. Jun 2007 11:10

Re: Multiselect mit Strg + Maus (wie?)
 
Hallo,

Danke für die Antworten.

@ibp
Wenn ich die Flagrückstellung weglasse, erfolgt eine Übernahme der Werte nur bei
jeden zweiten Klick und bei den nächsten Klick wird der Wert auch übernommen, obwohl
dieser die Auswahl löschen und sich normal verhalten sollte.

Mal schauen woran das liegt.

@SirThornberry

Deine Lösung ist OK.
Hat für mich nur den Nachteil, das mit einem festen Statuspuffer gearbeitet wird, aber
das läst sich ja ändern.

Ich werde sehen was ich davon umsetze.

Gruß


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:39 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