トップ回答者
textBoxに振り仮名を自動入力時に制限するキーを設定したいのですが

質問
-
下の青字のように制限するキーを設定しているのですが、このほかにも
Home、PageUp、PageDown、ScrollRock、PauseBreak
などを制限したくてずらずらと並べてはみたのですが、もっとスマートな方法がありはしないかと思ったりします。
これらのキーを押すと
タナカタナカタナカタナカタナカタナカタナカタナカタナカ
というように押した回数だけダブって表示されてしまいます。
(氏名を入力しているときにまさかこのようなキーを押す人はいないと思うのですが、念のために)
このことについてアドバイスをいただけないでしょうか。
「振り仮名自動入力」のクラスを作れたらなぁと夢見ているのですが、相当に難しいのでしょうね。
何を勉強したらいいでしょうか。
Code Snippetusing System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;namespace tbxKatakana
{
public partial class frmtbxKatakana : Form
{
public string Furigana = "";
const int GCS_RESURTREADSTR = 0x0200;[DllImport("imm32.dll")]
static extern IntPtr ImmGetContext(IntPtr hWnd);
[DllImport("imm32.dll")]
static extern int ImmGetCompositionString(
IntPtr hiMC, int dwIndex, StringBuilder lpBuf, int dwBufLen);
[DllImport("imm32.dll")]
static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hiMC);public frmtbxKatakana()
{
InitializeComponent();
}private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text == "")
{
textBox2.Text = "";
Furigana = "";
}
}private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
string tmpStr;IntPtr himc = ImmGetContext(textBox1.Handle);
if (himc == IntPtr.Zero || e.KeyCode == Keys.Return
|| e.KeyCode == Keys.Back || e.KeyCode == Keys.Left
|| e.KeyCode == Keys.Right || e.KeyCode == Keys.Up
|| e.KeyCode == Keys.Down || e.KeyCode == Keys.Delete
|| e.KeyCode == Keys .Shift || e.KeyCode == Keys .Control
|| e.KeyCode == Keys .Insert || e.KeyCode == Keys .End )
{
return;
}
try
{
int dwSize = ImmGetCompositionString(himc, GCS_RESURTREADSTR, null, 0);
StringBuilder lpBuf = new StringBuilder(dwSize);ImmGetCompositionString(himc, GCS_RESURTREADSTR, lpBuf, dwSize);
lpBuf.Length = dwSize;
tmpStr = lpBuf.ToString();
Furigana += tmpStr;
textBox2.Text = Furigana;
}
finally
{
ImmReleaseContext(textBox1.Handle, himc);
}
}
}
}
回答
-
いよいよ、ウィンドウメッセージです。
詳しくはやっぱりご自身で調べていただくとして、
私なりに大雑把に説明しますと、
TextBoxにキー入力された場合、キー入力されたよ、というメッセージがTextBoxに飛んできます。
TextBoxはそのメッセージに従って、一仕事します。
一仕事とは、文字を表示する、などのことです。
クリックされた場合も、クリックされたよ、というメッセージが飛んできます。
全ての場合についてメッセージが飛んできます。
その、飛んでくる全てのメッセージを処理できるプロシージャがWndProcです。
キー入力されたよ、というメッセージは0x102(WM_CHAR)と決められています。
そこで、そのメッセージが来た時に処理をしてあげればよいことになります。
厳密にはWM_CHARはTextChangedと同等ではありません。ペーストされた場合などに対応しません。
WndProcは万能ですが、積極的に使うものではありません。
今回のフリガナの時のように、変換確定イベントが標準では用意されていない場合などに、
しょうがなく、WndProcで処理します。あまり、わかりやすいコードになりませんからね。
Code Snippetclass MyTextBox:TextBox
{
//プライベートなメンバ
private string findstring;private const int WM_CHAR = 0x102;
//プロパティとして公開
public string FindString
{
get
{
return findstring;
}
set
{
findstring = value;
}}
//イベント
public delegate void FindEventHandler(object sender, FindStringEventArgs e);
public event FindEventHandler FindStringEvent;
protected override void OnTextChanged(EventArgs e)
{
//if (this.findstring != "")
//{
// int pos=this.Text.IndexOf(this.findstring);
// if (pos >= 0)
// {
// this.BackColor = System.Drawing.Color.Red;
// FindStringEventArgs fsea=new FindStringEventArgs();
// fsea.FindPosition=pos;
// FindStringEvent(this,fsea);// }
// else
// {
// this.BackColor = System.Drawing.Color.White;// }
//}
//else
//{
// this.BackColor = System.Drawing.Color.White;
//}base.OnTextChanged(e);
}protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_CHAR)
{
if (this.findstring != "")
{
int pos = (this.Text ).IndexOf(this.findstring);
if (pos >= 0)
{
this.BackColor = System.Drawing.Color.Red;
FindStringEventArgs fsea = new FindStringEventArgs();
fsea.FindPosition = pos;
FindStringEvent(this, fsea);}
else
{
this.BackColor = System.Drawing.Color.White;}
}
else
{
this.BackColor = System.Drawing.Color.White;
}
}
}
}実行して処理を確認します。
これで、一通りの説明は終わりです。
フリガナコードをものにしてください。
では、頑張ってください。
すべての返信
-
外池と申します。
「振り仮名」と仰っているので、入力できる文字を仮名文字だけに制限することか・・・、と思ったのですが、違うようですね。
カーソルやフォーカスの制御を制限したい、というようにお見受けします。
問題点の整理のためにお尋ねしますが、
とりあえず、振り仮名のことは忘れて回答してもよいのでしょうか?
(私としては、これは比較的簡単だと思うので、回答しやすいのですが。)
カーソルやフォーカスの制御をどのように制限したいのでしょうか?
(私としては、Windowsの標準のインターフェイスを制限することは避けるべきという意見なので
何もしないほうが良いと思うんですが・・・)
-
外池 さんからの引用 とりあえず、振り仮名のことは忘れて回答してもよいのでしょうか?
はい、そういうことでお願いします。
外池 さんからの引用 カーソルやフォーカスの制御をどのように制限したいのでしょうか?
(私としては、Windowsの標準のインターフェイスを制限することは避けるべきという意見なので
何もしないほうが良いと思うんですが・・・)
Windowsの標準のインターフェイスを制限したいということではなく、BackSpaceとかDelete外のキーの働きはそのままに残っています。しかし、これらのキーを押したときに振り仮名を表示する動作をさせないということなのです。よろしくお願いします。
-
はなはなさん、ありがとうございます。
@ITでの質問は確か3・4年前の質問でして、DataGridのセルに振り仮名を自動入力するものでした。
前回の質問はこれをdataGridViewに適用しようと意図したものでしたが、handcraftさんのご指導のお陰でうまく動いてくれています。
今回の質問はdataGridでもdataGridViewでもなくtextBoxへの振り仮名自動入力の際のキー制限に関することです。
「振り仮名自動入力クラス」を作ることは、ボケの入っている65歳の私には非常にむずかしいことだとは承知しています。いますぐに作りたいというのではなく遠い将来の目標(まぁ、生きているうちに)なのです。これについては参考本などをご紹介いただけたらと思っています。
tbx1[善浪| ] → tbx2[ゼンナミ ]
ここで、BackSpaceキーを押すと
tbx1[善| ] → tbx2[ゼンナミゼンナミ ]
となっていまいます。Space・矢印キー等の押下でも同じ現象となります。
そこで、
if (himc == IntPtr.Zero || e.KeyCode == Keys.Back)
としたら、
tbx1[善| ] → tbx2[ゼンナミ ]
となって、tbx2[ゼンナミゼンナミ ]とはならないことがわかったものですから、同様の振る舞いをする他のキーもということで、
if (himc == IntPtr.Zero || e.KeyCode == Keys.Return
|| e.KeyCode == Keys.Back || e.KeyCode == Keys.Left
|| e.KeyCode == Keys.Right || e.KeyCode == Keys.Up
|| e.KeyCode == Keys.Down || e.KeyCode == Keys.Delete
|| e.KeyCode == Keys .Shift || e.KeyCode == Keys .Control
|| e.KeyCode == Keys .Insert || e.KeyCode == Keys .End )としみました。
これで私の思い通りの動きにはなったのですが、振り仮名表示を規制するキーを羅列するのも芸がないなぁと思ったのです。
それでもっとスッキリとスマートに(或は別の方法で)コードを記述する方法があるなら、その方法を知りたいのです。
よろしくお願いします。
-
外池さん、はなはなさん、ありがとうございます。
はなはな さんからの引用 解釈が違っていたら、ごめんなさい。
私が言いたかったのは、KeyDownで処理せずにWndProcで処理すれば、キーを羅列せずに済み、
すっきりしますよ、ということだったのです。
ただ、DataGridViewの中のTextBoxについてならば、ちょっとやることが増えるから、お勧めできないかなぁ、
と思った次第です。
普通のTextBoxとして、教えましょうか?
継承から勉強しないといけませんが。
教えていただけるのでしたら是非にもお願いします。
「WndProcで処理すれば、キーを羅列せずに済み、すっきりしますよ」ということですが、上に示したAPIの部分は何とかDataGridで振り仮名を表示したい一心で考えたものでした。今となっては呆けのせいで解読も覚束ないし、<継承>についても人のコードを見ているとなるほどなぁとは思っても自分で1から書くとなると全く心もとないのですがよろしくお願いします。
-
zen73 さんからの引用 それでもっとスッキリとスマートに(或は別の方法で)コードを記述する方法があるなら、その方法を知りたいのです。
昔、諸農さんのコードを元に私が作ったコードが以下にありますので、参考になるかもしれません。振り仮名をイベントで提供するカスタムコントロールを作成しています。
テキストボックスで漢字名を入力した際にルビを振る方法について
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=456214&SiteID=7 -
ではでは、私の思うままに、説明します。間違った場合はご指摘を。>ALL
まず、とにかく継承してみる!
1.プロジェクトを作成し、プロジェクトの名前をMyFuriganaとします。
2.メニューの「プロジェクト」から「クラスの追加」を選択し、クラスの名前をMyTextBoxとします。
ここまでの作業でMyTextBoxの中身は次のようになっています。
Code Snippetusing System;
using System.Collections.Generic;
using System.Text;
namespace MyFurigana
{
class MyTextBox{
}
}3.クラスMyTextBoxがTextBoxを継承するように指定します。
赤字の部分を追加します。
Code Snippetusing System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;namespace MyFurigana
{
class MyTextBox:TextBox{
}
}4.メニューから「ビルド」→「MyFuriganaのビルド」を選択し、一回ビルドします。
5.Form1.cs[デザイン]の画面を開きます。ツールボックスのMyFuriganaコンポーネントからMyTextBoxをフォームに貼り付けます。
6.実行して、普通のTextBoxとして動作することを確認します。
さて、まずはここまで。
-
zen73 さんからの引用
trapemiyaさんがお示しくださったクラスの使用法を考えていたのですが結局はわからず、使えないままでいます。新規プロジェクトからWindowsフォームコントロールライブラリを選択して新しくプロジェクトを作ります。これはユーザーコントロール用のテンプレートなので、このままでは使えません。なぜかVS2008にはWindowsコントロールライブラリというテンプレートがありません。
私が以前示したコードはパーシャルなクラスではないので、以下のように修正して下さい。クラス名とか名前空間とかファイル名はは適当に変えてもらってかまいません。FuriganaTextBox2.cs
Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsControlLibrary1
{
public partial class FuriganaTextBox2 : System.Windows.Forms.TextBox
{
public FuriganaTextBox2()
{
InitializeComponent();
}const int WM_IME_COMPOSITION = 0x010F;
const int GCS_RESULTREADSTR = 0x0200;[DllImport("Imm32.dll", CharSet = CharSet.Auto)]
public static extern int ImmGetContext(IntPtr hWnd);[DllImport("Imm32.dll")]
public static extern int ImmGetCompositionString(
int hIMC,
int dwIndex,
IntPtr lpBuf,
int dwBufLen
);
[DllImport("Imm32.dll", CharSet = CharSet.Auto)]
public static extern bool ImmReleaseContext(IntPtr hWnd,int hIMC);[Serializable]
public class CompositionEventArgs:EventArgs
{
public string ImeStr;
}#region デリゲート & イベントの定義
//デリゲート & イベントの定義
public delegate void CompositionEventHandler(object sender,CompositionEventArgs e);
public event CompositionEventHandler CompositionEvent;
#endregionprotected override void OnPaint(PaintEventArgs pe)
{
// TODO: カスタム描画コードをここに追加してください。// OnPaint で基本クラスを呼び出し中
base.OnPaint(pe);
}#region WndProc
protected override void WndProc(ref Message m)
{
if (CompositionEvent != null && m.Msg == WM_IME_COMPOSITION)
{
if (((int)m.LParam & GCS_RESULTREADSTR)>0)
{
IntPtr buffer = IntPtr.Zero;try
{
int Imc = ImmGetContext(this.Handle);
int bytes = ImmGetCompositionString(Imc, GCS_RESULTREADSTR, IntPtr.Zero, 0);buffer = Marshal.AllocHGlobal(bytes);
ImmGetCompositionString(Imc, GCS_RESULTREADSTR, buffer, bytes);
byte[] arrByte = new Byte[bytes];
Marshal.Copy(buffer, arrByte, 0, bytes);
string str = Encoding.GetEncoding(932).GetString(arrByte);ImmReleaseContext(this.Handle,Imc);
CompositionEventArgs args = new CompositionEventArgs();
args.ImeStr = str;CompositionEvent(this,args);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
}
base.WndProc(ref m);
}
#endregion}
}FuriganaTextBox2.Designer.cs
Code Snippetnamespace WindowsFormsControlLibrary1
{
partial class FuriganaTextBox2
{
///
/// 必要なデザイナ変数です。
///
private System.ComponentModel.IContainer components = null;///
/// 使用中のリソースをすべてクリーンアップします。
///
/// マネージ リソースが破棄される場合 true、破棄されない場合は false です。
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}#region コンポーネント デザイナで生成されたコード
///
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
///
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}#endregion
}
}これでコンパイルできることを確認して下さい。
次にこの振り仮名テキストボックスを使うプロジェクトを開きます。
参照設定で上の振り仮名テキストボックスのプロジェクトを追加します。
ソリューションから上の振り仮名テキストボックスのプロジェクトを追加します(これは必須ではないですが、こうしとくと振り仮名テキストボックスのデバッグができます)。そうするとツールボックスにFuriganaTextBox2が追加されますので、それをフォームにドラッグします。あとはその振り仮名テキストボックスのCompositonEventイベントで、例えばtextBox1.Text = e.ImeStr; とすれば、textBox1に振り仮名が自動的に入ります。
-
はなはなはなさんとtrapemiyaさんのお二人には、今回はもとより以前からとてもお世話になりいろんなことを懇切丁寧に教えていただいておりますことに感謝申し上げます。
はなはなはな さんからの引用 あんな感じでいいなら、続けましょうか?
とりあえず、先の説明はご理解していただけたでしょうか?
はい、確認できました。
「Form1.cs[デザイン]の画面を開きます。ツールボックスのMyFuriganaコンポーネントからMyTextBoxをフォームに貼り付けます。」ってことは、初めての経験でちょっとおどろきでした。
はなはなはなさんには貴重なお時間を割かれてお教えくださっていることを思うと恐縮ですが、よろしくお願いします。
trapemiya さんからの引用 あとはその振り仮名テキストボックスのCompositonEventイベントで、例えばtextBox1.Text = e.ImeStr; とすれば、textBox1に振り仮名が自動的に入ります。
ありがとうございます。早速にも試してみます。
-
私は好きでやってますので。タブン、質問に答えるのも、人に教えるのも、好きなんでしょう。ww
とにかく、拡張してみる!
前回で、TextBoxを継承したMyTextBoxは作成できました。
しかし、これをこのまま使っては、普通のTextBoxとまったく同じで面白くありません。
なので、機能をかくちょうしましょう♪
フリガナ機能は、テーマとして重いので、ここでは、ある特定の文字が入力されたら
背景色を変える、というのをして見ます。
MyTextBox.csの中身に以下のコードを付け足してください。
Code Snippetnamespace MyFurigana
{
class MyTextBox:TextBox{
protected override void OnTextChanged(EventArgs e)
{
if (this.Text.IndexOf("ぜん") >= 0)
{
this.BackColor = System.Drawing.Color.Red;
}
else
{
this.BackColor = System.Drawing.Color.White;}
base.OnTextChanged(e);
}
}
}実行してみて、いろんな文字を入力してみましょう。
”ぜん”という文字が入力されると、背景色が赤になるはずです。
でも、継承なんかしなくてもできるよ、と思われるかもしれません。
ただ、この仕様のTextBoxが100個いると言われたとしたら、
あとあと、同じ仕様のTextBoxを別のプロジェクトで使うとしたら、
継承して作っておいたほうがらくちんです。
-
いや、実は、こんな話して喜んでくれるかどうかは?なので、私も二の足を踏むところがありますが、
@ITで、話があそこで切れていた点、zen73さんが夢だと言われた点、
これまでの投稿から、内容をひとつひとつ理解されたいのかなぁ、と予想して、やってます。
で、とりあえず、続きを。
独自のプロパティをつくってみる!
前回作ったMyTextBoxは、"ぜん"という固定した文字を検索しました。
これでは、応用が利かないので、指定できるようにします。
Code Snippetclass MyTextBox:TextBox
{
//プライベートなメンバ
private string findstring;//プロパティとして公開
public string FindString
{
get
{
return findstring;
}
set
{
findstring = value;
}}
protected override void OnTextChanged(EventArgs e)
{
if (this.findstring != "")
{
if (this.Text.IndexOf(this.findstring) >= 0)
{
this.BackColor = System.Drawing.Color.Red;
}
else
{
this.BackColor = System.Drawing.Color.White;}
}
else
{
this.BackColor = System.Drawing.Color.White;
}base.OnTextChanged(e);
}
}一度、ビルドしてから、Formのほうに以下のコードを加えます。
Code Snippetpublic partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}private void Form1_Load(object sender, EventArgs e)
{
this.myTextBox1.FindString = "はな";}
}これで、指定できるようになりました。
実行して、"はな"という文字が入力されたら赤色になることを確認します。
-
あと、イベントと、ウィンドウメッセージを習得すれば、trapemiyaさんのコードが読めるはずです。
ということで今回はイベント!
前回の話で、色もプロパティにしたくなりますが、それはお任せします。
フォームに指定の文字列が見つかったよ、というのを通知してあげましょう。
まずはdelegateを定義します。ここではFindEventHandlerと名づけます。(Foundのほうがいいかな?)
引数にobjectとFindStringEventArgsを指定します。
FindStringEventArgsは上にある、独自クラスです。普通のEventArgsでもよいですが、
ついでに次のテーマに取り上げる予定ですので、独自クラスを定義しておきます。
なお、クラスは一つのファイルに一つのほうがいいかもしれません。
ここでは、めんどくさい、という理由だけで同じファイルに書いています。
次にdelegateに基づいたeventを定義します。
そこまで済んだら、あとはイベントを起こしたいところでFindStringEventを呼び出すだけです。
Code Snippetnamespace MyFurigana
{
class FindStringEventArgs : EventArgs
{
}
class MyTextBox:TextBox{
//プライベートなメンバ
private string findstring;//プロパティとして公開
public string FindString
{
get
{
return findstring;
}
set
{
findstring = value;
}}
//イベント
public delegate void FindEventHandler(object sender, FindStringEventArgs e);
public event FindEventHandler FindStringEvent;
protected override void OnTextChanged(EventArgs e)
{
if (this.findstring != "")
{
if (this.Text.IndexOf(this.findstring) >= 0)
{
this.BackColor = System.Drawing.Color.Red;
FindStringEvent(this,new FindStringEventArgs());}
else
{
this.BackColor = System.Drawing.Color.White;}
}
else
{
this.BackColor = System.Drawing.Color.White;
}base.OnTextChanged(e);
}
}
}ここまで書いたら、いつものごとく、ビルドしましょう。
フォームにリストボックスを一つ貼り付けます。メッセージ表示用です。
サンプルとしてださい気がしますが、目をつむってください。w
また、myTextBox1をデザイナで選択し、プロパティシートのイベント表示(カミナリマークのボタン)をして
FindStringEventを選択して、以下のコードを記述します。
Code Snippetpublic partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}private void Form1_Load(object sender, EventArgs e)
{
this.myTextBox1.FindString = "はな";}
private void myTextBox1_FindStringEvent(object sender, FindStringEventArgs e)
{
this.listBox1.Items.Add("文字列が見つかりました。");
}
} -
ご自分で勉強されたとはすばらしい。(^^)
わたしが詳しく説明しなかったのは、単に詳しく説明するほど理解していないからです。w
今度、私がデリゲートで質問したら、答えてくださいね。ww
さて今回は、
イベント通知時に情報を渡す!
です。
言ってませんでしたが、使っているサンプルは文字列が何個もあるばあいとかは考えてません。
あしからず。
FindStringEventArgsにプロパティを設定します。
見つかった文字列が何文字目かの情報を設定してからイベントを起こします。
Code Snippetnamespace MyFurigana
{
class FindStringEventArgs : EventArgs
{
private int findposition;public int FindPosition
{
get
{
return findposition;
}
set
{
findposition = value;
}
}
}
class MyTextBox:TextBox{
//プライベートなメンバ
private string findstring;//プロパティとして公開
public string FindString
{
get
{
return findstring;
}
set
{
findstring = value;
}}
//イベント
public delegate void FindEventHandler(object sender, FindStringEventArgs e);
public event FindEventHandler FindStringEvent;
protected override void OnTextChanged(EventArgs e)
{
if (this.findstring != "")
{
int pos=this.Text.IndexOf(this.findstring);
if (pos >= 0)
{
this.BackColor = System.Drawing.Color.Red;
FindStringEventArgs fsea=new FindStringEventArgs();
fsea.FindPosition=pos;
FindStringEvent(this,fsea);}
else
{
this.BackColor = System.Drawing.Color.White;}
}
else
{
this.BackColor = System.Drawing.Color.White;
}base.OnTextChanged(e);
}
}
}ここでいつものごとくビルドします。
フォーム側を以下のように変更します。
Code Snippetprivate void myTextBox1_FindStringEvent(object sender, FindStringEventArgs e)
{
this.listBox1.Items.Add(e.FindPosition.ToString() + "文字目に文字列が見つかりました。");
} -
はなはなはなさん、おはようございます。
確認できました。(文字列が何個もある場合も)
はなはなはな さんからの引用 ご自分で勉強されたとはすばらしい。(^^)
わたしが詳しく説明しなかったのは、単に詳しく説明するほど理解していないからです。w
今度、私がデリゲートで質問したら、答えてくださいね。ww
正直に申しましょう。10年ほど前にに読んだことのある日経BP社「プログラミングC#]という本を本棚から引っ張り出し”デリゲートとイベントハンドラ”という章を開いたところ、当然でしょうけれど<理解不能>というタッグシールがはられているではありませんか。それでも相当量の書き込みがありますから何とか理解しようとしたのでしょう。10才も若い時に理解できなかったのですから今となっては自分の書いた書き込みさえ理解できない情けなさが残るのみでした。
-
いよいよ、ウィンドウメッセージです。
詳しくはやっぱりご自身で調べていただくとして、
私なりに大雑把に説明しますと、
TextBoxにキー入力された場合、キー入力されたよ、というメッセージがTextBoxに飛んできます。
TextBoxはそのメッセージに従って、一仕事します。
一仕事とは、文字を表示する、などのことです。
クリックされた場合も、クリックされたよ、というメッセージが飛んできます。
全ての場合についてメッセージが飛んできます。
その、飛んでくる全てのメッセージを処理できるプロシージャがWndProcです。
キー入力されたよ、というメッセージは0x102(WM_CHAR)と決められています。
そこで、そのメッセージが来た時に処理をしてあげればよいことになります。
厳密にはWM_CHARはTextChangedと同等ではありません。ペーストされた場合などに対応しません。
WndProcは万能ですが、積極的に使うものではありません。
今回のフリガナの時のように、変換確定イベントが標準では用意されていない場合などに、
しょうがなく、WndProcで処理します。あまり、わかりやすいコードになりませんからね。
Code Snippetclass MyTextBox:TextBox
{
//プライベートなメンバ
private string findstring;private const int WM_CHAR = 0x102;
//プロパティとして公開
public string FindString
{
get
{
return findstring;
}
set
{
findstring = value;
}}
//イベント
public delegate void FindEventHandler(object sender, FindStringEventArgs e);
public event FindEventHandler FindStringEvent;
protected override void OnTextChanged(EventArgs e)
{
//if (this.findstring != "")
//{
// int pos=this.Text.IndexOf(this.findstring);
// if (pos >= 0)
// {
// this.BackColor = System.Drawing.Color.Red;
// FindStringEventArgs fsea=new FindStringEventArgs();
// fsea.FindPosition=pos;
// FindStringEvent(this,fsea);// }
// else
// {
// this.BackColor = System.Drawing.Color.White;// }
//}
//else
//{
// this.BackColor = System.Drawing.Color.White;
//}base.OnTextChanged(e);
}protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_CHAR)
{
if (this.findstring != "")
{
int pos = (this.Text ).IndexOf(this.findstring);
if (pos >= 0)
{
this.BackColor = System.Drawing.Color.Red;
FindStringEventArgs fsea = new FindStringEventArgs();
fsea.FindPosition = pos;
FindStringEvent(this, fsea);}
else
{
this.BackColor = System.Drawing.Color.White;}
}
else
{
this.BackColor = System.Drawing.Color.White;
}
}
}
}実行して処理を確認します。
これで、一通りの説明は終わりです。
フリガナコードをものにしてください。
では、頑張ってください。