Silverlight 4的OOB+Elevated Trust模式,可以讓我們直接呼叫COM物件,這讓我有了把TSF Helper搬到Silverlight 4
上執行的想法,首先把TSF Helper改寫回COM物件,並註冊到電腦中,這並不難。
TSF Ime Helper 與 Silverlight
文/黃忠成
關於TSF Ime Helper
   2007年,我在MSDN上發表了如何在Vista下透過TSF來切換中文輸入法,至今已經過了2年多了,原文已找不到,
所以我重新整理一份放在我的Blog上,順便修正了CoFreeTaskMem會引發的問題。
可以用在Silverlight上嗎?
   Silverlight 4的OOB+Elevated Trust模式,可以讓我們直接呼叫COM物件,這讓我有了把TSF Helper搬到Silverlight 4
上執行的想法,首先把TSF Helper改寫回COM物件,並註冊到電腦中,這並不難。
TSFWrapper.cs  | 
//////////////////////////////////////////////////////////////////////////////////// //                             TSF Wrapper  //                                                       write by code6421  //////////////////////////////////////////////////////////////////////////////////// using System; using System.ComponentModel; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace TSF {     [Guid("95C45D1B-5965-44AB-98E3-836ADDA10EB0")]     public interface ITSFHelper     {         short[] GetLangIDS();         bool ActiveInputMethodWithDesc(short langID, string desc);         string[] GetInputMethodList(short langID);         string GetCurrentInputMethodDesc(short langID);         bool DeActiveInputMethod(short langID);     }     [Guid("F2D6D1CD-A287-445C-A279-285E1E683DA1"),         ClassInterface(ClassInterfaceType.None),     ProgId("TSF.TSFHelper10")     ]     public class TSFHelper : ITSFHelper     {         public short[] GetLangIDS()         {             return TSFWrapper.GetLangIDs();         }         public bool ActiveInputMethodWithDesc(short langID, string desc)         {             return TSFWrapper.ActiveInputMethodWithDesc(langID, desc);         }         public string[] GetInputMethodList(short langID)         {             return TSFWrapper.GetInputMethodList(langID);         }         public string GetCurrentInputMethodDesc(short langID)         {             return TSFWrapper.GetCurrentInputMethodDesc(langID);         }         public bool DeActiveInputMethod(short langID)         {             return TSFWrapper.DeActiveInputMethod(langID);         }     }     public static class TSFWrapper     {         public static short[] GetLangIDs()         {             List<short> langIDs = new List<short>();             ITfInputProcessorProfiles profiles;             if (TSF_NativeAPI.TF_CreateInputProcessorProfiles(out profiles) == 0)             {                 IntPtr langPtrs;                 int fetchCount = 0;                 if (profiles.GetLanguageList(out langPtrs, out fetchCount) == 0)                 {                     for (int i = 0; i < fetchCount; i++)                     {                         short id = Marshal.ReadInt16(langPtrs, sizeof(short) * i);                         langIDs.Add(id);                     }                 }                 Marshal.ReleaseComObject(profiles);             }             return langIDs.ToArray();         }         public static bool ActiveInputMethodWithDesc(short langID, string desc)         {             ITfInputProcessorProfiles profiles;             if (TSF_NativeAPI.TF_CreateInputProcessorProfiles(out profiles) == 0)             {                 try                 {                     IEnumTfLanguageProfiles enumerator = null;                     if (profiles.EnumLanguageProfiles(langID, out enumerator) == 0)                     {                         if (enumerator != null)                         {                             TF_LANGUAGEPROFILE[] langProfile = new TF_LANGUAGEPROFILE[1];                             int fetchCount = 0;                             while (enumerator.Next(1, langProfile, out fetchCount) == 0)                             {                                 IntPtr ptr;                                 if (profiles.GetLanguageProfileDescription(ref langProfile[0].clsid, langProfile[0].langid, ref langProfile[0].guidProfile, out ptr) == 0)                                 {                                     bool enabled;                                     if (profiles.IsEnabledLanguageProfile(ref langProfile[0].clsid, langProfile[0].langid, ref langProfile[0].guidProfile, out enabled) == 0)                                     {                                         if (enabled)                                         {                                             string s = Marshal.PtrToStringBSTR(ptr);                                             if (s.Equals(desc))                                                 return profiles.ActivateLanguageProfile(ref langProfile[0].clsid, langProfile[0].langid, ref langProfile[0].guidProfile) == 0;                                         }                                     }                                     Marshal.FreeBSTR(ptr);                                     //Marshal.FreeCoTaskMem(ptr);                                 }                             }                         }                     }                 }                 finally                 {                     Marshal.ReleaseComObject(profiles);                 }             }             return false;         }         public static string[] GetInputMethodList(short langID)         {             List<string> imeList = new List<string>();             ITfInputProcessorProfiles profiles;             if (TSF_NativeAPI.TF_CreateInputProcessorProfiles(out profiles) == 0)             {                 try                 {                     IEnumTfLanguageProfiles enumerator = null;                     if (profiles.EnumLanguageProfiles(langID, out enumerator) == 0)                     {                         if (enumerator != null)                         {                             TF_LANGUAGEPROFILE[] langProfile = new TF_LANGUAGEPROFILE[1];                             int fetchCount = 0;                             while (enumerator.Next(1, langProfile, out fetchCount) == 0)                             {                                 IntPtr ptr;                                 if (profiles.GetLanguageProfileDescription(ref langProfile[0].clsid, langProfile[0].langid, ref langProfile[0].guidProfile, out ptr) == 0)                                 {                                     bool enabled;                                     if (profiles.IsEnabledLanguageProfile(ref langProfile[0].clsid, langProfile[0].langid, ref langProfile[0].guidProfile, out enabled) == 0)                                     {                                         if (enabled)                                             imeList.Add(Marshal.PtrToStringBSTR(ptr));                                     }                                 }                                 Marshal.FreeBSTR(ptr);                                 //in windows 2008, it will crash.                                 //Marshal.FreeCoTaskMem(ptr);                             }                         }                     }                 }                 finally                 {                     Marshal.ReleaseComObject(profiles);                 }             }             return imeList.ToArray();         }         public static string GetCurrentInputMethodDesc(short langID)         {             ITfInputProcessorProfiles profiles;             if (TSF_NativeAPI.TF_CreateInputProcessorProfiles(out profiles) == 0)             {                 try                 {                     Guid clsid;                     Guid profileid;                     Guid catid = new Guid(TSF_NativeAPI.GUID_TFCAT_TIP_KEYBOARD.ToByteArray());                     if (profiles.GetDefaultLanguageProfile(langID, ref catid, out clsid, out profileid) == 0)                     {                         if (profiles.GetActiveLanguageProfile(ref clsid, out langID, out profileid) == 0)                         {                             IntPtr ptr;                             try                             {                                 if (profiles.GetLanguageProfileDescription(ref clsid, langID, ref profileid, out ptr) == 0)                                 {                                     string s = Marshal.PtrToStringBSTR(ptr);                                     Marshal.FreeBSTR(ptr);                                     //in windows 2008 , it will carsh.                                     //Marshal.FreeCoTaskMem(ptr);                                     return s;                                 }                             }                             catch (Exception ex)                             {                                 int i = 0;                             }                         }                     }                 }                 finally                 {                     Marshal.ReleaseComObject(profiles);                 }             }             return string.Empty;         }         public static bool DeActiveInputMethod(short langID)         {             List<string> imeList = new List<string>();             ITfInputProcessorProfiles profiles;             if (TSF_NativeAPI.TF_CreateInputProcessorProfiles(out profiles) == 0)             {                 try                 {                     Guid clsid = Guid.Empty;                     return profiles.ActivateLanguageProfile(ref clsid, langID, ref clsid) == 0;                 }                 finally                 {                     Marshal.ReleaseComObject(profiles);                 }             }             return false;         }     } }  | 
透過RegAsm即可註冊到電腦中。
Visual Studio Command Prompt  | 
regasm TSFIMEHelper.dll  | 
結合Silverlight OOB+Elevated Trust
   最後是在Silverlight中使用它了,請注意,此法僅能用於Silverlight OOB+Elevated Trust模式。
MainPage.xaml  | 
<UserControl x:Class="SilverlightApplication27.MainPage"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d"     d:DesignHeight="300" d:DesignWidth="400">     <Grid x:Name="LayoutRoot" Background="White">         <TextBox Height="23" HorizontalAlignment="Left" Margin="52,46,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />         <Button Content="Fetch Input List" Height="23" HorizontalAlignment="Left" Margin="275,35,0,0" Name="button1" VerticalAlignment="Top" Width="113" Click="button1_Click" />         <ListBox Height="100" HorizontalAlignment="Left" Margin="21,150,0,0" Name="listBox1" VerticalAlignment="Top" Width="231" />         <Button Content="Switch To" Height="23" HorizontalAlignment="Left" Margin="275,85,0,0" Name="button2" VerticalAlignment="Top" Width="113" Click="button2_Click" />         <Button Content="Deactive" Height="23" HorizontalAlignment="Left" Margin="275,138,0,0" Name="button3" VerticalAlignment="Top" Width="113" Click="button3_Click" />     </Grid> </UserControl>  | 
MainPage.xaml.cs  | 
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SilverlightApplication27 {     public partial class MainPage : UserControl     {         public MainPage()         {             InitializeComponent();         }         private void button1_Click(object sender, RoutedEventArgs e)         {             if (System.Runtime.InteropServices.Automation.AutomationFactory.IsAvailable)             {                 dynamic tsfHelper = System.Runtime.InteropServices.Automation.AutomationFactory.CreateObject("TSF.TSFHelper10");                 short[] result = (short[])tsfHelper.GetLangIDs();                 foreach (var lid in result)                 {                     string[] inputs = (string[])tsfHelper.GetInputMethodList(lid);                     foreach (var sname in inputs)                         listBox1.Items.Add(sname + "," + lid.ToString());                 }             }         }         private void button2_Click(object sender, RoutedEventArgs e)         {             if (System.Runtime.InteropServices.Automation.AutomationFactory.IsAvailable)             {                 if (listBox1.SelectedIndex != -1)                 {                     dynamic tsfHelper = System.Runtime.InteropServices.Automation.AutomationFactory.CreateObject("TSF.TSFHelper10");                     string[] sels = ((string)listBox1.Items[listBox1.SelectedIndex]).Split(',');                     tsfHelper.ActiveInputMethodWithDesc(short.Parse(sels[1]), sels[0]);                 }             }         }         private void button3_Click(object sender, RoutedEventArgs e)         {             if (System.Runtime.InteropServices.Automation.AutomationFactory.IsAvailable)             {                 dynamic tsfHelper = System.Runtime.InteropServices.Automation.AutomationFactory.CreateObject("TSF.TSFHelper10");                 string[] sels = ((string)listBox1.Items[listBox1.SelectedIndex]).Split(',');                 tsfHelper.DeActiveInputMethod(short.Parse(sels[1]));             }         }     } }  | 
編譯並執行,按下Fetch Input List按鈕,可取得輸入法列表。

接著選取輸入法,按下Switch To即可切換,按下Deactive則切回英數。
範例下載: http://code6421.sg1002.myweb.hinet.net/SL4/TSF/TSF_Silverlight.ZIP