2024年08月22日
前回の記事の変更点です。
というのは、最後のコードの部分が、少し複雑になっているので、もう少し簡単にしたいと思います。といっても、本の少しなんですが(笑)。
それと、新たな「WordPress サーバー」に関しては、ただ今検討中なので、もう暫く時間が掛かります。
また、その後で「新たなテーマで作成」することになるので、勉強も重なるので時間が掛かります。
まぁしかし、大凡の目処は立っているので、大丈夫です。
以下が、そのコードです。
/// <summary>
/// 行番号を描画します。
/// </summary>
/// <param name="g">Graphics</param>
/// <param name="client">Rectangle</param>
protected virtual void DrawLineNumber(Graphics g, Rectangle client)
{
// 画面上の最初の行を取得します。
int firstVisibleLine = SendMessage(
ScrollTextBox.Handle, EM_GETFIRSTVISIBLELINE, 0, 0);
// 最初の行から、その行の最初の文字の Index を取得します。
int firstVisibleIndex = ScrollTextBox
.GetFirstCharIndexFromLine(firstVisibleLine);
// その文字の Index から、見かけ上の行ではなく、実際の行を取得します。
// (Wordwrap 対策として、SecondScrollTextBox を使います。)
int reallyFirstVisibleLine = SecondScrollTextBox
.GetLineFromCharIndex(firstVisibleIndex);
// テキスト全体の最後の行を取得します。
int totalLine = ScrollTextBox
.GetLineFromCharIndex(ScrollTextBox.Text.Length);
// 画面に表示するテキストの最大行数を計算します。
int totalVisibleLines = totalLine - firstVisibleLine;
// フォントの高さを取得します。
// ただし、フォントの高さと、実際に表示される行高とは、異なって
// いるので、FontScrollTextBox から、実際の高さを取得します。
Point reallyLinePt = FontScrollTextBox
.GetPositionFromCharIndex(7);
// 空白行を作るために、一行前の実際の行数を取得します。
// (WordWrap 対策です。)
int beforeVisibleLine = firstVisibleLine;
if (ScrollTextBox.WordWrap)
{
if (firstVisibleLine > 0)
{
int beforeVisibleIndex = ScrollTextBox
.GetFirstCharIndexFromLine(firstVisibleLine - 1);
beforeVisibleLine = SecondScrollTextBox
.GetLineFromCharIndex(beforeVisibleIndex);
}
else
{
beforeVisibleLine = -1;
}
}
beforeVisibleLine += 1;
// 行番号を描画します。
Font nmfont = NumberProperty.Font; // 行番号の Font。
SolidBrush foreBrush = new SolidBrush(NumberProperty.ForeColor);
// 行番号を作成します。
for (int i = firstVisibleLine + 1, rowCnt = 0;
i <= firstVisibleLine + totalVisibleLines + 1;
i++, rowCnt++)
{
// 行番号を作成します。
string st = "";
if (ScrollTextBox.WordWrap)
{
// 画面上の行の最初の文字の Index を取得します。
int dspFirstIndex = ScrollTextBox
.GetFirstCharIndexFromLine(i - 1);
// 実際の行を取得します(Wordwrap 無しとして)。
int dspReallyFirstLine = SecondScrollTextBox
.GetLineFromCharIndex(dspFirstIndex) + 1;
if (i == 1 || dspReallyFirstLine != beforeVisibleLine)
{
st = dspReallyFirstLine.ToString().PadLeft(5, ' ') + "\r\n";
}
beforeVisibleLine = dspReallyFirstLine;
}
else
{
st = i.ToString().PadLeft(5, ' ') + "\r\n";
}
// 描画文字長を取得。
SizeF stSz = g.MeasureString(st, nmfont);
// 右寄せ位置を取得。
PointF pt = new PointF(client.Width - stSz.Width - 10,
reallyLinePt.Y * rowCnt + (reallyLinePt.Y - nmfont.Height) / 2);
// 表示位置が、Client 領域を超えた時点で、終了します。
if (pt.Y > client.Height)
{
break;
}
// 描画。
g.DrawString(st, nmfont, foreBrush, pt);
}
foreBrush.Dispose();
}
変更した点は、表示行数を計算するのではなく、表示位置が「Client.Height」を超えた時点で、表示を終了するようにしました。
コードというのは基本的に、「計算数」や「変数の数」が少ない方が、プログラマー的には楽なので、速度差がそれ程なければ、その方が良いです。
まぁしかし、前回のコードも経験則の一つとして、検討して見るというのも、一興かと思います(笑)。
ということで、改良点やバグ等があれば、また報告したいと思います。それではこの辺で、ごきげんよう。
-
no image
-
no image
この記事へのトラックバックURL
https://fanblogs.jp/tb/12673518
※ブログオーナーが承認したトラックバックのみ表示されます。