问题标签 [text-services-framework]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - ITfFnReconversion::QueryRange 使用“Microsoft IME(日语)”输出 NULL
参考TSF 的 Get the candicate list的文章(对不起,是日文写的),我开发了一个 C++ Component of Windows Store App。
但是当我测试这个组件的时候,有一个奇怪的现象:如果我把输入法变成“微软输入法”,代码
始终在输出参数“range_cp”中返回 NULL,但如果我将输入法转换为“Google 日本语入力”,“range_cp”将返回正确的结果,我可以通过 ITfFnReconversion::GetReconversion 获取候选列表。
有人遇到过同样的问题吗?或者我错过了 Microsoft IME 的一些设置?
有这个问题的代码部分:
我非常感谢您能提供的任何帮助。
winapi - 在 Windows 上的自定义控件中处理任意文本输入的正确、现代方法是什么?WM_CHAR?国际模联?TSF?
我希望能够支持自定义 Windows 控件中的文本输入,就像 EDIT 和富编辑控件已经做的那样,但不继承其中任何一个。该控件当前使用 Direct2D 和 DirectWrite 来绘制文本,并在具有平台更新或更新版本的 Windows Vista SP1 上运行(如果我决定需要更新的 Direct2D 和 DirectWrite 功能,我可能会将其更改为具有平台更新或更新版本的 Windows 7 SP1,假设这些是在那里或仅在 Windows 8 上可用,但这是一个不同的问题......)
对于它的价值,在 OS XI 上将使用NSTextInputClient而在 GTK+ 上我将使用GtkIMContext。我说的就是这些。
显而易见的选择是使用WM_CHAR
,如果我正确收集,如果窗口类注册了RegisterClassW()
,则它本身就是 UTF-16,因此无论位置如何都应该“正常工作”。但是,WM_CHAR
是由 生成的TranslateMessage()
,它的文档说没有办法确定 aWM_CHAR
是否已经生成,因为TranslateMessage()
总是返回非零。我需要能够确定当前的键盘消息是否将由文本系统处理(因此应该被忽略);尤其如此,因为所有非文本键都需要以独立于布局的方式(我已经拥有)进行处理。
我还在 IMM API 和文本服务框架的 Windows 7 示例代码中看到。我不确定一个是否比另一个更好,而且他们似乎都在做同样的事情。他们有吗?
在 IMM 的情况下,有许多WM_IMM_xxx
消息我不确定是否应该忽略,而且我发现的每个参考似乎都不同意我是否应该在 Unicode 窗口中处理它们。 .. 此外,上述知道给定关键事件是否将由 IMM 处理的问题仍然存在;有办法吗?
TSF 有一个称为 ACP 的概念,它似乎允许我使用我想要的任何文本存储格式来存储我实际要使用的文本(即,不是正在进行的合成)。这是真的?我希望能够将我的文本存储为带有属性的 UTF-8,在绘图时转换为 UTF-16(用于 DirectWrite)。其他 API 选择是否也允许我这样做?
还是我完全走错了路?
我使用的其他参考资料:
谢谢。
更新2016 年 11 月 7 日
再次查看 TsfPad 示例后,我注意到它似乎也只是使用WM_CHAR
; 现在我不确定它是如何使用 TSF 的,除此之外......
winapi - 由于 TranslateMessage() 无条件返回非零值,我如何才能在事实发生之前或之后判断是否发生了翻译?
这是什么是在 Windows 上的自定义控件中处理任意文本输入的正确、现代的方法的延续?WM_CHAR?国际模联?TSF?.
因此,在尝试了非 IME 布局(美国英语)、非 TSF IME(来自 Windows XP DDK 的日语 FAKEIME)和 TSF 文本服务(Windows 7 附带的任何内容)之后,似乎如果活动输入处理器配置文件不是 TSF 文本服务(也就是说,它是一个TF_PROFILETYPE_KEYBOARDLAYOUT
),我仍然必须处理击键和WM_CHAR
消息来进行文本输入。
我的问题是我的架构需要一种方法来告知它可以忽略当前的关键消息,因为它已被翻译成文本输入消息。它不关心这发生在翻译之前还是之后;它只需要知道这样的翻译将会或已经发生。或者用伪代码术语:
处理文本输入的标准方法,无论是从键盘还是通过非 TSF IME,都是让TranslateMessage()
-to-WM_KEYDOWN
翻译WM_CHAR
。但是,有一个问题:MSDN 说
如果消息是 WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN 或 WM_SYSKEYUP,则无论转换如何,返回值都是非零值。
这意味着我无法使用它来确定是否发生了翻译。
在阅读了一些 Michael Kaplan 博客文章后,我想我可以使用ToUnicode()
或ToUnicodeEx()
自己进行转换,将状态数组从GetKeyboardState()
. wine 源代码似乎同意,但它有两个特殊情况,我不确定它们是特定于 wine 还是需要在真实 Windows 上完成:
VK_PACKET
WM_CHAR
—直接从消息中生成一个LPARAM
VK_PROCESS
— 调用一个函数ImmTranslateMessage()
,该函数似乎是特定于葡萄酒的函数或未记录的 imm32.dll 函数;我分不清哪个是真的
而且 wine 也与WM_KEYUP
and无关WM_SYSKEYUP
;再说一次,我不知道这是否仅适用于葡萄酒。
但是在使用 TSF 的程序中,我什至需要担心这些情况吗?如果我这样做,那么“官方”的做法是什么?即便如此,我会在WM_KEYUP
/上做什么WM_SYSKEYUP
;我也需要把这些寄给ToUnicode()
吗?WM_KEYUP
如果有 s,我什至需要特别在我的窗口中捕捉sWM_CHAR
吗?
或者我是否遗漏了任何 MSDN TSF 示例中没有的东西,这些示例允许我让 TSFTF_PROFILETYPE_KEYBOARDLAYOUT
处理处理器?我认为 TSF 进行了透明的 IME 直通,但我对 FAKEIME 样本的实验显示其他情况......?我看到 Firefox 和 Chromium 也检查TF_PROFILETYPE_KEYBOARDLAYOUT
甚至用于ImmGetIMEFileName()
查看键盘布局是否由 IME 支持,但我不知道在这些情况下他们是否真的自己处理输入......
我现在的最低版本是 Windows 7。
谢谢。
更新这个问题的原始版本包括需要了解关联WM_KEYUP
的s;在第二次查看我在其他平台上的等效代码时,这毕竟不是必需的,除了 ; 的细节TranslateMessage()
。我已经相应地调整了问题。(在 OS X 上,您甚至不会向文本输入系统提供按键释放事件;在 GTK+ 上您会这样做,但似乎插入字符的按键不会影响释放,因此无论如何它们都不会被处理,至少对于我尝试过的输入法(可能有一些……)。话虽如此,如果我错过了什么,我添加了另一个子问题。
.net - CLR 无法在 UWP 中创建基于 .NET 的 COM 对象
我创建了一个类库(.NET Framework 4.7.1),它使用属性在TSFITfTextInputProcessorEx
中实现了文本服务(等) 。我使用它注册了它,它可以被系统成功识别为输入法(IME),并且可以在大多数应用程序中使用,除了 UWP 应用程序。ComVisible
RegistrationServices
在 Win32 应用程序中使用
在 Win32 应用程序(例如 32 位notepad.exe
)中,当我激活基于 .NET 的 TextService(通过切换到语言栏中的 IME)时会发生以下情况:
(圈出YngPing.TSF.dll
的是包含 COM 对象实现的 .NET 程序集。由 COM 对象创建引起的加载从 #56 开始。)
基本上,在切换到我的 IME 时,TSF 框架(不是应用程序代码,而是在同一进程中运行)将尝试通过调用来创建/请求我的 TextService 的 COM 对象CoCreateObject
。因为这不是本机 COM 对象,mscoree.dll
实际上是注册表中的“真实”COM DLL。mscoree.dll
首先加载,然后加载mscoreei.dll
,clr.dll
等等,最后加载实际的 .NET dll。
在 AppContainer 中使用(UWP 应用)
现在这些都在普通桌面应用程序中按预期工作,但在 UWP 应用程序中,相同的进程将在加载后停止mscoree.dll
(mscoreei.dll
即clr.dll
,我的 .NET 程序集未加载)。调用堆栈如下所示:
(这里测试的 UWP 应用只是一个带有文本框的空白应用。所有这些 COM 加载都是由 TSF 发起的。)
另一个观察:在调用mscoree.dll
退出之后,内部的一个指针combase.dll
被设置为E_NOTIMPL
.
在同一个 UWP 应用程序中,可以毫无问题地加载和使用其他 3rd 方 IME 的 DLL(比如这个用 C++ 编写的https://github.com/rime/weasel )。我还没有测试官方示例,https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/IME ,但我很有信心它也会起作用。
我对正在发生的事情有一个粗略的了解,但我缺乏深入研究根本原因的专业知识:对于基于 .NET 的 COM 对象,会在请求 COM 对象时首先加载 CLR;但在这种情况下,对于 UWP,CLR 无法加载,随后 COM 对象无法启动。
我还使用了 Fusion Log(UWP 具有沉浸式模式),但没有看到任何相关消息。我想这是因为clr.dll
在我的情况下甚至没有加载。
谁能提供一些关于如何解决这个问题的想法?谢谢!
更新:当我在这篇文章中说“IME”时,我的意思是“使用文本服务框架 API 的文本服务”,而不是传统的“输入法管理器 (IMM)”基于 API 的 IME。
com - 文本服务框架未能将全局区间值设置为 VT_BSTR
我为使用 TSF 全局区间的进程间通信编写了一个测试应用程序 (.exe),当变体类型为 VT_I4 时,以下代码可以正常工作,但对于 VT_BSTR,ITfCompartment::SetValue 返回 S_FALSE 并且 OnChange 回调不会在文本服务(IME)。
ITfCompartment::SetValue 的 S_FALSE 甚至没有记录在 MSDN 上,我猜这意味着操作成功但没有效果。
谁能提供一些关于如何解决这个问题的想法?谢谢!
c# - TF_E_NOLOCK如何解决:ec中的cookie无效
我正在开发 TSF 文本服务。它依赖于 TSF-TypeLib。这是我项目的一部分代码:
错误发生在“res = context.GetStart(e, out var range);”的行中。
TF_E_NOLOCK:ec中的cookie无效。
如何解决这个问题?
com - 如果应用程序以 SYSTEM 用户身份运行,则文本服务框架 AdviseSink 对全局隔间失败
当我尝试在以 SYSTEM 用户身份启动的进程中为全局隔离专区建议 ITfCompartmentEventSink 时,AdviseSink 失败并显示 E_FAIL。我尝试冒充普通用户,但似乎没有帮助。
并且隔间 GetValue 会成功,但 SetValue 也会因 E_FAIL 而失败。
但是,当该过程以普通用户身份启动时,AdviseSink 可以正常工作。
以下示例代码中的 AdviseSink 对于 SYSTEM 用户也失败。
Windows-classic-samples\Samples\Win7Samples\winui\tsf\tsfcompart\monitor.cpp
那么我是否必须以某种方式设置安全描述符或使用特定选项初始化 COM 库才能使其工作?
谢谢。
c++ - Windows 10 检测键盘布局更改
我正在尝试实施一项可以监视语言/布局更改的服务。我在英语和俄语之间切换。到目前为止,我已经找到了这个问题并尝试实施和安装那里建议的两个接收器。但是,也有问题。ITfActiveLanguageProfileNotifySink::OnActivated
根本没有触发;ITfLanguageProfileNotifySink::OnLanguageChange
也没有被触发;ITfLanguageProfileNotifySink::OnLanguageChanged
仅当我的程序的主窗口处于前台时触发,但它不包含有关语言的任何信息。有没有办法在全球范围内监控输入语言更改事件?