質問者
richtextboxのfind関数の使用方法について

質問
-
Visual C++のプログラミングについて質問があります。
使ってるプロジェクトはVisuaC++ CLRのwindowsフォーム
アプリケーションで作ってます。
今、メモ帳などのテキストエディタを作っているのですが、
ある特定の文字だけを部分的に青文字にするにはどのように
書けばよいでしょうか?
最初はコントロールにtextBoxを使って
イベント関数をこのようにしてたのですが
private: System::Void--------------------
{
if(textBox1->Text =="japan")
textBox1->ForeColor = Color::Blue;
else
textBox1->ForeColor = Color::Black;
}
この場合ですと、"japan"とtextBox内に入力されれば
フォントが青色になるのですが例えば
"japanef aiueo"と入れると青色にはなりません。
例えば
"japanaiueo ef efefefadafffda"と入力されると
japanと綴られている所だけフォントを変えたいのですが、
どのように記述すればよいのでしょうか?
自分なりに考えると、TextBoxではなくRichTextBoxのfind関数を
使えばいいのではないかと思うのですが、どのように記述すれば
よいのか悩んでいます
もしお分かりいただける方がいれば教えてくださると幸いです。
すべての返信
-
hirohirothanks さん、こんにちは。
hirohirothanks さんからの引用 この場合ですと、"japan"とtextBox内に入力されればフォントが青色になるのですが例えば
"japanef aiueo"と入れると青色にはなりません。それは、
if(textBox1->Text =="japan") と、"japan" という文字列かどうか '決め打ち' になっているからでしょう。(部分的ではなく全体でしか判断していない)
自分なりに考えると、TextBoxではなくRichTextBoxのfind関数を使えばいいのではないかと思うのですが、どのように記述すればよいのか悩んでいます いいえ、Find メソッドは、そのために存在するメソッドではなりません。
ヒントのひとつとして。
TextBox は、ご存知のように Text プロパティが存在します。
Text プロパティは文字列型です。
System::String クラスには、IndexOf メソッドという、文字列を検索するメソッドが存在します。 -
じゃんぬねっとさん、貴重なアドバイスありがとうございます。
findメソッドはそういう使い方をするためのものじゃないのですね…
自分なりに考えてみたのですが…findメソッドですが…
private: System::Void button1_Click_1(System::Object^ sender, System::EventArgs^ e) {
//higeという文字を検索して赤文字にする
String^ SearchStr = "hige";
int FindPos;
FindPos = richTextBox1->Find(SearchStr);
do
{
richTextBox1->Select(FindPos, SearchStr->Length);
richTextBox1->SelectionColor = Color::Red;
} while (FindPos == -1);
}
このようにボタン1をクリックすればhigeは赤文字にはなるのですが、
疑問点が2つあります。
例えば"hige is hige "と打つと最初のhigeはボタンを押すと赤文字にはなりますが
isの後のhigeは赤文字にはなりません。すべてのhigeを赤文字にしたいのですが
どうのようにすればよいのでしょう
もう1つはボタンを押さずにデフォルトでhigeと入力されたら
赤文字になるようにするにはどうしたらいいでしょうか
ご教授お願いいたします。 -
TextBox の Text Property は String を返します。なので、String の中から文字列を探すのに String の method の1つである IndexOf が使えますよ…という話だったと思うのですが…閑話休題。
# フォントを変更したり、色を変更したりするのは Owner Draw を使うことになるのでしょうか。TextBox で試したことがないので、こちらは良く分からないです。
RichTextBox の Find なのですが、Find (String) の他に Find (String,Int32,RichTextBoxFinds) が存在します (まだ他にもありますが…)。2番目の引数が検索開始位置なので、FindPos に String の長さを加えた位置から続きの検索を行わせれば良いように思えます。(見付からなくなるまでループするのでしょうか)
ボタンを押さずにという部分は、例えば KeyPress のイベントによってトリガーがかかるようにする (その場合、カーソル周辺だけ探すようにした方が良いかもしれません)ないし、TextChanged でトリガーがかかるようにするなどで解決できそうです。
-
Takashi SAKAMOTOさんアドバイスありがとうございます
大変参考になりました。
自分なりにrichTextBoxのtextchangeのイベント関数に以下のように記述すると
仕様通り動かすことができました。
private: System::Void richTextBox1_TextChanged(System::Object^ sender, System::EventArgs^ e) {
String^ Searchtext="hige";
int Start;
Start = 0;
while(1){
Start = richTextBox1->Find(Searchtext,Start,RichTextBoxFinds::MatchCase);
if(Start > -1){
richTextBox1->Select(Start, Searchtext->Length);
richTextBox1->SelectionColor = Color::Red;
richTextBox1->Select(Start+1000,richTextBox1->Text->Length);
richTextBox1->SelectionColor = Color::Black;
}
else if (Start == -1)
break;
Start = Start+1;
}
}
しかし、この場合ですと、higeと打ち込んだあとにbackspaceでegを消していくと
hiは赤文字のままです。higeと打ち込んだあとそのスペルの一部分(eg)を削除すると
(hiが)黒文字にするようにするにはどうのように記述すればいいのでしょうか?
ご教授お願いいたします。 -
DeselectAll を呼び出すだけでは、まずかったようです。一度全部選択した状態にしてから SelectionColor を戻すことで解決できるようです。
TextChanged イベントは削除の場合にも来ているようでした。
例えば、次のようなコードは如何でしょうか?
String^ Searchtext="hige"; int Start; int iPos, iLen ; iPos = richTextBox1->SelectionStart ; iLen = richTextBox1->SelectionLength ; richTextBox1->SelectAll () ; richTextBox1->SelectionColor = Color::Black; richTextBox1->DeselectAll () ; Start = 0; while(1){ Start = richTextBox1->Find(Searchtext,Start,RichTextBoxFinds::MatchCase); if(Start > -1){ richTextBox1->Select(Start, Searchtext->Length); richTextBox1->SelectionColor = Color::Red; richTextBox1->Select(Start+1000,richTextBox1->Text->Length); richTextBox1->SelectionColor = Color::Black; } else if (Start == -1) break; Start = Start+1; } richTextBox1->SelectionStart = iPos ; richTextBox1->SelectionLength = iLen ; richTextBox1->SelectionColor = Color::Black;
最初と最後の Selection の設定を追加したのは、RichTextBox の Cursor も Selection で管理されているようですので、元に戻しておかないと非常にテキストの編集がし難くなりそうだったからです。
-
同じような問題にぶつかっていたのですが、こんなの(以下のソース)は、いかがでしょうか?C#なのでうまくC++に移植してください。
private void Form1_Load(object sender, EventArgs e)
{
richTextBox1.Text =
"<html><head><title>タイトル</title></head><body>タイトルの中身</body></html>";
}private void button2_Click(object sender, EventArgs e)
{
int x = 0;
do
{
try
{
x = richTextBox1.Find("タイトル", x+4, RichTextBoxFinds.MatchCase);
richTextBox1.SelectionColor = Color.Blue;
richTextBox1.DeselectAll();
}
catch (Exception ex)
{
richTextBox1.Text += ex.Message;
}
} while (!(x == -1));
}ボタン2をクリックすると”タイトル”という文字2か所だけが青く変わります。
-
C++でも以下にソースコードを書いてみました。良かったら参考にしてください。
#pragma once
namespace richtexboxfindcp {using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;/// <summary>
/// Form1 の概要
///
/// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた
/// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを
/// 変更する必要があります。この変更を行わないと、
/// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、
/// 正しく相互に利用できなくなります。
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: ここにコンストラクタ コードを追加します
//
}protected:
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::RichTextBox^ richTextBox1;
protected:
private: System::Windows::Forms::TextBox^ textBox1;
private: System::Windows::Forms::Button^ button1;private:
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
System::ComponentModel::Container ^components;#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void InitializeComponent(void)
{
this->richTextBox1 = (gcnew System::Windows::Forms::RichTextBox());
this->textBox1 = (gcnew System::Windows::Forms::TextBox());
this->button1 = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// richTextBox1
//
this->richTextBox1->Location = System::Drawing::Point(1, 3);
this->richTextBox1->Name = L"richTextBox1";
this->richTextBox1->Size = System::Drawing::Size(515, 257);
this->richTextBox1->TabIndex = 0;
this->richTextBox1->Text = L"";
//
// textBox1
//
this->textBox1->Location = System::Drawing::Point(522, 12);
this->textBox1->Name = L"textBox1";
this->textBox1->Size = System::Drawing::Size(100, 19);
this->textBox1->TabIndex = 1;
//
// button1
//
this->button1->Location = System::Drawing::Point(533, 62);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(75, 23);
this->button1->TabIndex = 2;
this->button1->Text = L"button1";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(632, 263);
this->Controls->Add(this->button1);
this->Controls->Add(this->textBox1);
this->Controls->Add(this->richTextBox1);
this->Name = L"Form1";
this->Text = L"Form1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
this->PerformLayout();}
#pragma endregion
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
richTextBox1->Text="<html><head><title>タイトル</title></head><body>タイトルの中身</body></html>";
textBox1->Text="タイトル";
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
int x=0;
do
{
x = richTextBox1->Find(textBox1->Text, x+textBox1->TextLength,RichTextBoxFinds::MatchCase);
richTextBox1->SelectionColor = Color::Blue;
} while (!(x == -1));
}
};
}