From a0426df76aa736ba2d618441232d72e4ba38a380 Mon Sep 17 00:00:00 2001 From: ashok Date: Sat, 20 Sep 2014 03:17:35 +0000 Subject: Convert native paths returned from file dialogs to Tcl canonical paths. --- tests/winDialog.test | 56 ++++++++++++++++++++++++++++++++--------- win/tkWinDialog.c | 14 ++++++++--- win/tkWinTest.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 119 insertions(+), 21 deletions(-) diff --git a/tests/winDialog.test b/tests/winDialog.test index 8aa9ac3..357349e 100644 --- a/tests/winDialog.test +++ b/tests/winDialog.test @@ -22,11 +22,30 @@ testConstraint english [expr { && (([testwinlocale] & 0xff) == 9) }] -proc start {arg} { +proc start {widgetcommand args} { set ::tk_dialog 0 set ::iter_after 0 - after 1 $arg + # On newer versions of Windows, we need to find the dialog window + # based on the title + if {[llength $args]} { + set ::dialogtitle [lindex $args 0] + set ::dialogclass "#32770" + if {$::dialogtitle eq ""} { + switch $widgetcommand { + tk_getOpenFile { + set ::dialogtitle Open + } + tk_getSaveFile { + set ::dialogtitle "Save As" + } + tk_chooseDirectory { + set ::dialogtitle "Select Folder" + } + } + } + } + after 1 $widgetcommand } proc then {cmd} { @@ -34,19 +53,32 @@ proc then {cmd} { set ::dialogresult {} set ::testfont {} - afterbody + after 100 afterbody vwait ::dialogresult return $::dialogresult } proc afterbody {} { - if {$::tk_dialog == 0} { - if {[incr ::iter_after] > 30} { - set ::dialogresult ">30 iterations waiting on tk_dialog" + # On Vista and later, using the new file dialogs we have to find + # the window using its title as tk_dialog will not be set at the C level + if {$::dialogtitle ne "" && [string match 6.* $::tcl_platform(osVersion)]} { + if {[catch {testfindwindow "" $::dialogclass} ::tk_dialog]} { + if {[incr ::iter_after] > 10} { + set ::dialogresult ">30 iterations waiting on tk_dialog" + return + } + after 150 {afterbody} + return + } + } else { + if {$::tk_dialog == 0} { + if {[incr ::iter_after] > 30} { + set ::dialogresult ">30 iterations waiting on tk_dialog" + return + } + after 150 {afterbody} return } - after 150 {afterbody} - return } uplevel #0 {set dialogresult [eval $command]} } @@ -205,7 +237,7 @@ test winDialog-5.2 {GetFileName: one argument} -constraints { test winDialog-5.3 {GetFileName: many arguments} -constraints { nt testwinevent } -body { - start {tk_getOpenFile -initialdir c:/ -parent . -title test -initialfile foo} + start {tk_getOpenFile -initialdir c:/ -parent . -title test -initialfile foo} test then { Click cancel } @@ -218,7 +250,7 @@ test winDialog-5.4 {GetFileName: Tcl_GetIndexFromObj() != TCL_OK} -constraints { test winDialog-5.5 {GetFileName: Tcl_GetIndexFromObj() == TCL_OK} -constraints { nt testwinevent } -body { - start {tk_getOpenFile -title bar} + start {tk_getOpenFile -title bar} bar then { Click cancel } @@ -235,10 +267,10 @@ test winDialog-5.7 {GetFileName: extension begins with .} -constraints { # string++; # } - start {set x [tk_getSaveFile -defaultextension .foo -title Save]} + start {set x [tk_getSaveFile -defaultextension .foo -title Save]} Save set msg {} then { - if {[catch {SetText 0x47C bar} msg]} { + if {[catch {SetText 0x3e9 bar} msg]} { Click cancel } else { Click ok diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index 3130cf2..67f0df4 100644 --- a/win/tkWinDialog.c +++ b/win/tkWinDialog.c @@ -1387,8 +1387,13 @@ static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr, hr = itemIf->lpVtbl->GetDisplayName(itemIf, SIGDN_FILESYSPATH, &wstr); if (SUCCEEDED(hr)) { - Tcl_ListObjAppendElement(interp, multiObj, - Tcl_NewUnicodeObj(wstr, -1)); + Tcl_DString fnds; + ConvertExternalFilename(wstr, &fnds); + CoTaskMemFree(wstr); + Tcl_ListObjAppendElement( + interp, multiObj, + Tcl_NewStringObj(Tcl_DStringValue(&fnds), + Tcl_DStringLength(&fnds))); } itemIf->lpVtbl->Release(itemIf); if (FAILED(hr)) @@ -1408,7 +1413,10 @@ static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr, hr = resultIf->lpVtbl->GetDisplayName(resultIf, SIGDN_FILESYSPATH, &wstr); if (SUCCEEDED(hr)) { - resultObj = Tcl_NewUnicodeObj(wstr, -1); + Tcl_DString fnds; + ConvertExternalFilename(wstr, &fnds); + resultObj = Tcl_NewStringObj(Tcl_DStringValue(&fnds), + Tcl_DStringLength(&fnds)); CoTaskMemFree(wstr); } resultIf->lpVtbl->Release(resultIf); diff --git a/win/tkWinTest.c b/win/tkWinTest.c index 9fa956c..2c38d71 100644 --- a/win/tkWinTest.c +++ b/win/tkWinTest.c @@ -79,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; +} + + /* *---------------------------------------------------------------------- * @@ -244,11 +280,13 @@ TestwineventObjCmd( { 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"}, @@ -302,6 +340,7 @@ TestwineventObjCmd( return TCL_ERROR; } } + message = TkFindStateNum(NULL, NULL, messageMap, Tcl_GetString(objv[3])); wParam = 0; lParam = 0; @@ -318,7 +357,19 @@ TestwineventObjCmd( Tcl_DString ds; char 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); @@ -326,15 +377,21 @@ TestwineventObjCmd( } case WM_SETTEXT: { Tcl_DString ds; - BOOL result; + 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 = SetDlgItemTextA(hwnd, id, Tcl_DStringValue(&ds)); + result = SendMessageA(control, WM_SETTEXT, 0, + (LPARAM) Tcl_DStringValue(&ds)); Tcl_DStringFree(&ds); if (result == 0) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to send text to dialog: ", -1)); - 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; } @@ -395,7 +452,8 @@ TestfindwindowObjCmd( if (objc == 3) { class = Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString); } - + if (title[0] == 0) + title = NULL; hwnd = FindWindow(class, title); if (hwnd == NULL) { -- cgit v0.12