質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
C++Builder

C++Builderは、C/C++を用いてアプリ開発できる統合開発環境 (IDE) 。DelphiのC++版です。コンポーネントによるビジュアル開発、高機能なコードエディターなどで生産性の高い開発ができます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

条件によりRichEditの行の色を変えたい(Windows10)

dem0nmichik0
dem0nmichik0

総合スコア37

C++Builder

C++Builderは、C/C++を用いてアプリ開発できる統合開発環境 (IDE) 。DelphiのC++版です。コンポーネントによるビジュアル開発、高機能なコードエディターなどで生産性の高い開発ができます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1回答

0グッド

0クリップ

2235閲覧

投稿2019/10/15 00:58

###実現したいこと
次のフォーマットでRichEditに文字列を表示したい.状態(発生/回復=赤色/黒色)によって色を変えたい。

【フォーマット】
[番号1]_年(1,000位,100位)年(10位,1位)/月/日_時:分:秒__No.番号2-番号3_故障名_状態」
・ 番号1:3桁表示で右寄せ,0でパディング.
・ 年,月,日,時,分,秒:2桁表示,0でパディング.
・ 番号2:2桁表示で右寄せ,0でパディング.
・ 番号3:1桁表示で右寄せ.
・ 故障名:最大48文字まで
・状態:全角2文字で"発生"または"回復"
・ _(アンダーバー)は半角2文字分のスペース

【実現したい例】
[001] 2018/12/05 23:09:09 No.01-1 Labelイベントハンドラ 発生
[002] 2018/12/05 23:09:09 No.01-1 Button1イベントハンドラ 発生



[019] 2018/12/05 23:09:09 No.01-1 Label1イベントハンドラ 回復(赤色)
[020] 2018/12/05 23:09:09 No.01-1 Button1イベントハンドラ 回復(赤色)
スクロールにより,No.021からNo.100までも表示できる.

###困っていること
上記,【実現したい例】のようにRichEditに文字列を表示したいのですが,下記Windows7の画面からWindows10に移行すると,回復の状態の行が赤色と赤色が混ざってしまいます。どなたか解決方法をご教授お願いいたします。「テスト」の部分は実際には故障名称が入っておりますが,秘密保持の観点から消しています。ご了承ください。

【Windows7時の画面(上手くいく画面(発生時が赤色,回復時が黒色))】
![イメージ説明

【Windows10に移行後の画面(上手くいかない画面(赤色と黒色が混ざる))】
イメージ説明

###試したこと
TRichEditで書式が部分的に変更できない場合の対処法
を参考に「CRやLF」を考慮してコードに修正してみたが,上手くいかなかった。また,Lines->Addではなく,SelTextに修正したりしたが,上手くいかなかった。

###ソースコード
該当箇所を抜粋します。

C++

1void __fastcall TFailureHistory::ShowFailureHistory(void) 2{ 3 // 変数宣言 4 AnsiString caption; 5 AnsiString temp; 6 AnsiString isTrodgState; 7 char historyBuff[DISPLAY_MAX][LABEL_MAX]; // 故障履歴ラベルバッファ 8 AnsiString trodgName; // 故障名称 9 10 //----- 初期化 ----- 11 BYTE l = 0; 12 BYTE m = 0; 13 memset( &historyBuff[0][0], 0, sizeof(historyBuff) ); 14 WORD allPages = 0; // 故障履歴の総ページ 15 WORD showPages = 0; // 故障履歴の現在ページ 16 WORD pageUp = 0; // 前に表示可能なページ数 17 WORD pageDown = 0; // 次に表示可能なページ数 18 19 // 履歴表示エリア内を削除 20 _failureHistoryRichEdit->Lines->Clear(); 21 //------------------ 22 23 //----- 「前」および「次」に表示可能なページ数の計算 ----- 24 // 前に表示可能なページ数が割り切れない場合 25 if( (GA_startHistoryIdx%DISPLAY_MAX) != 0 ) 26 { 27 pageUp = (GA_startHistoryIdx/DISPLAY_MAX)+1; 28 } 29 // 前に表示可能なページ数が割り切れる場合 30 else 31 { 32 pageUp = (GA_startHistoryIdx/DISPLAY_MAX); 33 } 34 // 次に表示可能なページ数が割り切れない場合 35 if( ((GA_history.count-GA_endHistoryIdx) % DISPLAY_MAX) != 0 ) 36 { 37 pageDown = ( (GA_history.count-GA_endHistoryIdx) / DISPLAY_MAX ) + 1; 38 } 39 // 次に表示可能なページ数が割り切れる場合 40 else 41 { 42 pageDown = ( (GA_history.count-GA_endHistoryIdx) / DISPLAY_MAX ); 43 } 44 //-------------------------------------------------------- 45 46 //----- 故障履歴の総ページ数を計算後,表示 ----- 47 // 故障履歴の総ページをセット 48 allPages = (pageUp + 1 + pageDown); 49 // 故障履歴の総ページ数(分母)を表示 50 denominator->Caption = IntToStr(allPages); 51 denominator->Left = GetFailureHistoryPosition(allPages); 52 //---------------------------------------------- 53 54 //----- 故障履歴の表示ページを計算後,表示 ----- 55 // 故障履歴の表示ページをセット 56 showPages = (pageUp + 1); 57 // 最初の故障履歴件数番号(分子)を表示 58 numerator->Caption = IntToStr(showPages); 59 numerator->Left = GetFailureHistoryPosition(showPages); 60 //---------------------------------------------- 61 62 // 故障履歴件数が1件以上の場合 63 if( GA_history.count > 0 ) 64 { 65 // 故障履歴情報をバッファに設定するループ(最大100) 66 for(WORD i=GA_startHistoryIdx; i<GA_endHistoryIdx; i++, l++) 67 { 68 // 故障名称バッファに故障名称をセット 69 trodgName = GA_history.data[i].trodgName; 70 for( int k=trodgName.Length(); k<STRING_MAX; k++) 71 { 72 // 48文字の内,空きスペースに半角スペースをセット 73 trodgName += " "; 74 } 75 // 故障情報が代表故障の場合 76 if( GA_history.data[i].trackNo != 0 ) 77 { 78 // 故障情報がアークネット情報の場合 79 if( GA_history.data[i].trainNo != 0 ) 80 { 81 // 故障状態が異常の場合 82 if( GA_history.data[i].isTrodgState == ON ) 83 { 84 sprintf( historyBuff[l], 85 "[%03d] %02d%02d/%02d/%02d %02d:%02d:%02d%4d号線 No.%02d-%d %-s発生", 86 (l+1), 87 GA_history.data[i].yyh, 88 GA_history.data[i].yyl, 89 GA_history.data[i].mm, 90 GA_history.data[i].dd, 91 GA_history.data[i].hh, 92 GA_history.data[i].ms, 93 GA_history.data[i].ss, 94 GA_history.data[i].trackNo, 95 GA_history.data[i].trainNo, 96 GA_history.data[i].doorNo, 97 trodgName.c_str()); 98 } 99 // 故障状態が正常の場合 100 else 101 { 102 sprintf( historyBuff[l], 103 "[%03d] %02d%02d/%02d/%02d %02d:%02d:%02d%4d号線 No.%02d-%d %-s回復", 104 (l+1), 105 GA_history.data[i].yyh, 106 GA_history.data[i].yyl, 107 GA_history.data[i].mm, 108 GA_history.data[i].dd, 109 GA_history.data[i].hh, 110 GA_history.data[i].ms, 111 GA_history.data[i].ss, 112 GA_history.data[i].trackNo, 113 GA_history.data[i].trainNo, 114 GA_history.data[i].doorNo , 115 trodgName.c_str()); 116 } 117 } 118 119 if( GA_history.data[i].trainNo == 0 ) 120 { 121 // 故障状態が異常の場合 122 if( GA_history.data[i].isTrodgState == ON ) 123 { 124 sprintf( historyBuff[l], 125 "[%03d] %02d%02d/%02d/%02d %02d:%02d:%02d%4d号線%11s%-s発生", 126 (l+1), 127 GA_history.data[i].yyh, 128 GA_history.data[i].yyl, 129 GA_history.data[i].mm, 130 GA_history.data[i].dd, 131 GA_history.data[i].hh, 132 GA_history.data[i].ms, 133 GA_history.data[i].ss, 134 GA_history.data[i].trackNo, 135 " ", 136 trodgName.c_str()); 137 } 138 // 故障状態が正常の場合 139 else 140 { 141 sprintf( historyBuff[l], 142 "[%03d] %02d%02d/%02d/%02d %02d:%02d:%02d%4d号線%11s%-s回復", 143 (l+1), 144 GA_history.data[i].yyh, 145 GA_history.data[i].yyl, 146 GA_history.data[i].mm, 147 GA_history.data[i].dd, 148 GA_history.data[i].hh, 149 GA_history.data[i].ms, 150 GA_history.data[i].ss, 151 GA_history.data[i].trackNo, 152 " ", 153 trodgName.c_str()); 154 } 155 } 156 } 157 } 158 } 159 160 // バッファを故障履歴エディットに表示するループ 161 for(WORD j=GA_startHistoryIdx; j<GA_endHistoryIdx; j++, m++) 162 { 163 // char型配列をAnsiString型に変換 164 caption = StrPas(&historyBuff[m][0]); 165 // 100件目の場合 166 if( j == (GA_endHistoryIdx-1) ) 167 { 168 // 故障履歴をダンプエリアに表示(改行しない) 169 _failureHistoryRichEdit->Lines->Text = _failureHistoryRichEdit->Lines->Text + caption; 170 } 171 // 1~99件目の場合 172 else 173 { 174 // 故障履歴をダンプエリアに表示 175 _failureHistoryRichEdit->Lines->Add(caption); 176 } 177 } 178 179 BYTE rows = 0; // 行数 180 // 状態(発生/回復)によって,文字列のフォント(赤/黒)を設定するループ 181 for(WORD n=GA_startHistoryIdx; n<GA_endHistoryIdx; n++, rows++) 182 { 183 // 文字列のフォントを変更する開始位置(テキスト全体における最初からの文字数,0から始まる) 184 _failureHistoryRichEdit->SelStart = (DISPLAY_MAX * rows); 185 // 文字列のフォントを変更する長さ 186 _failureHistoryRichEdit->SelLength = DISPLAY_MAX; 187 188 // 故障状態が異常の場合 189 if( GA_history.data[n].isTrodgState == ON ) 190 { 191 // 故障履歴の指定行のフォントを赤に設定 192 _failureHistoryRichEdit->SelAttributes->Color = clRed; 193 } 194 // 故障状態が正常の場合 195 else 196 { 197 // 故障履歴の指定行のフォントを黒に設定 198 _failureHistoryRichEdit->SelAttributes->Color = clBlack; 199 } 200 } 201}

###開発環境
OS:Windows10 64bit
IDE:embarcadero C++ Builder10.3

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

ベストアンサー

DISPLAY_MAX が実際の文字数を表していないように見えます。固定値を使うのではなく、実際追加された文字数がどうなっているのかを見て、DISPLAY_MAX の値と比べてみてください。

投稿2019/10/15 07:16

Zuishin

総合スコア27702

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

dem0nmichik0

2019/10/15 08:21

Zuishin様,回答ありがとうございます。 caption.Lengthで実際追加されていく文字数を確認したところ,どんな故障でも98. SelLengthが故障によって異なるのですが,同じ故障(伝送異常)でも65や56,47となります。 DISPLAY_MAXは100でRichEditのMAX_LENGTHプロパティが100のため,SelStartから100文字分追加するようにしています。間違っていますでしょうか?
Zuishin

2019/10/15 08:24

> _failureHistoryRichEdit->SelStart = (DISPLAY_MAX * rows); ここがまずい気がします。
dem0nmichik0

2019/10/15 10:00

Zuishin様,回答ありがとうございます。 > _failureHistoryRichEdit->SelStart = (DISPLAY_MAX * rows);のようにした理由は,1行が最大100文字なので,1行追加ごとに行頭を指定するようにするためです。 それとも,これではCRやLFなどの関係から行頭を指定できていないのでしょうか?
Zuishin

2019/10/15 10:01

デバッガで確かめてみてください。
dem0nmichik0

2019/10/18 03:08

Zuishin様,回答ありがとうございます。 デバッガやShowMessageなどを使い確認した結果,上手くいきました。 SelLengthには追加する文字列数分,SelStartには全体文字列から表示済みの文字列とCR分を除いた位置にした所,上手くいきました。 ありがとうございました

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C++Builder

C++Builderは、C/C++を用いてアプリ開発できる統合開発環境 (IDE) 。DelphiのC++版です。コンポーネントによるビジュアル開発、高機能なコードエディターなどで生産性の高い開発ができます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。