cppBuilder
TMemo

C++ Builder XE4, 10.2 Tokyo > TMemo > 最終行に移動する実装

動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)

処理の概要

TMemoで任意の場所を表示している状態から最終行の表示状態にしたい。

v0.1

参考

[Delphi] TMemoで、先頭行/最終行/指定行へ移動する by くろねこ研究所さん

上記にDelphi実装(SendMessage使用)があるものをC++ Builder実装(かつPerform使用)に変更してみた。

code

Uni1t.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_addClick(TObject *Sender)
{
    for(int loop = 0; loop < 10; loop++) {
        Memo1->Lines->Add(L"TEST");
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_moveLastClick(TObject *Sender)
{
    int iLineNow = Memo1->Perform(EM_LINEFROMCHAR, Memo1->SelStart, 0);
    int iLineLast = Memo1->Perform(EM_GETLINECOUNT, 0, 0);

    // debug
    String msg = IntToStr(iLineNow) + L":" + IntToStr(iLineLast);
    OutputDebugString(msg.c_str());

    Memo1->Perform(EM_LINESCROLL, 0, iLineLast - iLineNow);
    Memo1->SelStart = Memo1->Perform(EM_LINEINDEX, iLineLast - 1, 0);
}
//---------------------------------------------------------------------------

動作

下記の手順では最終行に移動する[成功]。

  1. スクロールバーで移動
  2. TMemo内の行をクリックしてカーソル位置を調整
  3. 最終行移動処理をする

下記の手順では最終行に移動しない[失敗]。

  1. TMemo内の行をクリックしてカーソル位置を調整
  2. スクロールバーで移動
  3. 最終行移動処理をする

原因は、スクロールした状態と実際のカーソル位置(SelStart)のずれによる。

v0.2

以下の実装とした。
上記の二通りの操作でも正常に動作する。

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_addClick(TObject *Sender)
{
    for(int loop = 0; loop < 10; loop++) {
        Memo1->Lines->Add(L"TEST");
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_moveLastClick(TObject *Sender)
{
    int lineCnt = Memo1->Lines->Count;
    Memo1->Perform(EM_LINESCROLL, 0, lineCnt);
    Memo1->SelStart = Memo1->Perform(EM_LINEINDEX, lineCnt, 0);
}
//---------------------------------------------------------------------------