UPDATE:
Я обнаружил, что IID для ITfDocumentMgr был в реестре, но IID для ITextStoreACP не было. Когда я удалил [Guid ("28888 ....")] из определения интерфейса ITextStoreACP, метод Push () не завершился сбоем, я подозреваю, потому что мой класс не сообщал, что у него был этот интерфейс. Затем я поместил его обратно и сделал сборку, класс и интерфейс НЕ COM видимыми. Опять же, мой метод AdviseSink не вызывается.
Любые мысли по этому поводу будут оценены.
РЯДОМ ОРИГИНАЛЬНОЙ ПОЧТЫ:
Я пытаюсь интегрировать Text Services Framework в мое приложение C #, используя мое приложение C # в качестве клиента TSF (в отличие от службы TSF). Я могу получить COM-интерфейсы TSF для создания менеджера документов. Я создал текстовое хранилище, которое реализует ITextStoreACP.
[ComVisible(true)]
public class TextStore : ITextStoreACP
{
public uint AdviseSink(
[MarshalAs(UnmanagedType.Struct)] ref IID Iid,
[MarshalAs(UnmanagedType.IUnknown)] Object pUnknown,
uint Mask
)
{
ITextStoreAcpSink Sink = pUnknown as ITextStoreAcpSink;
return 0;
}
....
}
После создания контекста, использующего мой ITextStoreACP, я затем использую DocumentMgr.Push (), чтобы использовать контекст, который ссылается на мое текстовое хранилище. В свою очередь, инфраструктура TSF должна затем вызвать мой метод ITextStoreACP.AdviseSink () с его интерфейсом приемника, чтобы я мог уведомить инфраструктуру, когда происходят изменения в содержимом текстового хранилища.
public partial class Form1 : Form
{
static ITextStoreACP pStore = new TextStore();
static Object pIunknown;
static ITfContext Context;
static ITfDocumentMgr DocMgr;
static IThreadMgr ThreadMgr;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
TfClientId Tid = new TfClientId();
TfEditCookie Cookie = new TfEditCookie();
uint hr;
// Get a new thread manager...
ThreadMgr = TsfInterfaces.CreateManager();
// Activate the thread manager and get our cookie back...
hr = ThreadMgr.Activate(out Tid);
// Create a document manager for our use...
hr = ThreadMgr.CreateDocumentMgr(out DocMgr);
// Get the IUnknown interface to pass to CreateContext()...
pIunknown = pStore as Object;
// Create a context to work in, designating our text store for our use...
hr = DocMgr.CreateContext(Tid, 0, pIunknown, out Context, out Cookie);
try
{
// Select our context to work in now. With a text store as part of
// the context, the Text services framework should call into our
// text store object with its sink interface.
//
// But it crashes instead.
//
hr = DocMgr.Push(Context);
}
catch
{
}
}
}
Я использую определение интерфейса ITfDocumentMgr здесь:
[Guid("aa80e7f4-2021-11d2-93e0-0060b067b86e")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITfDocumentMgr
{
uint CreateContext(
TfClientId Tid,
uint Flags,
[MarshalAs(UnmanagedType.IUnknown)] Object pUnkUnique,
[MarshalAs(UnmanagedType.Interface)] out ITfContext pContext,
out TfEditCookie pCookie
);
uint Push([MarshalAs(UnmanagedType.Interface)] ITfContext pContext);
uint Pop(uint Flags);
uint GetTop(out ITfContext Context);
uint GetBase(out ITfContext Context);
uint EnumContexts(out IEnumITfContexts EnumContexts);
}
Однако вместо получения вызова моего метода AdviseSink () приложение аварийно завершает работу и закрывается из-за вызова Push (). Если я не передаю интерфейс для текстового хранилища (что является законным), а скорее ноль, когда я вызываю CreateContext, то Push () возвращает нормально, поскольку нет ITextStoreACP.AdviseSink () для вызова.
Я установил для свойства проекта «Сделать сборку видимым» значение true.
Я установил для свойства проекта «Регистрация для COM-взаимодействия» значение true, хотя я не думаю, что это необходимо.
Есть ли что-то еще, что мне нужно сделать, чтобы сделать мой объект класса C # на основе интерфейса ITextStoreACP доступным для метода внешнего COM-объекта для его правильного использования?
Далее показан интерфейс, на котором я основываю свой объект TextStore. Все методы реализованы в хранилище текста, по крайней мере с исключением по умолчанию «Метод не реализован», так что я могу запустить код.
[Guid("28888fe3-c2a0-483a-a3ea-8cb1ce51ff3d")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITextStoreACP
{
uint AdviseSink(
[MarshalAs(UnmanagedType.Struct)] ref IID Iid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnknown,
uint Mask
);
uint UnadviseSink([MarshalAs(UnmanagedType.IUnknown)] object pUnknown);
uint RequestLock(uint LockFlags, out uint hrSession);
uint GetStatus([MarshalAs(UnmanagedType.Struct)] out TS_STATUS TSS);
uint QueryInsert(long TestStart, long TestEnd, ulong Count, out long ResultStart, out long ResultEnd);
uint GetSelection(
ulong Index,
ulong Count,
[MarshalAs(UnmanagedType.Struct)] out TS_SELECTION_ACP Selection,
out ulong Fetched
);
uint SetSelection(
ulong Count,
[MarshalAs(UnmanagedType.Struct)] ref TS_SELECTION_ACP Selection
);
uint GetText(
long Start,
long End,
out string Plain,
ulong PlainReq,
out ulong PlainRet,
[MarshalAs(UnmanagedType.Struct)] out TS_RUNINFO RunInfo,
ulong RunInfoReq,
out ulong RunInfoRet,
out long Next
);
uint SetText(
uint Flags,
long Start,
long End,
string Text, // What kind of marshaling should I specify here for "in WCHAR *" types?
ulong Count,
[MarshalAs(UnmanagedType.Struct)] out TS_TEXTCHANCE Change
);
uint GetFormattedText(
long Start,
long End,
[MarshalAs(UnmanagedType.Interface)] out IDataObject DataObject
);
uint GetEmbedded(
long Pos,
[MarshalAs(UnmanagedType.Struct)] ref IID GUID_Service,
[MarshalAs(UnmanagedType.Struct)] ref IID IID_Service,
[MarshalAs(UnmanagedType.IUnknown)] out object pUnk
);
uint QueryInsertEmbedded(
[MarshalAs(UnmanagedType.Struct)] ref IID GUID_Service,
[MarshalAs(UnmanagedType.Struct)] ref FORMATETC FormatEtc,
[MarshalAs(UnmanagedType.Bool)] out bool IsInsertable
);
uint InsertEmbedded(
uint Flags,
long Start,
long End,
[MarshalAs(UnmanagedType.Interface)] IDataObject DataObject,
[MarshalAs(UnmanagedType.Struct)] out TS_TEXTCHANCE Change
);
uint InsertTextAtSelection(
uint Flags,
string Text,
ulong Count,
out long Start,
out long End,
[MarshalAs(UnmanagedType.Struct)] out TS_TEXTCHANCE Change
);
uint InsertEmbeddedAtSelection(
uint Flags,
[MarshalAs(UnmanagedType.Interface)] IDataObject DataObject,
out long Start,
out long End,
[MarshalAs(UnmanagedType.Struct)] out TS_TEXTCHANCE Change
);
uint RequestSupportedAttrs(
uint Flags,
ulong FilterAttrs,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRID AttrId
);
uint RequestAttrsAtPosition(
long Pos,
ulong FilterAttrs,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRID AttrId,
uint Flags
);
uint RequestAttrsTransitioningAtPosition(
long Pos,
ulong FilterAttrs,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRID AttrId,
uint Flags
);
uint FindNextAttrTransition(
long Start,
long Halt,
ulong FilterAttrs,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRID AttrId,
uint Flags,
out long Next,
out bool Found,
out long FoundOffset
);
uint RetrieveRequestedAttrs(
ulong Count,
[MarshalAs(UnmanagedType.Struct)] ref TS_ATTRVAL Vals,
out ulong Fetched
);
uint GetEndACP(out long Acp);
uint GetActiveView(out TsViewCookie Cookie);
uint GetACPFromPoint(
TsViewCookie Cookie,
[MarshalAs(UnmanagedType.Struct)] ref POINT Point,
uint Flags,
out long Acp
);
uint GetTextExt(
TsViewCookie Cookie,
long Start,
long End,
[MarshalAs(UnmanagedType.Struct)] out RECT Rect,
out bool IsClipped
);
uint GetScreenExt(
TsViewCookie Cookie,
[MarshalAs(UnmanagedType.Struct)] out RECT Rect
);
uint GetWnd(
TsViewCookie Cookie,
[MarshalAs(UnmanagedType.I4)] IntPtr hWnd
);
}