0

Com インターフェイスを .net アプリケーションで利用したいのですが、これはテキスト サービス フレームワークに関連しており、これについて再調査したところ、COM サーバーのみをサポートしているようでした。これについて誰か助けてくれませんか。ネットアプリケーションとはいの場合は、それを行う方法を教えてくださいplzzzzzz :)ありがとう

4

1 に答える 1

3

私は同じ問題を抱えています。仕事をするために本当に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 ファイルでしか IID を見つけられなかったからです。私が思うにそのファイルを解析する方が良いでしょうが、これもうまくいきます。指定されたクラスは正常に動作します。次のバッチでサービスを登録できます (C# プロジェクトのオプションで regasm が有効になっているかどうかを確認してください)

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

私が抱えていた問題は、これらすべてに多大な努力が必要であり、私が考える痛みに値しない多くの問題があることです. よくわかりませんが、誰かに何らかのガイダンスがあればいいのにと思います。ポイントは、常に次のような素晴らしいサイトに従う必要があるということです: TSF Aware ブログ ですが、とにかく C++ で書くことができます。1 つのオプションは、C++/CLR かもしれません。すべての COM と登録を C++ で行い、ロジックを C# で行う可能性があります。

基本的に機能することを示すテストコードを次に示します。

var プロファイル = 新しい 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;
}
于 2010-05-19T18:31:48.377 に答える