如何确定 Tcl_Obj 是否是某种 ttk:: 实体,例如 ttk:entry?

How can I find out if a Tcl_Obj is a certain kind of ttk:: entity, such as ttk:entry?

我正在使用一个遗留的(桌面风格,现在已知)Windows 应用程序主要是用 C 和 C++ 构建的。当此应用程序 运行 在触摸屏 Windows 笔记本电脑上运行时,我需要在用户点击对话框屏幕上的输入框内部时自动显示触摸键盘。这种行为很常见,据我所知,Microsoft 禁用 这种以前在 Windows 8/8.1 中的自动行为,并将在 [=] 中重新启用它29=]10.

所以...我可以通过编程方式显示触摸键盘,那部分已经解决了。我现在要做的是在 ttk::entry 小部件接收到焦点然后激活键盘时捕捉。我最接近的是在 tk8.5.9/generic/tkFocus.c 里面。有一种方法叫做 Tk_FocusObjCmd:

 /*
 *--------------------------------------------------------------
 *
 * Tk_FocusObjCmd --
 *
 *  This function is invoked to process the "focus" Tcl command. See the
 *  user documentation for details on what it does.
 *
 * Results:
 *  A standard Tcl result.
 *
 * Side effects:
 *  See the user documentation.
 *
 *--------------------------------------------------------------
 */

int
Tk_FocusObjCmd(
    ClientData clientData,  /* Main window associated with interpreter. */
    Tcl_Interp *interp,     /* Current interpreter. */
    int objc,           /* Number of arguments. */
    Tcl_Obj *CONST objv[])  /* Argument objects. */
{

除其他外,此方法还提供了一个 Tcl_Obj 对象数组。我想做的是找出被操作的对象是否属于某种类型,例如 ttk::entry。如果是,我将启动触摸键盘。我试过使用 object->typePtr->name,但这并没有给我预期的结果,有时它会崩溃(还没有弄清楚为什么):

char *objectType = objv[1]->typePtr->name;

if (objectType)
{
    printf("Object Type: %s\n", objectType); // don't do this, it breaks sometimes.
}

这就是我卡住的地方。我将不胜感激任何能让我朝着正确方向前进的见解。

你的做法大错特错。你应该做的是假设你传递了一个小部件名称(类似于.a2.b5.c9)然后让Tk告诉你知道这个名字的小部件的 class 是什么。

winfo class .a2.b5.c9

对于 ttk::entry 的实例,这将 return TEntry(除非您通过在小部件创建时传入 -class 选项来更改它)。

从 C 级别开始,您可以使用 Tk_Class() 查询 class,它接受一个 Tk_Window 参数(您可以通过 Tk_NameToWindow、传入参数值的字符串形式,您又可以从 Tcl_GetString 获得)。但是使用 Tcl_VarEval 可能更简单,假设是非邪恶的 window 名字……

if (Tcl_VarEval(interp, "winfo class ", Tcl_GetString(objPtr), NULL) == TCL_OK) {
    const char *className = Tcl_GetString(Tcl_GetObjResult(interp));
    // ...
}

(真正谨慎的人或真正追求速度的人会使用Tcl_EvalObjv,但那有点复杂。)