SynEditでマウスカーソル下の文字列を取得する

記事
IT・テクノロジー
Lazarus等で使えるSynEditの話です
単語であればGetWordAtRowColを使えばよいのですが
 ちょっと特殊な事をしたい場合の対策法です
というか GetWordAtRowCol や GetWordBoundsAtRowColは現行のLazarus 内(ver 1.0と表示される)では多バイト文字で取得位置がズレるようですから。
たぶん GetWordBoundsAtRowColに XY.X:=PhysicalToLogicalCol(LINE.XY.Y-1,XY.X): をいれたらよさそうに思うけど、ちょっと怖い。

protectedメンバーを無理やり使う

GetWordAtRowColの動作を見ると FTheLinesViewを見ていますが、これはPrivateです。どうしようもありません。 しかしFTheLinesViewはTextViewというプロパティで参照出ます。 当然使いたいのですが、これがprotectedなのです。
そこで public にしただけのクラスを
 type   TMySynEdit = class(TSynEdit) public    property TextView;  end;
と実装(implementation)に作って無理やり呼び出します。

実際のコード例

 type
  TMySynEdit = class(TSynEdit)
  public
    property TextView;
  end;
 {マウス座標の文字が "hoge"ならhogeを返す}
function GetBraketWordInSynEdit(const ed: TSynEdit; mouse: TPoint): String;
var
  ps: TPoint;
  sx, ex: Integer;
  s: String;
begin
  Result := '';
  ps := ed.PixelsToRowColumn(mouse); //画面上の文字位置を得る
  s := TMySynEdit(ed).TextView[ps.Y - 1];//その行の文字を得る
  if s = '' then exit;
  if length(s) < 3 then exit;//次の処理が重いので軽くするために
  sx := ed.PhysicalToLogicalCol(s, ps.Y - 1, ps.X);//画面上の位置のbyte番目を得る
  if sx > length(s) then exit;
  if not (s[sx] in ['_', '0'..'9', 'a'..'z', 'A'..'Z']) then exit;
  ex := sx;
  Dec(sx);
  while s[sx] <> '"' do begin
    Dec(sx);
    if sx < 1 then exit;
  end;
  Inc(ex);
  while s[ex] <> '"' do begin
    Inc(ex);
    if s[ex] = #0 then exit;
  end;
  Result := copy(s, sx + 1, ex - sx - 1);
end;

呼び出し方

//SynEditのOnMouseMoveイベントにて
procedure TForm1.SynEdit1MouseMove(Sender: TObject; Shift: TShiftState; X,  Y: Integer);
var
  s: String;
  ps: TPoint;
begin
  sr.X := X;
  sr.Y := y;
  s := GetBraketWordInSynEdit(SynMemo, sr); 
//この後に sを使う処理を描く

今回の失敗談


AnsiStringであればバイト位置と表示位置は固定幅フォントなら一致するので楽でした。
でもLazarusの内部文字はUTF8です
UTF8だと日本語文字の多くは2byte以上になってしまいます。可変長ですし、外国語だと文字幅も半角になったりします。LazarusのIDEも他のエディタでは全角なのに半角になったりする文字もあります。ややこしそうだ。という事で、

最初はPhysicalToLogicalColを呼ばなくてもAnsiStringに代入すれば日本語だけなら問題ないだろ程度に考えていたのですが、代入しても中身はUTF8だし、UTF8toAnsiとかを呼び出しても変換されない。WideStringにしてからAnsiStringに代入してみたりいろいろやってもダメ。

遠回りでした。



サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す ココナラコンテンツマーケット ノウハウ記事・テンプレート・デザイン素材はこちら