Živě.cz o počítačích a internetu

Tipy a triky v Delphi, díl 144. - kouzlíme s OnMouseMove

Jan Šindelář 23.6.2004

Společným prvkem dnešních dvou tipů je událost OnMouseMove. Nejprve si ukážeme, jak v komponentě ListBox automaticky označit prvek pouhým ukázáním myši a v druhém tipu si pak předvedeme, jak v komponentě RichEdit zjistit, které slovo se nachází pod kurzorem myši.

Nejprve tedy příklad se zmiňovaným ListBoxem. Za normálních okolností prvky v ListBoxu ignorují pohyb myši a jedinou reakci vyvolá až kliknutí, kdy dojde k označení příslušného prvku v seznamu.

Velmi jednoduchým způsobem můžeme zařídit, aby se automaticky označoval ten prvek, který se nachází pod kurzorem myši. ListBox pak vlastně připomíná svým chováním běžné menu. Stačí nám do události OnMouseMove přidat jediný řádek, který na základě souřadnic kurzoru v daném ListBoxu označí příslušný prvek. Můžeme tak tímto způsobem výrazně zpřehlednit ovládání naší aplikace. Ovšem za předpokladu, že není potřeba vybírat z ListBoxu více položek najednou, protože pak by tento postup nebyl příliš vhodný. Vlastnost MultiSelect tedy nastavte na False, naplňte ListBox několika testovacími řádky a můžete si tento velmi jednoduchý příklad hned vyzkoušet (viz. zdrojový kód).

Druhý tip je o něco delší a týká se komponenty RichEdit. Opět s využitím události OnMouseMove budeme tentokrát zjišťovat, které slovo se právě nachází pod kurzorem myši. Toto slovo pak budeme zobrazovat ve stavovém řádku. Na formulář tedy přidejte RichEdit s nějakým vyplněným textem a StatusBar. Postup je pak takový, že nejprve opět pomocí souřadnic kurzoru a také s využitím zpráv systému zjistíme, na kterém řádku a v jaké pozici se kurzor nachází. Poté cyklem určíme hranice slova a vypíšeme ho do StatusBaru. Hranice slova určíme s využitím definované množiny oddělovačů slov, kterou tvoří mezera a interpunkční znaménka. Přidat si pochopitelně můžete libovolné další znaky podle vaší potřeby.

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    StatusBar1: TStatusBar;
    ListBox1: TListBox;
    procedure RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure ListBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.RichEdit1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  chr, line, chpos, k, j: Integer;
  Pt: TPoint;
  s, WordUnderCur: string;
  inter: set of char;
begin
  inter := [` `, `,`, `.`, `?`, `!`];
  with TRichEdit(Sender) do
    begin
      Pt := Point(X, Y);
      chr := Perform(EM_CHARFROMPOS, 0, Integer(@Pt));
      if chr < 0 then Exit;
      line := Perform(EM_EXLINEFROMCHAR, 0, chr);
      chpos := chr - Perform(EM_LINEINDEX, line, 0);
      if Lines.Count - 1 < line then Exit;
      s := Lines[line];
      k := chpos;
      while (k > 0) and (not (s[k] in inter)) do k := k - 1;
      k := k + 1;
      j := k;
      while (j <= Length(s)) and (not (s[j] in inter)) do Inc(j);
      WordUnderCur := Copy(s, k, j-k);
    end;
  StatusBar1.SimpleText := WordunderCur;
end;

procedure TForm1.ListBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  ListBox1.ItemIndex := ListBox1.ItemAtPos(Point(x, y), True);
end;

end.

Po spuštění programu se tedy bude zobrazovat do stavového řádku to slovo, které se nachází pod kurzorem myši. Pochopitelně je to jen na ukázku a v reálné aplikaci můžeme zobrazovat například nějakou formu nápovědy pro dané slovo (synonymum, překlad do cizího jazyka a podobně).

Zdrojový kód obou dnešních příkladů v jednom projektu (Delphi7) a to i ve zkompilované podobě pro rychlé otestování si můžete stáhnout zde.