【问题标题】:how to make use of Text Services Framework into .net application如何在 .net 应用程序中使用文本服务框架
【发布时间】:2010-05-04 04:45:32
【问题描述】:

我想在我的 .net 应用程序中使用 Com 接口, 但这与 Text Services Framework 有关,我对此进行了重新搜索,好像它只支持 COM 服务器 谁可以帮我这个事 我可以在我的 .net 应用程序中使用 TSF 接口吗 如果是,请告诉我该怎么做 plzzzzzz :) 谢谢

【问题讨论】:

    标签: .net com text-services-framework


    【解决方案1】:

    嘿,我有同样的问题,我正在评估我是否真的必须使用 C++ 来完成这项工作。您当然可以在任何兼容 COM 的环境中创建 COM 服务器,在 .NET 中也是如此。 到目前为止,我还没有处于任何可用状态,但我可以告诉你我到目前为止做了什么。 首先,msctf.dll 只有一个头文件和一个 IDL 文件(在 Windows SDK 7.0 中),必须对其进行修改以获得类型库 (tlb)。我使用了 codeplex 的 tlbimp2,它​​有一个基于 xml 的重写机制(这可以减轻类型库中指针的大量使用: 这是我的批处理文件

    set sdk7=C:\Program Files\Microsoft SDKs\Windows\v7.0
    set imported=msctf
    
    rem call "%sdk7%\Bin\SetEnv.cmd"
    midl "%sdk7%\Include\%imported%.idl"
    rem i copied the tlbimp2 into the sdk bin
    tlbimp2 /keyfile:TextService.snk %imported%.tlb /config:msctf.xml
    rem tlbimp /keyfile:TextService.snk %imported%.tlb
    
    rem not sure about this
    gacutil /u %imported%
    gacutil /i %imported%.dll
    

    这里是我的 XML 规则文件(当然要扩展) http://clrinterop.codeplex.com/

    <Rules>
      <Rule Name="addlangprofile string 1" Category="Signature">
        <Condition>
          <And>
            <NativeParentFunctionName Operator="Equal" Value="AddLanguageProfile" />
            <NativeParameterIndex Operator="Equal" Value="4" />
          </And>
        </Condition>
        <Action Name="ConvertTo">
          <Parameter Key="Direction" Value="[In]" />
          <Parameter Key="ByRef" Value="False" />
          <Parameter Key="ManagedType" Value="LPArray" />
          <Parameter Key="MarshalAs" Value="(default)" />
          <Parameter Key="Attributes" Value="[SizeParamIndexOffset=+1]" />
        </Action>
      </Rule>
      <Rule Name="addlanguageprofile string2" Category="Signature">
        <Condition>
          <And>
            <NativeParentFunctionName Operator="Equal" Value="AddLanguageProfile" />
            <NativeParameterIndex Operator="Equal" Value="6" />
          </And>
         </Condition>
         <Action Name="ConvertTo">
           <Parameter Key="Direction" Value="[In]" />
           <Parameter Key="ByRef" Value="False" />
           <Parameter Key="ManagedType" Value="LPArray" />
           <Parameter Key="MarshalAs" Value="(default)" />
           <Parameter Key="Attributes" Value="[SizeParamIndexOffset=+1]" />
         </Action>
       </Rule>
       <Rule Name="GUID" Category="Type">
         <Condition>
           <And>
             <NativeName Operator="Equal" Value="GUID" />
           </And>
         </Condition>
         <Action Name="ResolveTo">
           <Parameter Key="AssemblyName" Value="mscorlib" />
           <Parameter Key="ManagedTypeFullName" Value="System.Guid" />
         </Action>
       </Rule>
    </Rules>
    

    然后我试图将接口包装成对 .NET 更友好:

    使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Text; 使用 System.Globalization;

    using MSCTF;
    using System.Runtime.InteropServices;
    
    namespace TextService
    {
        public class LanguageProfiles
        {
            private ITfInputProcessorProfiles instance;
    
            public LanguageProfiles()
            {
                instance = new COMIFace<ITfInputProcessorProfiles>().CreateInstance();
            }
    
            public CultureInfo CurrentLanguage
            {
                get
                {
                    ushort plangid;
                    instance.GetCurrentLanguage(out plangid);
                    return CultureInfo.GetCultureInfo(plangid);
                }
                set
                {
                    instance.ChangeCurrentLanguage((ushort) value.LCID);
                }
            }
    
            public IEnumerable<TF_LANGUAGEPROFILE> ProfilesOfLanguage(CultureInfo culture)
            {
                IEnumTfLanguageProfiles ppenum;
                instance.EnumLanguageProfiles( (ushort) culture.LCID, out ppenum);
    
                TF_LANGUAGEPROFILE profile;
                uint fetch;
                do
                {
                    ppenum.Next(1, out profile, out fetch);
                    yield return profile;
                } while (fetch == 1 && profile.fActive != -1);
            }
    
            public void Register(ref Guid rclsid)
            {
                instance.Register(ref rclsid);
            }
    
            public void Unregister(ref Guid rclsid)
            {
                instance.Unregister(ref rclsid);
            }
    
            public void Add(ref Guid rclsid, CultureInfo info, string name, string icon)
            {
                var empty = Guid.Empty;
                instance.AddLanguageProfile(ref empty, (ushort)info.LCID, ref rclsid, name.ToUShortArray(), name.ULength(), icon.ToUShortArray(), icon.ULength(), 0);
            }
    
            public void Remove(ref Guid rclsid, CultureInfo info)
            {
                instance.RemoveLanguageProfile(ref rclsid, (ushort)info.LCID, ref rclsid);
            }
        }
    }
    

    COMIFace 类只是从注册表中获取 IID 的助手,因为我只在 IDL 编译器生成的 .c 文件中找到了它们。我认为最好解析那个文件,但这也很好。 给定的类工作正常,我可以使用以下批次注册服务(检查 C# 项目选项中是否启用了 regasm)

    set outtype=Debug
    set asmname=TextService
    cd bin\%outtype%
    gacutil /u %asmname%
    gacutil /i %asmname%.dll
    cd ..\..
    

    我遇到的问题是,这一切都是一项巨大的努力,而且有很多问题不值得我认为的痛苦。我不确定,希望有人能得到一些指导。 一点是,一个人总是需要关注一些像这样的伟大网站:TSF Aware blog 但是你无论如何都可以用C++编写它。 一种选择可能是 C++/CLR,在 C++ 中完成所有 COM 的东西和注册以及在 C# 中的逻辑,我猜可能

    这是一些测试代码,表明它基本上可以工作:

    var profiles = new LanguageProfiles();

    var ko_KR = CultureInfo.GetCultureInfo("ko-KR");
    
    foreach (var profile in profiles.ProfilesOfLanguage(ko_KR))
    {
        Console.WriteLine("clsid: " + profile.clsid + " lid: " + CultureInfo.GetCultureInfo(profile.langid) + " catid: " + profile.catid + " active: " + profile.fActive + " guidProf: " + profile.guidProfile);
        var id = profile.clsid;
    }
    

    【讨论】:

    • 嘿,我也可以给你我的解决方案文件夹,但我不知道哪里有最好的上传位置
    • @SebastianGodelet,这很棒。多年来,我一直在寻找这样的解决方案。我真的很想得到任何可以帮助我为 TSF 制作包装器的东西。有没有机会为对这种开发感兴趣的我们在 mediafire 或其他地方粘贴一些代码?
    • 我并没有真正在其中工作,我仍然有文件,但我实际上认为可能会有一个新的尝试我猜,我认为这个代码 + MEF 的组合会很棒,这样您就可以编写通用 COM 代码膨胀,然后并排打包单个 IME
    • 不幸的是我不懂 C++。如果我们所有对 .NET 的包装器感兴趣的人都能启动一个开源项目,那就太好了。可能我见过的最好的尝试来自一个日本人:d.hatena.ne.jp/NyaRuRu/20040524/p1...当然,MS 似乎已经实现了各种零碎的东西....参见 System.Windows.Input.TextServicesContext 和 System.Windows。文档.TextStore。当然还有遍布 StackOverflow 和其他地方的点点滴滴。如果我们能将这些资源整合在一起并拥有我们都可以在 .NET 中使用的东西,那就太好了
    • 你好@Matt 你最近对这件事做了什么吗?
    猜你喜欢
    • 1970-01-01
    • 2020-12-07
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多