diff options
Diffstat (limited to 'win/tkWinTest.c')
-rw-r--r-- | win/tkWinTest.c | 282 |
1 files changed, 179 insertions, 103 deletions
diff --git a/win/tkWinTest.c b/win/tkWinTest.c index 2498864..6e79df3 100644 --- a/win/tkWinTest.c +++ b/win/tkWinTest.c @@ -12,6 +12,10 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#undef USE_TCL_STUBS +#define USE_TCL_STUBS +#undef USE_TK_STUBS +#define USE_TK_STUBS #include "tkWinInt.h" HWND tkWinCurrentDialog; @@ -23,8 +27,9 @@ HWND tkWinCurrentDialog; static int TestclipboardObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); -static int TestwineventCmd(ClientData clientData, - Tcl_Interp *interp, int argc, const char **argv); +static int TestwineventObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); static int TestfindwindowObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); @@ -34,7 +39,7 @@ static int TestgetwindowinfoObjCmd(ClientData clientData, static int TestwinlocaleObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); -MODULE_SCOPE int TkplatformtestInit(Tcl_Interp *interp); +static Tk_GetSelProc SetSelectionResult; /* *---------------------------------------------------------------------- @@ -63,7 +68,7 @@ TkplatformtestInit( Tcl_CreateObjCommand(interp, "testclipboard", TestclipboardObjCmd, (ClientData) Tk_MainWindow(interp), NULL); - Tcl_CreateCommand(interp, "testwinevent", TestwineventCmd, + Tcl_CreateObjCommand(interp, "testwinevent", TestwineventObjCmd, (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testfindwindow", TestfindwindowObjCmd, (ClientData) Tk_MainWindow(interp), NULL); @@ -74,6 +79,42 @@ TkplatformtestInit( return TCL_OK; } +struct TestFindControlState { + int id; + HWND control; +}; + +/* Callback for window enumeration - used for TestFindControl */ +BOOL CALLBACK TestFindControlCallback( + HWND hwnd, + LPARAM lParam +) +{ + struct TestFindControlState *fcsPtr = (struct TestFindControlState *)lParam; + fcsPtr->control = GetDlgItem(hwnd, fcsPtr->id); + /* If we have found the control, return FALSE to stop the enumeration */ + return fcsPtr->control == NULL ? TRUE : FALSE; +} + +/* + * Finds the descendent control window with the specified ID and returns + * its HWND. + */ +HWND TestFindControl(HWND root, int id) +{ + struct TestFindControlState fcs; + + fcs.control = GetDlgItem(root, id); + if (fcs.control == NULL) { + /* Control is not a direct child. Look in descendents */ + fcs.id = id; + fcs.control = NULL; + EnumChildWindows(root, TestFindControlCallback, (LPARAM) &fcs); + } + return fcs.control; +} + + /* *---------------------------------------------------------------------- * @@ -106,7 +147,8 @@ AppendSystemError( if (Tcl_IsShared(resultPtr)) { resultPtr = Tcl_DuplicateObj(resultPtr); } - length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM + length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (WCHAR *) wMsgPtrPtr, 0, NULL); @@ -114,6 +156,7 @@ AppendSystemError( char *msgPtr; length = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) &msgPtr, 0, NULL); @@ -185,50 +228,36 @@ AppendSystemError( */ static int +SetSelectionResult( + ClientData dummy, + Tcl_Interp *interp, + const char *selection) +{ + Tcl_AppendResult(interp, selection, NULL); + return TCL_OK; +} + +static int TestclipboardObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { - HGLOBAL handle; - char *data; - int code = TCL_OK; + Tk_Window tkwin = (Tk_Window) clientData; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } - if (OpenClipboard(NULL)) { - /* - * We could consider using CF_UNICODETEXT on NT, but then we - * would have to convert it from External. Instead we'll just - * take this and do "bytestring" at the Tcl level for Unicode - * inclusive text - */ - handle = GetClipboardData(CF_TEXT); - if (handle != NULL) { - data = GlobalLock(handle); - Tcl_AppendResult(interp, data, NULL); - GlobalUnlock(handle); - } else { - Tcl_AppendResult(interp, "null clipboard handle", NULL); - code = TCL_ERROR; - } - CloseClipboard(); - return code; - } else { - Tcl_AppendResult(interp, "couldn't open clipboard: ", NULL); - AppendSystemError(interp, GetLastError()); - return TCL_ERROR; - } - return TCL_OK; + return TkSelGetSelection(interp, tkwin, Tk_InternAtom(tkwin, "CLIPBOARD"), + XA_STRING, SetSelectionResult, NULL); } /* *---------------------------------------------------------------------- * - * TestwineventCmd -- + * TestwineventObjCmd -- * * This function implements the testwinevent command. It provides a way * to send messages to windows dialogs. @@ -243,19 +272,21 @@ TestclipboardObjCmd( */ static int -TestwineventCmd( +TestwineventObjCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - const char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { HWND hwnd = 0; HWND child = 0; + HWND control; int id; char *rest; UINT message; WPARAM wParam; LPARAM lParam; + LRESULT result; static const TkStateMap messageMap[] = { {WM_LBUTTONDOWN, "WM_LBUTTONDOWN"}, {WM_LBUTTONUP, "WM_LBUTTONUP"}, @@ -266,38 +297,38 @@ TestwineventCmd( {-1, NULL} }; - if ((argc == 3) && (strcmp(argv[1], "debug") == 0)) { + if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]), "debug") == 0)) { int b; - if (Tcl_GetBoolean(interp, argv[2], &b) != TCL_OK) { + if (Tcl_GetBoolean(interp, Tcl_GetString(objv[2]), &b) != TCL_OK) { return TCL_ERROR; } TkWinDialogDebug(b); return TCL_OK; } - if (argc < 4) { + if (objc < 4) { return TCL_ERROR; } - hwnd = INT2PTR(strtol(argv[1], &rest, 0)); - if (rest == argv[1]) { - hwnd = FindWindow(NULL, argv[1]); + hwnd = INT2PTR(strtol(Tcl_GetString(objv[1]), &rest, 0)); + if (rest == Tcl_GetString(objv[1])) { + hwnd = FindWindowA(NULL, Tcl_GetString(objv[1])); if (hwnd == NULL) { - Tcl_SetResult(interp, "no such window", TCL_STATIC); + Tcl_SetObjResult(interp, Tcl_NewStringObj("no such window", -1)); return TCL_ERROR; } } UpdateWindow(hwnd); - id = strtol(argv[2], &rest, 0); - if (rest == argv[2]) { + id = strtol(Tcl_GetString(objv[2]), &rest, 0); + if (rest == Tcl_GetString(objv[2])) { char buf[256]; child = GetWindow(hwnd, GW_CHILD); while (child != NULL) { - SendMessage(child, WM_GETTEXT, (WPARAM) sizeof(buf), (LPARAM) buf); - if (strcasecmp(buf, argv[2]) == 0) { + SendMessageA(child, WM_GETTEXT, (WPARAM) sizeof(buf), (LPARAM) buf); + if (strcasecmp(buf, Tcl_GetString(objv[2])) == 0) { id = GetDlgCtrlID(child); break; } @@ -305,19 +336,20 @@ TestwineventCmd( } if (child == NULL) { Tcl_AppendResult(interp, "could not find a control matching \"", - argv[2], "\"", NULL); + Tcl_GetString(objv[2]), "\"", NULL); return TCL_ERROR; } } - message = TkFindStateNum(NULL, NULL, messageMap, argv[3]); + + message = TkFindStateNum(NULL, NULL, messageMap, Tcl_GetString(objv[3])); wParam = 0; lParam = 0; - if (argc > 4) { - wParam = strtol(argv[4], NULL, 0); + if (objc > 4) { + wParam = strtol(Tcl_GetString(objv[4]), NULL, 0); } - if (argc > 5) { - lParam = strtol(argv[5], NULL, 0); + if (objc > 5) { + lParam = strtol(Tcl_GetString(objv[5]), NULL, 0); } switch (message) { @@ -325,7 +357,19 @@ TestwineventCmd( Tcl_DString ds; char buf[256]; - GetDlgItemText(hwnd, id, buf, 256); +#if 0 + GetDlgItemTextA(hwnd, id, buf, 256); +#else + control = TestFindControl(hwnd, id); + if (control == NULL) { + Tcl_SetObjResult(interp, + Tcl_ObjPrintf("Could not find control with id %d", id)); + return TCL_ERROR; + } + buf[0] = 0; + SendMessageA(control, WM_GETTEXT, (WPARAM)sizeof(buf), + (LPARAM) buf); +#endif Tcl_ExternalToUtfDString(NULL, buf, -1, &ds); Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL); Tcl_DStringFree(&ds); @@ -333,34 +377,40 @@ TestwineventCmd( } case WM_SETTEXT: { Tcl_DString ds; - BOOL result; - Tcl_UtfToExternalDString(NULL, argv[4], -1, &ds); - result = SetDlgItemText(hwnd, id, Tcl_DStringValue(&ds)); + control = TestFindControl(hwnd, id); + if (control == NULL) { + Tcl_SetObjResult(interp, + Tcl_ObjPrintf("Could not find control with id %d", id)); + return TCL_ERROR; + } + Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[4]), -1, &ds); + result = SendMessageA(control, WM_SETTEXT, 0, + (LPARAM) Tcl_DStringValue(&ds)); Tcl_DStringFree(&ds); if (result == 0) { - Tcl_SetResult(interp, "failed to send text to dialog: ", TCL_STATIC); - AppendSystemError(interp, GetLastError()); - return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to send text to dialog: ", -1)); + AppendSystemError(interp, GetLastError()); + return TCL_ERROR; } break; } case WM_COMMAND: { char buf[TCL_INTEGER_SPACE]; - if (argc < 5) { + if (objc < 5) { wParam = MAKEWPARAM(id, 0); lParam = (LPARAM)child; } - sprintf(buf, "%d", (int) SendMessage(hwnd, message, wParam, lParam)); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + sprintf(buf, "%d", (int) SendMessageA(hwnd, message, wParam, lParam)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); break; } default: { char buf[TCL_INTEGER_SPACE]; sprintf(buf, "%d", - (int) SendDlgItemMessage(hwnd, id, message, wParam, lParam)); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + (int) SendDlgItemMessageA(hwnd, id, message, wParam, lParam)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); break; } } @@ -385,18 +435,48 @@ TestfindwindowObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { - const char *title = NULL, *class = NULL; + const TCHAR *title = NULL, *class = NULL; + Tcl_DString titleString, classString; HWND hwnd = NULL; int r = TCL_OK; + DWORD myPid; + + Tcl_DStringInit(&classString); + Tcl_DStringInit(&titleString); if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "title ?class?"); return TCL_ERROR; } - title = Tcl_GetString(objv[1]); - if (objc == 3) - class = Tcl_GetString(objv[2]); - hwnd = FindWindowA(class, title); + + title = Tcl_WinUtfToTChar(Tcl_GetString(objv[1]), -1, &titleString); + if (objc == 3) { + class = Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString); + } + if (title[0] == 0) + title = NULL; +#if 0 + hwnd = FindWindow(class, title); +#else + /* We want find a window the belongs to us and not some other process */ + hwnd = NULL; + myPid = GetCurrentProcessId(); + while (1) { + DWORD pid, tid; + hwnd = FindWindowEx(NULL, hwnd, class, title); + if (hwnd == NULL) + break; + tid = GetWindowThreadProcessId(hwnd, &pid); + if (tid == 0) { + /* Window has gone */ + hwnd = NULL; + break; + } + if (pid == myPid) + break; /* Found it */ + } + +#endif if (hwnd == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to find window: ", -1)); @@ -405,7 +485,11 @@ TestfindwindowObjCmd( } else { Tcl_SetObjResult(interp, Tcl_NewLongObj(PTR2INT(hwnd))); } + + Tcl_DStringFree(&titleString); + Tcl_DStringFree(&classString); return r; + } static BOOL CALLBACK @@ -427,10 +511,11 @@ TestgetwindowinfoObjCmd( Tcl_Obj *const objv[]) { long hwnd; - Tcl_Obj *resObj = NULL, *classObj = NULL, *textObj = NULL; + Tcl_Obj *dictObj = NULL, *classObj = NULL, *textObj = NULL; Tcl_Obj *childrenObj = NULL; - char buf[512]; - int cch, cchBuf = tkWinProcs->useWide ? 256 : 512; + TCHAR buf[512]; + int cch, cchBuf = 256; + Tcl_DString ds; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "hwnd"); @@ -440,46 +525,37 @@ TestgetwindowinfoObjCmd( if (Tcl_GetLongFromObj(interp, objv[1], &hwnd) != TCL_OK) return TCL_ERROR; - if (tkWinProcs->useWide) { - cch = GetClassNameW(INT2PTR(hwnd), (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)); - classObj = Tcl_NewUnicodeObj((LPWSTR)buf, cch); - } else { - cch = GetClassNameA(INT2PTR(hwnd), (LPSTR)buf, sizeof(buf)); - classObj = Tcl_NewStringObj((LPSTR)buf, cch); - } + cch = GetClassName(INT2PTR(hwnd), buf, cchBuf); if (cch == 0) { - Tcl_SetResult(interp, "failed to get class name: ", TCL_STATIC); + Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to get class name: ", -1)); AppendSystemError(interp, GetLastError()); return TCL_ERROR; + } else { + Tcl_DString ds; + Tcl_WinTCharToUtf(buf, -1, &ds); + classObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); } - resObj = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, resObj, Tcl_NewStringObj("class", -1)); - Tcl_ListObjAppendElement(interp, resObj, classObj); + dictObj = Tcl_NewDictObj(); + Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("class", 5), classObj); + Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("id", 2), + Tcl_NewLongObj(GetWindowLongA(INT2PTR(hwnd), GWL_ID))); - Tcl_ListObjAppendElement(interp, resObj, Tcl_NewStringObj("id", -1)); - Tcl_ListObjAppendElement(interp, resObj, - Tcl_NewLongObj(GetWindowLong(INT2PTR(hwnd), GWL_ID))); - - cch = tkWinProcs->getWindowText(INT2PTR(hwnd), (LPTSTR)buf, cchBuf); - if (tkWinProcs->useWide) { - textObj = Tcl_NewUnicodeObj((LPCWSTR)buf, cch); - } else { - textObj = Tcl_NewStringObj((LPCSTR)buf, cch); - } + cch = GetWindowText(INT2PTR(hwnd), (LPTSTR)buf, cchBuf); + Tcl_WinTCharToUtf(buf, cch * sizeof (WCHAR), &ds); + textObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); - Tcl_ListObjAppendElement(interp, resObj, Tcl_NewStringObj("text", -1)); - Tcl_ListObjAppendElement(interp, resObj, textObj); - Tcl_ListObjAppendElement(interp, resObj, Tcl_NewStringObj("parent", -1)); - Tcl_ListObjAppendElement(interp, resObj, - Tcl_NewLongObj(PTR2INT(GetParent(INT2PTR(hwnd))))); + Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("text", 4), textObj); + Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("parent", 6), + Tcl_NewLongObj(PTR2INT(GetParent((INT2PTR(hwnd)))))); childrenObj = Tcl_NewListObj(0, NULL); EnumChildWindows(INT2PTR(hwnd), EnumChildrenProc, (LPARAM)childrenObj); - Tcl_ListObjAppendElement(interp, resObj, Tcl_NewStringObj("children", -1)); - Tcl_ListObjAppendElement(interp, resObj, childrenObj); + Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("children", -1), childrenObj); - Tcl_SetObjResult(interp, resObj); + Tcl_SetObjResult(interp, dictObj); return TCL_OK; } @@ -494,7 +570,7 @@ TestwinlocaleObjCmd( Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewIntObj((int)GetSystemDefaultLCID())); + Tcl_SetObjResult(interp, Tcl_NewIntObj((int)GetThreadLocale())); return TCL_OK; } |