none
richtextboxのfind関数の使用方法について RRS feed

  • 質問

  • 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関数を
    使えばいいのではないかと思うのですが、どのように記述すれば
    よいのか悩んでいます

    もしお分かりいただける方がいれば教えてくださると幸いです。
    2006年11月25日 12:56

すべての返信

  • hirohirothanks さん、こんにちは。

     hirohirothanks さんからの引用
    この場合ですと、"japan"とtextBox内に入力されればフォントが青色になるのですが例えば
    "japanef aiueo"と入れると青色にはなりません。

    それは、

    if(textBox1->Text =="japan")

    と、"japan" という文字列かどうか '決め打ち' になっているからでしょう。(部分的ではなく全体でしか判断していない)

    自分なりに考えると、TextBoxではなくRichTextBoxのfind関数を使えばいいのではないかと思うのですが、どのように記述すればよいのか悩んでいます

    いいえ、Find メソッドは、そのために存在するメソッドではなりません。

    ヒントのひとつとして。

    TextBox は、ご存知のように Text プロパティが存在します。
    Text プロパティは文字列型です。
    System::String クラスには、IndexOf メソッドという、文字列を検索するメソッドが存在します。

    2006年11月25日 16:04
  • じゃんぬねっとさん、貴重なアドバイスありがとうございます。
    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と入力されたら
    赤文字になるようにするにはどうしたらいいでしょうか

    ご教授お願いいたします。
    2006年11月27日 7:39
  • 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 でトリガーがかかるようにするなどで解決できそうです。

     

    2006年11月27日 9:32
  • 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が)黒文字にするようにするにはどうのように記述すればいいのでしょうか?

    ご教授お願いいたします。
    2006年11月28日 7:50
  • 検索をかける前に DeselectAll method を呼び出して Selection を全部消去してしまうというのは如何でしょうか?

    ただ…テキストが少し編集される度に全 search がかかるというのは、テキスト量が増大すると厳しくなってくるかもしれません…。

     

    2006年11月28日 10:33
  • Takashi SAKAMOTOさんアドバイスありがとうございます。
    richTextBoxに選択解除のメソッドがあるとは知りませんでした。

    参考にさせてもらいます。

    やはりrichTextboxのイベントであるTextchangedは入力は認識するが
    文字が削除された場合については認識されないらしいですね;

    文字が削除されたことを認識するメソッドが別にあるといいのですが…
    2006年11月29日 6:14
  • 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 で管理されているようですので、元に戻しておかないと非常にテキストの編集がし難くなりそうだったからです。

     

    2006年11月29日 8:35
  • 私自身デバッガを使って、プログラムを追ってみると
    確かにTextChangedイベントは削除しても起こっていますね
    失礼致しました。

    ところで
    私が書いたコードはhigeを入力したあと、更にテキスト入力を続けると
    選択箇所がちらつくという不具合が生じるみたいです
    この原因が何なのかがいまいち分からないのが難点です…



    2006年11月29日 11:28
  •  

    選択箇所がちらつくという不具合が生じるみたいです
    この原因が何なのかがいまいち分からないのが難点です…

    これは TextBox で領域選択すると選択された箇所のテキストの色が反転するのですが、同じことが richTextBox1->Select の呼び出しで起きてしまっているのです。

    ですから、Select した段階でテキストの反転、SelectionColor を変更してテキスト反転の解除と細かな画面の書き直しが発生しているようです。

    具体的な解決方法は…思いつかないです…。

     

    2006年12月1日 1:59
  • 同じような問題にぶつかっていたのですが、こんなの(以下のソース)は、いかがでしょうか?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か所だけが青く変わります。

    2011年1月9日 2:01
  • 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));
        }
     };
    }

    2011年1月9日 2:58