• 追加された行はこの色です。
  • 削除された行はこの色です。
#title(Visual Studio International Pack: Japanese Yomi Auto-Completion Libraryを使う)

#navi(.NETプログラミング研究)

#contents

*Visual Studio International Pack: Japanese Yomi Auto-Completion Libraryを使う [#d231fbd1]

Japanese Yomi Auto-Completion Libraryは、テキストボックス等で日本語IMEを使って文字入力するときにオートコンプリート機能を提供するライブラリです。日本語IMEで確定した文字列の読みを自動的に登録してくれるため、非常に簡単に使用できます。このライブラリを使用するには、日本語IMEがインストールされており、有効になっている必要があります。

**ダウンロードとインストール [#wd828c82]

Japanese Yomi Auto-Completion Libraryをインストールする手順は、[[第85号>../85]]で紹介した方法とほぼ同じです。インストールに使用するMSIファイルは、"JPNTextAlign.msi "です。

またプロジェクトの参照に「YomiAutoCompletion.dll」を追加する必要があることも[[第85号>../85]]と同じです。具体的な方法は、「[[「○○○.dllを参照に追加します」の意味は?>http://dobon.net/vb/dotnet/help/addreference.html]]」をご覧ください。なおこのDLLがある場所は、デフォルトでは、「C:\Program Files\Microsoft Visual Studio International Pack\Japanese Yomi Auto-Completion Library\Library」というフォルダです。
またプロジェクトの参照に「YomiAutoCompletion.dll」を追加する必要があることも[[第85号>../85]]と同じです。具体的な方法は、「[[「○○○.dllを参照に追加します」の意味は?>https://dobon.net/vb/dotnet/help/addreference.html]]」をご覧ください。なおこのDLLがある場所は、デフォルトでは、「C:\Program Files\Microsoft Visual Studio International Pack\Japanese Yomi Auto-Completion Library\Library」というフォルダです。

**YomiAutoCompletionListenerクラス [#ofcbe26d]

Japanese Yomi Auto-Completion Libraryの使い方は非常に簡単で、YomiAutoCompletionListenerクラスのコンストラクタのパラメータにオートコンプリート機能を付けたいテキストボックスを渡すだけです。

テキストボックス"TextBox1"にオートコンプリート機能を付ける例を以下に示します。

#code(vbnet){{
Private listener As Microsoft.International.Windows.YomiAutoCompletionListener

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load
    Me.listener = _
        New Microsoft.International.Windows.YomiAutoCompletionListener(Me.TextBox1)
End Sub
}}

#code(csharp){{
private Microsoft.International.Windows.YomiAutoCompletionListener listener;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    this.listener =
        new Microsoft.International.Windows.YomiAutoCompletionListener(this.TextBox1);
}
}}

例えば、このテキストボックスに日本語IMEを使って"青森"と入力したとします。テキストボックスに入力されている文字列をクリアした後、日本語IMEで"あ"と入力すると、その下に候補ウィンドウが表示され、その中に"青森"が表示されます。ここで十字キーの↓で"青森"を選択してEnterキーを押せば、"青森"と入力することが出来ます。

&ref(YomiAutoCompletion1.png);

このようにJapanese Yomi Auto-Completion Libraryは、日本語IMEで確定した文字列とその読みがなを自動的に登録してくれます。

読みがなの登録はテキストボックスの内容が空であってもそうでなくても行われますが、候補ウィンドウが表示されるのはテキストボックスが空のとき(未確定の文字列だけのとき)だけです。

***自動的に登録される読みがなはどのように決定されるか [#q2d66c50]

自動的に登録される読みがなは、ユーザーが実際にIMEで入力した文字列ではなく、確定した文字列の読みがなとして適当だとIMEが判断した文字列となるようです。具体的には、[[IFELanguage::GetJMorphResultメソッド>http://msdn.microsoft.com/en-us/library/ms970145.aspx#felang2fnc_getresult]]を使用しているのではないかと思われます。

***候補ウィンドウの実体 [#f9d60395]

候補ウィンドウの実体はCandidatesWindowクラスというものであり、このクラスはListBoxクラスから派生しています。候補ウィンドウは別ウィンドウになっておらず、フォーム内に表示されるListBoxなので、TextBoxの下に候補ウィンドウを表示するだけの十分なスペースがないと候補ウィンドウが全て表示されません。

**TextBoxクラスをオーバーライドして、オートコンプリート機能を持つテキストボックスを作る [#k00efb69]

TextBoxクラスをオーバーライドして、オートコンプリート機能を持つテキストボックスを作っておくと便利です。ちなみにヘルプでは、このような方法しか紹介されていません。

#code(vbnet){{
''' <summary> 
''' Japanese Yomi Auto-Completion Libraryを使って 
''' 日本語IMEでのオートコンプリート機能を可能にしたテキストボックス 
''' </summary> 
Public Class YomiAutoCompleteTextBox
    Inherits System.Windows.Forms.TextBox
    Private listener As Microsoft.International.Windows.YomiAutoCompletionListener
    ''' <summary> 
    ''' 使用しているYomiAutoCompletionListener 
    ''' </summary> 
    Public ReadOnly Property YomiAutoCompletionListener() As  _
        Microsoft.International.Windows.YomiAutoCompletionListener
        Get
            Return Me.listener
        End Get
    End Property

    Public Sub New()
        Me.listener = _
            New Microsoft.International.Windows.YomiAutoCompletionListener(Me)
    End Sub
End Class
}}

#code(csharp){{
/// <summary>
/// Japanese Yomi Auto-Completion Libraryを使って
/// 日本語IMEでのオートコンプリート機能を可能にしたテキストボックス
/// </summary>
public class YomiAutoCompleteTextBox : System.Windows.Forms.TextBox
{
    private Microsoft.International.Windows.YomiAutoCompletionListener listener;
    /// <summary>
    /// 使用しているYomiAutoCompletionListener
    /// </summary>
    public Microsoft.International.Windows.YomiAutoCompletionListener
        YomiAutoCompletionListener
    {
        get { return this.listener; }
    }

    public YomiAutoCompleteTextBox()
    {
        this.listener =
            new Microsoft.International.Windows.YomiAutoCompletionListener(this);
    }
}
}}

このクラスを使用する方法は、「[[「○○○クラスの代わりに派生クラスを使用します」の意味は?>http://dobon.net/vb/dotnet/help/derivedcontrol.html]]」を参考にしてください。
このクラスを使用する方法は、「[[「○○○クラスの代わりに派生クラスを使用します」の意味は?>https://dobon.net/vb/dotnet/help/derivedcontrol.html]]」を参考にしてください。

**登録された読みがなと候補を保存、復元する [#restoreyomi]

Japanese Yomi Auto-Completion Libraryで自動的に登録された読みがなと文字列は、アプリケーションが終了すれば忘れてしまいます。これをファイルに保存しておき、復元できるようにする方法を紹介します。

今まで登録されている読みがなのリストは、YomiAutoCompletionContextManagerクラスのSourceプロパティで取得できます(以下、Sourceプロパティで取得できるリストを「ソースリスト」と呼びます)。読みがなの登録は、YomiAutoCompletionContextManager.AddToSourceメソッドまたは、YomiStringCollection.Addメソッドでできます。

以下に、現在登録されているソースリストをファイルに保存、復元するメソッドと、これらを利用してアプリケーションを再起動しても同じソースリストが維持されるようにした例を示します。ちなみにソースリストはタブ区切りのリストで保存しています。

#code(vbnet){{
Private listener As Microsoft.International.Windows.YomiAutoCompletionListener
'オートコンプリートソースを保存するファイル 
Private yomiListFile As String = _
    System.IO.Path.Combine(Application.StartupPath, "yomi.tsv")


'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load
    Me.listener = _
        New Microsoft.International.Windows.YomiAutoCompletionListener(Me.TextBox1)

    'ソースリストを読み込む
    If System.IO.File.Exists(Me.yomiListFile) Then
        Me.LoadYomiSource(Me.yomiListFile, Me.listener)
    End If
End Sub

'フォームのFormClosedイベントハンドラ 
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs) _
        Handles MyBase.FormClosed
    'ソースリストを保存する
    Me.SaveYomiSource(Me.yomiListFile, Me.listener)
End Sub

''' <summary> 
''' YomiAutoCompletionListenerのオートコンプリートソースをファイルに保存する 
''' </summary> 
''' <param name="filePath">保存先のファイル</param> 
''' <param name="listen">保存するYomiAutoCompletionListener</param> 
Public Sub SaveYomiSource(ByVal filePath As String, _
        ByVal listen As Microsoft.International.Windows.YomiAutoCompletionListener)
    Using strm As New System.IO.StreamWriter(filePath)
        For Each strYomi As Microsoft.International.Windows.StringYomi _
                In listen.ContextManager.Source
            strm.WriteLine( _
                String.Format("{0}" & vbTab & "{1}", strYomi.Yomi, strYomi.Text))
        Next
    End Using
End Sub

''' <summary> 
''' YomiAutoCompletionListenerのオートコンプリートソースをファイルから復元する 
''' </summary> 
''' <param name="filePath">復元するファイル</param> 
''' <param name="listen">復元先のYomiAutoCompletionListener</param> 
Public Sub LoadYomiSource(ByVal filePath As String, _
        ByVal listen As Microsoft.International.Windows.YomiAutoCompletionListener)
    Using strm As New System.IO.StreamReader(filePath)
        listen.ContextManager.Source.Clear()
        Dim line As String = strm.ReadLine()
        While (line IsNot Nothing)
            Dim vals As String() = line.Split(New Char() {ControlChars.Tab}, 2)
            If vals.Length = 2 Then
                listen.ContextManager.Source.Add(vals(0), vals(1))
            End If
            line = strm.ReadLine()
        End While
    End Using
End Sub
}}

#code(csharp){{
private Microsoft.International.Windows.YomiAutoCompletionListener listener;
//ソースリストを保存するファイル
string yomiListFile =
    System.IO.Path.Combine(Application.StartupPath, "yomi.tsv");

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    this.listener =
        new Microsoft.International.Windows.YomiAutoCompletionListener(this.TextBox1);

    //ソースリストを読み込む
    if (System.IO.File.Exists(this.yomiListFile))
        this.LoadYomiSource(this.yomiListFile, this.listener);
}

//フォームのFormClosedイベントハンドラ
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    //ソースリストを保存する
    this.SaveYomiSource(this.yomiListFile, this.listener);
}

/// <summary>
/// YomiAutoCompletionListenerのソースリストをファイルに保存する
/// </summary>
/// <param name="filePath">保存先のファイル</param>
/// <param name="listen">保存するYomiAutoCompletionListener</param>
public void SaveYomiSource(
    string filePath,
    Microsoft.International.Windows.YomiAutoCompletionListener listen)
{
    using (System.IO.StreamWriter strm = new System.IO.StreamWriter(filePath))
    {
        foreach (Microsoft.International.Windows.StringYomi strYomi
            in listen.ContextManager.Source)
        {
            strm.WriteLine(string.Format("{0}\t{1}", strYomi.Yomi, strYomi.Text));
        }
    }
}

/// <summary>
/// YomiAutoCompletionListenerのソースリストをファイルから復元する
/// </summary>
/// <param name="filePath">復元するファイル</param>
/// <param name="listen">復元先のYomiAutoCompletionListener</param>
public void LoadYomiSource(
    string filePath,
    Microsoft.International.Windows.YomiAutoCompletionListener listen)
{
    using (System.IO.StreamReader strm = new System.IO.StreamReader(filePath))
    {
        listen.ContextManager.Source.Clear();
        string line;
        while ((line = strm.ReadLine()) != null)
        {
            string[] vals = line.Split(new char[] { '\t' }, 2);
            if (vals.Length == 2)
            {
                listen.ContextManager.Source.Add(vals[0], vals[1]);
            }
        }
    }
}
}}

**読みがなを独自に提供する [#ebe5af3e]

デフォルトではIMEで確定された文字列に対する読みがなが自動的に登録されますが、独自の読みがなを提供することも出来ます。それには、IYomiProviderインターフェイスを実装したクラスを作成する必要があります。

その方法は、ヘルプの「自分の辞書を利用する方法」にあります。ここではそこで紹介されているクラスをそのまま使用して、どのように動作するか見てみましょう。

ヘルプで紹介されているIYomiProviderインターフェイスを実装したクラスは次のようなものです((全く同じではありません。また、ヘルプにはC#のコードしかありません。))。"日本"という文字列の読みがなに"にほん"と"にっぽん"を、"日本人"という文字列の読みがなに"にほんじん"と"にっぽんじん"を登録するようにします。

#code(vbnet){{
Public Class MyYomiProvider
    Implements Microsoft.International.Windows.IYomiProvider

    Public Function GetYomi(ByVal text As String) As  _
            System.Collections.ObjectModel.ReadOnlyCollection(Of String) _
            Implements Microsoft.International.Windows.IYomiProvider.GetYomi
        Dim yomiCandidates As New List(Of String)()
        Select Case text
            Case "日本"
                yomiCandidates.Add("にほん")
                yomiCandidates.Add("にっぽん")
                Exit Select
            Case "日本人"
                yomiCandidates.Add("にほんじん")
                yomiCandidates.Add("にっぽんじん")
                Exit Select
            Case Else
                Exit Select
        End Select

        Return New System.Collections.ObjectModel.ReadOnlyCollection(Of String) _
            (yomiCandidates)
    End Function
End Class
}}

#code(csharp){{
public class MyYomiProvider :
    Microsoft.International.Windows.IYomiProvider
{
    public System.Collections.ObjectModel.ReadOnlyCollection<string> GetYomi(
        string text)
    {
        List<string> yomiCandidates = new List<string>();
        switch (text)
        {
            case "日本":
                yomiCandidates.Add("にほん");
                yomiCandidates.Add("にっぽん");
                break;
            case "日本人":
                yomiCandidates.Add("にほんじん");
                yomiCandidates.Add("にっぽんじん");
                break;
            default:
                break;
        }

        return new System.Collections.ObjectModel.ReadOnlyCollection<string>(
            yomiCandidates);
    }
}
}}

このクラスを利用するには、次のようにYomiAutoCompletionContextManager.YomiProviderプロパティを変更します。

#code(vbnet){{
Private listener As Microsoft.International.Windows.YomiAutoCompletionListener

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load
    Me.listener = _
        New Microsoft.International.Windows.YomiAutoCompletionListener(Me.TextBox1)

    'YomiProviderを変更する 
    Me.listener.ContextManager.YomiProvider = New MyYomiProvider()
End Sub
}}

#code(csharp){{
private Microsoft.International.Windows.YomiAutoCompletionListener listener;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    this.listener =
        new Microsoft.International.Windows.YomiAutoCompletionListener(this.TextBox1);

    //YomiProviderを変更する
    this.listener.ContextManager.YomiProvider = new MyYomiProvider();
}
}}

このようにして、TextBox1に日本語IMEで"に"と入力しても、候補ウィンドウは表示されません。TextBox1で一度IMEを使って"日本"あるいは"日本語"と確定した後に、TextBox1にIMEで"に"と入力すれば、候補ウィンドウが表示されます。例えば、TextBox1に"日本"と入力したならば、"にほん"と"にっぽん"の両方が候補として表示されるようになります。

なぜはじめから候補ウィンドウが表示されないのかというと、はじめの段階ではソースリストに読みがなが登録されておらず、"日本"あるいは"日本語"と確定した後でGetYomiメソッドが返す読みがながソースリストに追加されるからです。

よってこの例のように、提供される読みがなが少数であれば、わざわざIYomiProviderを実装したクラスを作るよりも、直接ソースリストに追加した方が簡単で便利です。IYomiProviderを実装した方法を使うのは、IFELanguage::GetJMorphResultとは違った方法で読みがなを取得したいときや、指定した読みがながソースリストに追加されないようにしたいときなどに限られそうです。

***ある文字列について、GetYomiメソッドが返す読みがなをソースリストに登録する [#n629d703]

ユーザーがIMEで確定するのではなく、プログラムによって、ある文字列についてIYomiProvider.GetYomiメソッドが返す読みがなをソースリストに登録するには、YomiAutoCompletionContextManager.AddToSourceメソッドを読みがなを指定しないで(nullか空の文字列を指定して)呼び出します。(YomiStringCollection.Addメソッドではできません。)

例えば上記の例において、"日本"の読みがなの"にほん"と"にっぽん"がソースリストに登録されるようにするには、次のようにします。

#code(vbnet){{
Me.listener = _
    New Microsoft.International.Windows.YomiAutoCompletionListener(Me.TextBox1)

'YomiProviderを変更する 
Me.listener.ContextManager.YomiProvider = New MyYomiProvider()

'"日本"の読みがなをソースリストに追加する 
Me.listener.ContextManager.AddToSource("日本", Nothing)
}}

#code(csharp){{
this.listener =
    new Microsoft.International.Windows.YomiAutoCompletionListener(this.TextBox1);
//YomiProviderを変更する
this.listener.ContextManager.YomiProvider = new MyYomiProvider();

//"日本"の読みがなをソースリストに追加する
this.listener.ContextManager.AddToSource("日本", null);
}}

**独自のソースリストだけを使い、入力された読みがなを登録しない [#ma9b5aca]

先に述べたように、IYomiProviderを実装するよりも、ソースリストに直接読みがなを追加した方が便利というケースも多いでしょう。もし独自に読みがなを追加したソースリストだけを使い、ユーザーが入力した読みがなをソースリストに追加しないのであれば、YomiAutoCompletionContextManager.YomiProviderプロパティにnullを設定できます。

「[[登録された読みがなと候補を保存、復元する>#restoreyomi]]」で紹介したLoadYomiSourceメソッドを使ってソースリストをファイルから読み込み、ユーザーが入力した読みがなを登録しないのならば、次のようにします。(「[[登録された読みがなと候補を保存、復元する>#restoreyomi]]」で示したコードのうち、変更するForm1_Loadメソッドの中身だけを示します。)

#code(vbnet){{
Me.listener = _
    New Microsoft.International.Windows.YomiAutoCompletionListener(Me.TextBox1)
'ユーザーが入力した読みがなを登録しない 
Me.listener.ContextManager.YomiProvider = Nothing

If System.IO.File.Exists(Me.yomiListFile) Then
    Me.LoadYomiSource(Me.yomiListFile, Me.listener)
End If
}}

#code(csharp){{
this.listener =
    new Microsoft.International.Windows.YomiAutoCompletionListener(this.TextBox1);
//ユーザーが入力した読みがなを登録しない
this.listener.ContextManager.YomiProvider = null;

if (System.IO.File.Exists(this.yomiListFile))
    this.LoadYomiSource(this.yomiListFile, this.listener);
}}

**複数のYomiAutoCompletionListenerのソースリストを共有する [#q8f16f3d]

複数のテキストボックスで同じYomiAutoCompletionListenerを共有することは出来ませんし、複数のテキストボックスで同じソースリストを共有することも出来ません。よって、複数のテキストボックスで同じオートコンプリートリストが表示されるようにするには、それぞれのソースリスト(YomiAutoCompletionContextManager.Source)を同期させる必要があります。

同期の方法やタイミングはいろいろ考えられますが、ここではIYomiProviderを実装したクラスで行う方法を考えてみます。ソースリストに新たな読みがなが追加されるとき、その前にIYomiProvider.GetYomiメソッドが呼び出され、GetYomiメソッドが返す読みがなをソースリストに追加しているようなので、GetYomiメソッドが呼び出されたときに、GetYomiメソッドが返す読みがなを他のソースリストにも登録して、同期するようにします。

具体的なサンプルは以下のようになります。

#code(vbnet){{
''' <summary> 
''' 複数のYomiAutoCompletionListenerでソースを共有するIYomiProvider 
''' </summary> 
Public Class SharedSourceYomiProvider
    Implements Microsoft.International.Windows.IYomiProvider

    '同期するすべてのソース 
    Private Shared sharedSources As New List( _
        Of Microsoft.International.Windows.YomiStringCollection)()

    'このYomiAutoCompletionListenerのソース 
    Private source As Microsoft.International.Windows.YomiStringCollection
    'このIYomiProviderの基になるIYomiProvider 
    Private yomiProvider As Microsoft.International.Windows.IYomiProvider

    ''' <summary> 
    ''' SharedSourceYomiProviderのコンストラクタ 
    ''' </summary> 
    ''' <param name="listen">使用しているYomiAutoCompletionListener</param> 
    Public Sub New( _
        ByVal listen As Microsoft.International.Windows.YomiAutoCompletionListener)

        Me.source = listen.ContextManager.Source
        Me.yomiProvider = listen.ContextManager.YomiProvider
        SharedSourceYomiProvider.sharedSources.Add(listen.ContextManager.Source)
    End Sub

    Public Function GetYomi(ByVal text As String) As  _
        System.Collections.ObjectModel.ReadOnlyCollection(Of String) _
        Implements Microsoft.International.Windows.IYomiProvider.GetYomi

        '基のIYomiProviderのGetYomiを呼び出す 
        Dim ret As System.Collections.ObjectModel.ReadOnlyCollection(Of String) = _
            Me.yomiProvider.GetYomi(text)

        'ソースを同期する 
        For Each src As Microsoft.International.Windows.YomiStringCollection _
                In SharedSourceYomiProvider.sharedSources
            If Me.source IsNot src Then
                For Each yomi As String In ret
                    src.Add(yomi, text)
                Next
            End If
        Next

        Return ret
    End Function
End Class
}}

#code(csharp){{
/// <summary>
/// 複数のYomiAutoCompletionListenerでソースを共有するIYomiProvider
/// </summary>
public class SharedSourceYomiProvider :
    Microsoft.International.Windows.IYomiProvider
{
    //同期するすべてのソース
    private static List<Microsoft.International.Windows.YomiStringCollection> sharedSources =
        new List<Microsoft.International.Windows.YomiStringCollection>();

    //このYomiAutoCompletionListenerのソース
    private Microsoft.International.Windows.YomiStringCollection source;
    //このIYomiProviderの基になるIYomiProvider
    private Microsoft.International.Windows.IYomiProvider yomiProvider;

    /// <summary>
    /// SharedSourceYomiProviderのコンストラクタ
    /// </summary>
    /// <param name="listen">使用しているYomiAutoCompletionListener</param>
    public SharedSourceYomiProvider(
        Microsoft.International.Windows.YomiAutoCompletionListener listen)
    {
        this.source = listen.ContextManager.Source;
        this.yomiProvider = listen.ContextManager.YomiProvider;
        SharedSourceYomiProvider.sharedSources.Add(listen.ContextManager.Source);
    }

    public System.Collections.ObjectModel.ReadOnlyCollection<string> GetYomi(
        string text)
    {
        //基のIYomiProviderのGetYomiを呼び出す
        System.Collections.ObjectModel.ReadOnlyCollection<string> ret =
            this.yomiProvider.GetYomi(text);

        //ソースを同期する
        foreach (Microsoft.International.Windows.YomiStringCollection src
            in SharedSourceYomiProvider.sharedSources)
        {
            if (this.source != src)
            {
                foreach (string yomi in ret)
                {
                    src.Add(yomi, text);
                }
            }
        }

        return ret;
    }
}
}}

例えばこのクラスを使って"TextBox1"と"TextBox2"の2つのテキストボックスでソースを共有するには、次のようにします。

#code(vbnet){{
Private listener As Microsoft.International.Windows.YomiAutoCompletionListener
Private listener2 As Microsoft.International.Windows.YomiAutoCompletionListener

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load
    Me.listener = _
        New Microsoft.International.Windows.YomiAutoCompletionListener(Me.TextBox1)
    'YomiProviderを変更する 
    Me.listener.ContextManager.YomiProvider = _
        New SharedSourceYomiProvider(Me.listener)

    Me.listener2 = _
        New Microsoft.International.Windows.YomiAutoCompletionListener(Me.TextBox2)
    'YomiProviderを変更する 
    Me.listener2.ContextManager.YomiProvider = _
        New SharedSourceYomiProvider(Me.listener2)
End Sub
}}

#code(csharp){{
private Microsoft.International.Windows.YomiAutoCompletionListener listener;
private Microsoft.International.Windows.YomiAutoCompletionListener listener2;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    this.listener =
        new Microsoft.International.Windows.YomiAutoCompletionListener(this.TextBox1);
    //YomiProviderを変更する
    this.listener.ContextManager.YomiProvider = new SharedSourceYomiProvider(this.listener);

    this.listener2 =
        new Microsoft.International.Windows.YomiAutoCompletionListener(this.TextBox2);
    //YomiProviderを変更する
    this.listener2.ContextManager.YomiProvider = new SharedSourceYomiProvider(this.listener2);
}
}}

**複数のソースリストを切り替えて使用する [#s2c12486]

状況によってソースリストを切り替え、候補として表示される読みがなを変えたいというケースもあるかもしれません。次にどのようにすれば複数のソースリストを切り替えて使用することができるかを考えてみます。

これには、ソースリストを切り替えるときに現在のYomiAutoCompletionContextManager.Sourceプロパティの内容を保存し、Sourceプロパティの内容をクリアし、切り替えるソースリストの内容をSourceプロパティに移すといった地味な方法しかなさそうです。

複数のソースリストをIDで切り替えられるようにしたYomiAutoCompletionListenerの派生クラスを作ってみましたので、以下にそのコードを紹介します。

#code(vbnet){{
''' <summary> 
''' 複数のソースリストを持つYomiAutoCompletionListener 
''' </summary> 
Public Class MultiSourceYomiListener
    Inherits Microsoft.International.Windows.YomiAutoCompletionListener
    Private _sources As New Dictionary( _
        Of String, Microsoft.International.Windows.YomiStringCollection)()

    Private _sourceId As String
    ''' <summary> 
    ''' ソースリストのID 
    ''' </summary> 
    Public Property SourceId() As String
        Get
            Return Me._sourceId
        End Get
        Set(ByVal value As String)
            If value.Equals(Me._sourceId) Then
                Return
            End If

            '現在のIDのソースリストを保存 
            If Not Me._sources.ContainsKey(Me._sourceId) Then
                '現在のIDのソースリストがなければ作る 
                Me._sources(Me._sourceId) = _
                    New Microsoft.International.Windows.YomiStringCollection()
            Else
                Me._sources(Me._sourceId).Clear()
            End If
            Me._sources(Me._sourceId).AddRange(Me.ContextManager.Source)

            'ソースリストをクリア 
            Me.ContextManager.Source.Clear()

            'ソースリストを復元 
            If Me._sources.ContainsKey(value) Then
                Me.ContextManager.Source.AddRange(Me._sources(value))
            End If

            'IDを変更 
            Me._sourceId = value
        End Set
    End Property

    ''' <summary> 
    ''' MultiSourceYomiListenerのコンストラクタ 
    ''' </summary> 
    ''' <param name="ctrl">バインド元のコントロール</param> 
    Public Sub New(ByVal ctrl As Control)
        MyBase.New(ctrl)
        Me._sourceId = ""
    End Sub
End Class
}}

#code(csharp){{
/// <summary>
/// 複数のソースリストを持つYomiAutoCompletionListener
/// </summary>
public class MultiSourceYomiListener :
    Microsoft.International.Windows.YomiAutoCompletionListener
{
    private Dictionary<string, Microsoft.International.Windows.YomiStringCollection>
        _sources =
        new Dictionary<string, Microsoft.International.Windows.YomiStringCollection>();

    private string _sourceId;
    /// <summary>
    /// ソースリストのID
    /// </summary>
    public string SourceId
    {
        get
        {
            return this._sourceId;
        }
        set
        {
            if (value.Equals(this._sourceId))
                return;

            //現在のIDのソースリストを保存
            if (!this._sources.ContainsKey(this._sourceId))
            {
                //現在のIDのソースリストがなければ作る
                this._sources[this._sourceId] =
                    new Microsoft.International.Windows.YomiStringCollection();
            }
            else
            {
                this._sources[this._sourceId].Clear();
            }
            this._sources[this._sourceId].AddRange(this.ContextManager.Source);

            //ソースリストをクリア
            this.ContextManager.Source.Clear();

            //ソースリストを復元
            if (this._sources.ContainsKey(value))
            {
                this.ContextManager.Source.AddRange(this._sources[value]);
            }

            //IDを変更
            this._sourceId = value;
        }
    }

    /// <summary>
    /// MultiSourceYomiListenerのコンストラクタ
    /// </summary>
    /// <param name="ctrl">バインド元のコントロール</param>
    public MultiSourceYomiListener(Control ctrl) : base(ctrl)
    {
        this._sourceId = "";
    }
}
}}

このクラスの使い方はYomiAutoCompletionListenerと同じで、次のようになります。ソースリストを切り替えるときは、SourceIdプロパティにIDを代入します。はじめのIDは空の文字列です。

#code(vbnet){{
Private listener As MultiSourceYomiListener

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load
    Me.listener = New MultiSourceYomiListener(Me.TextBox1)
End Sub
}}

#code(csharp){{
private MultiSourceYomiListener listener;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    this.listener = new MultiSourceYomiListener(this.TextBox1);
}
}}

**参考 [#nf9cd7a4]

-[[ディベロッパー製品開発統括部 Blog : 開発者共通の悩み?Yomi-Autocompletion の動作に関して>http://blogs.msdn.com/dd_jpn/archive/2008/03/19/8325563.aspx]]

**コメント [#b051b1d4]
- 大変貴重な情報ありがとうございます。 -- やまと &new{2015-04-03 (金) 13:16:47};

#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]] [[:Category/ASP.NET]],2008-12-17 (水) 01:17:29,DOBON!,2008-12-17 (水) 01:17:29,DOBON!)

[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]