2019年11月26日

2019-11-26 Delphi のメモコンポーネント(TMemo)の拡張

2019-11-26 Delphi のメモコンポーネント(TMemo)の拡張

Delphi XE2 で開発を行っていますがテキストを表示する「TMemo」のコンポーネントがあります。
「TMemo」は絵文字の表示も可能ですが、一般的なエディタでは可能な「改行」「タブ表示」「終端記号」「全角空白」の表示には対応していません。
Web を検索して、「WMPaint」のイベントでデフォルトの表示を行った後に、上書きでキャンバスに書き込む事で可能という事が判りました。
ただ参考にしたコンポーネントは「TMemo」でなく「TRichEdit」でしたので、「TMemo」用にあらたに作成しなおしました。

今回拡張した「TMemoEx」には「EditMrks」のプロパティが追加されます。
その配下に「CrlfMark」「EpofMark」「S@paceMark」「TabMark」が追加されます。
それぞれに「Color」「Enabled」「Mark」が追加されます。

全ての「Enabled」を「FALSE」にすれば、通常の「TMemo」と同じになります。

各記号を変更したい場合は、「MemoEx.pas」の
FEofMark.Mark := '←';
FCrlfMark.Mark := '↓';
FTabMark.Mark := '・';
FSpaceMark.Mark := '□';
を変更して下さい。

ソースは以下からダウンロードして下さい。
http://bonworld-annsfm.sblo.jp/article/185739733.html


TMemoEx.jpg
追加されたプロパティ

posted by bonworld at 09:07| Comment(0) | TrackBack(0) | Delphi

2019年11月25日

2019-11-25 Delphi のメモコンポーネント(TMemo)の高速表示

2019-11-25 Delphi のメモコンポーネント(TMemo)の高速表示

Delphi XE2 で開発を行っていますがテキストを表示する「TMemo」のコンポーネントがあります。

テキストを設定するには以下の1,2,3の方法があります。行数が多い場合は、ファイルから直接読み込んで表示がする方法が、追加して表示するより圧倒的に早い、という結果になります。

単純に読み込んで表示する場合は、ファイルから直接読み込んで下さい。

ただ、ファイルから読み込んで処理を行った結果を反映させる場合には、処理を行った結果のファイルリストを作成して、このファイルリストをストリームに保存してか、このストリームを一括して読み込むと、ファイルから直接読み込んだのと同じ効果が得られます。

1:文字列を追加して表示(遅い)

StrList1.LoadFromFile('C:\test\123.txt');
Memo1.Lines.BeginUpdate;
for iRow1 := to StrList1.Count-1 do
begin
Memo1.Lines.Add(StrList1.Strings[iRow1]);
end;
Memo1.Lines.EndUpdate;

2:ファイルから直接読み込んで表示(早い)

Memo1.Lines.LoadFromFile('C:\test\123.txt');

3:ストリームから読み込んで表示(処理を行った後にストリームから読み込みで早い)
ただし、絵文字を含んだ場合は、絵文字が正常に表示されません。

var
StrStream1: TMemoryStream;
StrList1: TStringList;
StrList2: TStringList;
begin
StrList1 := TStringList.Create;;
StrList2 := TStringList.Create;;

StrList1.LoadFromFile('C:\test\123.txt');
for iRow1 := 0 to trList1.Count-1 do
begin
StrList2.Lines.Add(...StrList1.Strings[iRow1]を処理した結果... );
end;

StrStream1 := TStringStream.Create(StrList2.Text);
Memo1.Lines.LoadFromStream(StrStream1);
StrStream1.Free;

StrList1.Free;
StrList2.Free;
end;


4:Delphi XE2 のファイル読み込み
文字コードを指定して、ファイルから直接読み込みます。絵文字の表示は可能です。

procedure TFormMain.LoadFile(Sender: TObject);
var
Enc1: TEncoding;
begin
//SJIS
if IntReadEncode1 = ENCODE_SJIS then
begin
Enc1 := TEncoding.GetEncoding(932);
try
Memo1.Lines.LoadFromFile(StrLoadFileName, Enc1);
finally
Enc1.Free;
end;
end
//JIS
else if IntReadEncode1 = ENCODE_JIS then
begin
Enc1 := TEncoding.GetEncoding(50220);
try
Memo1.Lines.LoadFromFile(StrLoadFileName, Enc1);
finally
Enc1.Free;
end;
end
//EUC
else if IntReadEncode1 = ENCODE_EUCJP then
begin
Enc1 := TEncoding.GetEncoding(20932);
try
Memo1.Lines.LoadFromFile(StrLoadFileName, Enc1);
finally
Enc1.Free;
end;
end
//UTF7
else if IntReadEncode1 = ENCODE_UTF7 then
begin
Memo1.Lines.LoadFromFile(StrLoadFileName, TEncoding.UTF7);
end
//UTF8 BOM
else if IntReadEncode1 = ENCODE_UTF8_BOM_ON then
begin
Memo1.Lines.LoadFromFile(StrLoadFileName);
end
//UTF8
else if IntReadEncode1 = ENCODE_UTF8_BOM_OFF then
begin
Memo1.Lines.LoadFromFile(StrLoadFileName, TEncoding.UTF8);
end
//UTF16 BOM BE
else if IntReadEncode1 = ENCODE_UTF16_BOM_ON_BE then
begin
Memo1.Lines.LoadFromFile(StrLoadFileName);
end
//UTF16 BE
else if IntReadEncode1 = ENCODE_UTF16_BOM_OFF_BE then
begin
Memo1.Lines.LoadFromFile(StrLoadFileName, TEncoding.BigEndianUnicode);
end
//UTF16 BOM LE
else if IntReadEncode1 = ENCODE_UTF16_BOM_ON_LE then
begin
Memo1.Lines.LoadFromFile(StrLoadFileName);
end
//UTF16 LE
else if IntReadEncode1 = ENCODE_UTF16_BOM_OFF_LE then
begin
Memo1.Lines.LoadFromFile(StrLoadFileName, TEncoding.Unicode);
end
//ここはない
else
begin
end;
end;

posted by bonworld at 09:38| Comment(0) | TrackBack(0) | Delphi

2019年11月24日

2019-11-24 Delphi のメモコンポーネント(TMemo)の同期

2019-11-24 Delphi のメモコンポーネント(TMemo)の同期

Delphi XE2 で開発を行っていますがテキストを表示する「TMemo」のコンポーネントがあります。
テキストの表示は簡単ですが、残念ながら行番号を表示する機能はありません。
テキストを表示する「Memo1」と行番号を表示する「Memo2」を作成し、両者のスクロールを同期して対応します。

「TMemo」にスクロールイベントを追加しましたが、垂直のスクロールバーの四角のツマミでスクロールさせた時はイベントは発生しませんでした。

最終的にタイマーを追加してタイマーイベント(200ms)で両者の最上行を監視して、今回最上行が前回最上行と異なったら、反対側をスクロールする処理で対応しました。


private
IntTopLineMemo: Integer;
IntTopLineNumber: Integer;

procedure TFormMain.Timer6Timer(Sender: TObject);
var
iLine5: Integer;
iLine6: Integer;
iLine7: Integer;
iLine8: Integer;
begin
if Memo1.Lines.Count > 0 then
begin
//画面の最上行
iLine5 := Memo1.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
//前回と違う
iLine5 <> IntTopLineMemo then
begin
//画面の最上行
iLine6 := Memo2.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
//移動
Memo2.Perform(EM_LINESCROLL, 0, iLine5 - iLine6);
end;
IntTopLineMemo := iLine5;
end;

if Memo2.Lines.Count > 0 then
begin
//画面の最上行
iLine7 := Memo2.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
前回と違う
if iLine7 <> IntTopLineNumber then
begin
//画面の最上行
iLine8 := Memo1.Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
//移動
Memo1.Perform(EM_LINESCROLL, 0, iLine7 - iLine8);
//フォーカス設定
Memo1.SetFocus;
end;
IntTopLineNumber := iLine7;
end;
end;


posted by bonworld at 11:06| Comment(0) | TrackBack(0) | Delphi