Einzelnen Beitrag anzeigen

Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.077 Beiträge
 
Delphi XE2 Professional
 
#10

AW: TComboBox - MouseMove

  Alt 12. Aug 2018, 10:49
Ich gebe Dir ein Beispiel okay, da ich Deinen Source nicht kenne ist es universal Einsetzbar.
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
  private
    procedure ApplicationIdle(sender: TObject; var Done: boolean);
  end;
Delphi-Quellcode:
procedure TForm1.ApplicationIdle(sender: TObject; var Done: boolean);
var
  pt: TPoint;
  wnd: HWND;
  buf: array[0..128] of Char;
  i: Integer;
begin
  GetCursorPos(pt);
  wnd := WindowFromPoint(pt);
  If wnd <> 0 then
    begin
      buf[0] := #0;
      GetClassName(wnd, buf, SizeOf(buf));
      If StrIComp(buf, 'ComboLBox') = 0 Then
        Begin
          Windows.ScreenToClient(wnd, pt);
          i := SendMessage(wnd, LB_ITEMFROMPOINT, 0, lparam(PointToSmallpoint(pt)));
          If i >= 0 Then
            Begin
              SendMessage(wnd, LB_GETTEXT, i, integer(@buf));
              Label1.Caption := buf; // <<<< HIER ÄNDERE DEN EMPFÄNGER, MIR IST DEIN SOURCE UNBEKANNT
              Exit;
            End;
        End;
    end;
end;
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.DropDownCount := 2;
  Application.OnIdle := ApplicationIdle;
end;
Dieser Code bewirkt das mir im Label1 ein Item aus einer aufgeklappten ComboBox wo Maus gerade drüber ist angezeigt wird.
Ob Du nun den Item Text darstellst oder per Pos() nach irgend was suchst um den Output anzupassen obliegt Deiner Phantasie.
Löst das Dein Problem oder habe ich es falsch verstanden?

Ps: Getestet mit D2009, da reicht es mit dem DropDownCount zu arbeiten.
Hallo KodeZwerg,
vielen Dank.
Nach ein paar Anlaufschwierigkeiten funktioniert das hervorragend.
Eine Beobachtung am Rande:
Wenn die Liste aufgeklappt wird und die Maus in das TextFeld der ComboBox gestellt wird, liefert GetClassName nicht 'ComboLBox'.
Ist auch logisch, denn die Maus ist ja nicht in der Liste.
Bewege ich aber nach dem Aufklappen die Maus in die Liste und dann in das TextFeld, dann liefert GetClassName 'ComboLBox', auch wenn die Maus nicht mehr in der Liste ist.
Hierbei ist es egal, ob ich die Maus in der Liste einfach nach oben bis in das Textfeld verschiebe oder z.B. nach rechts aus der Liste heraus, außerhalb der Liste nach oben und dann in das Textfeld.
Der mit I:=SendMessage(Wnd,LB_ITEMFROMPOINT,0,LParam(PointToSmallpoint(MP))); geholte Index ist dann (65536 + Index der gerade markierten Zeile).
Da das zu Problemen führte hab ich in ApplicationIdle zunächst abgefragt, ob Wnd=ComboBox.Handle ist (also die Maus ins TextFeld zeigt) und dann mit ComboBox.ItemIndex weitergemacht.
Überraschung hierbei: Combobox.ItemIndex ist dann der Index des in der Liste gerade markierten Eintrags, nicht des Eintags, der im Textfeld angezeigt wird.
Das hab ich gelöst, indem ich im ComboBoxDropDown den ItemIndex der Combobox in "fComboBoxIndex" speichere.

Bei mir sieht das jetzt so aus:

Delphi-Quellcode:
procedure TMain.cbMelodiesDropDown(Sender: TObject);
begin
   fComboBoxIndex:=cbMelodies.ItemIndex;
   Application.OnIdle:=ApplicationIdle;
end;
Delphi-Quellcode:
procedure TMain.cbMelodiesCloseUp(Sender: TObject);
begin
   Application.OnIdle:=Nil;
end;
Delphi-Quellcode:
PROCEDURE TMain.ApplicationIdle(Sender:TObject; var Done:Boolean);
const CN='ComboLBox';
var I:Integer; MP:TPoint; Wnd:HWND; Buf:array[0..Length(CN)] of Char;
begin
   GetCursorPos(MP);
   EraseHint;
   Wnd:=WindowFromPoint(MP);
   if Wnd<>0 then
      if Wnd=cbMelodies.Handle then begin
         WinApi.Windows.ScreenToClient(Wnd,MP);
         if ComboBoxIndex>0 then ShowComboBoxHint(ComboBoxIndex,MP.X);
      end else if GetClassName(Wnd,Buf,SizeOf(Buf)+1)=Length(CN) then begin
         if StrIComp(Buf,CN)=0 then begin
            WinApi.Windows.ScreenToClient(Wnd, MP);
            I:=SendMessage(Wnd,LB_ITEMFROMPOINT,0,LParam(PointToSmallpoint(MP)));
            if InRange(I,0,High(TSI)) then ShowComboBoxHint(I,MP.X);
         end;
      end;
end;
"TSI" ist ein Array das Zeiger auf die Daten der in der Combobox gezeigten Melodien enthält.
Hintergrund dieser Konstruktion ist, dass ich die in der Combobox-Liste gezeigten Einträge nach beliebigen Kriterien sortiert anzeigen kann.
Im ComBoxBox DrawItem greife ich auf TSI[] zurück, nicht auf Combobox.Items (das nur leere Strings enthält).

Delphi-Quellcode:
   // Daten einer Melodie
   TTrackDataRec=packed Record
      Index:Integer; // Nummer des Tracks
      Name:String; // Name des Tracks
      Time:Integer; // Spieldauer des Tracks in ms
      SequenceCount:Integer; // Anzahl Sequenzen im Track
      Count:Integer; // Wie viel Töne Track gespielt werden
      ToneCount:Byte; // Wie viel veschiedene Töne im Track vorkommen
      MinTone:Byte; // Niedrigster Ton
      MaxTone:Byte; // Höchster Ton
      AvgTone:Byte; // Durchschnittlicher Ton
      MinIntensity:Byte; // Niedrigste Intensity
      MaxIntensity:Byte; // Höchste Intensity
      AvgIntensity:Byte; // Durchschnittliche Intensity
      MinToneCount:Byte; // Niedrigste Anzahl Töne in einer Sequenz
      MaxToneCount:Byte; // Höchste Anzahl Töne in einer Sequenz
      AvgToneCount:Byte; // Durchschnittliche Anzahl Töne in einer Sequenz
      MinSequenceTime:Integer; // Spieldauer der kürzesten Sequenz
      MaxSequenceTime:Integer; // Spieldauer der längsten Sequenz
      AvgSequenceTime:Integer; // Durchschnittliche Spieldauer der Sequenzen
      ColorRange:TColorRange; // Zugeordneter Farbbereich
   end;
   TPTrackDataRec=^TTrackDataRec;
   TTrackData=Array of TTrackDataRec;
   TTrackDataSortIndex=Array of TPTrackDataRec;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat