Reputation: 2037
I am working with a legacy (Desktop-style, as they're now known) Windows application built mostly in C and C++. When this application is running on a touchscreen Windows laptop, I need to automatically show the touch keyboard when the user taps inside an entry box on a dialog screen. This behavior is very common, and as far as I can tell, Microsoft disabled this formerly automatic behavior in Windows 8/8.1, and will be re-enabling it in Windows 10.
So... I can programmatically show the touch keyboard, that part is solved. What I'm trying to do now is catch when a ttk::entry widget receives focus and then activate the keyboard. The closest I've come is inside tk8.5.9/generic/tkFocus.c. There is a method called 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. */
{
This method is given, among other things, an array of Tcl_Obj objects. What I'm trying to do is find out if the one being acted on is of a certain type, such as ttk::entry. If it is, I will launch the touch keyboard. I've tried using object->typePtr->name, but that doesn't give me what I'd expected, and sometimes it crashes (haven't figured out why yet):
char *objectType = objv[1]->typePtr->name;
if (objectType)
{
printf("Object Type: %s\n", objectType); // don't do this, it breaks sometimes.
}
This is where I'm stuck. I would greatly appreciate any insight to get me in the right direction.
Upvotes: 1
Views: 76
Reputation: 137567
You're doing this very thoroughly wrong. What you should do is instead assume that you're passed a widget name (something like .a2.b5.c9
) and then ask Tk to tell you what the class of the widget with that name is.
winfo class .a2.b5.c9
For an instance of a ttk::entry
, this will return TEntry
(unless you changed it by passing in the -class
option on widget creation).
From the C level, you'd query the class by using Tk_Class()
, which takes a single Tk_Window
argument (which you can obtain via Tk_NameToWindow
, passing in the string form of the argument value, which in turn you can obtain from Tcl_GetString
). But it might be simpler to just use Tcl_VarEval
, assuming non-evil window names…
if (Tcl_VarEval(interp, "winfo class ", Tcl_GetString(objPtr), NULL) == TCL_OK) {
const char *className = Tcl_GetString(Tcl_GetObjResult(interp));
// ...
}
(The truly cautious or those really keen on speed will use Tcl_EvalObjv
, but that's a bit more complex.)
Upvotes: 1