diff --git a/Bin/TkinterDesigner.dll b/Bin/TkinterDesigner.dll deleted file mode 100644 index 5c8d58c..0000000 Binary files a/Bin/TkinterDesigner.dll and /dev/null differ diff --git a/Bin/TkinterDesigner.exp b/Bin/TkinterDesigner.exp deleted file mode 100644 index 03a1231..0000000 Binary files a/Bin/TkinterDesigner.exp and /dev/null differ diff --git a/Bin/TkinterDesigner.lib b/Bin/TkinterDesigner.lib deleted file mode 100644 index 36a1995..0000000 Binary files a/Bin/TkinterDesigner.lib and /dev/null differ diff --git a/Bin/Vb6_SP6_Fix_for_Win7_and_Upper.exe b/Bin/Vb6_SP6_Fix_for_Win7_and_Upper.exe deleted file mode 100644 index 32e642f..0000000 Binary files a/Bin/Vb6_SP6_Fix_for_Win7_and_Upper.exe and /dev/null differ diff --git a/Bin/Vb6_SP6_Fix_for_Win7_and_Upper.txt b/Bin/Vb6_SP6_Fix_for_Win7_and_Upper.txt deleted file mode 100644 index fca320d..0000000 --- a/Bin/Vb6_SP6_Fix_for_Win7_and_Upper.txt +++ /dev/null @@ -1,4 +0,0 @@ -因WINDOWS 7/8/10对VB6兼容性不好,正常情况下要对VB6关闭视觉效果,否则拖放控件会很卡, -一跳一跳的,此补丁为网友在VB6 SP6的基础上修改而来,确认你安装的是VB6 SP6后,将 -Vb6_SP6_Fix_for_Win7_and_Upper.exe改名为vb6.exe,覆盖原文件,则可以正常使用VB6, -不用关闭视觉效果,拖放控件不飘不卡。 diff --git a/Bin/regtlib.exe b/Bin/regtlib.exe deleted file mode 100644 index 1577948..0000000 Binary files a/Bin/regtlib.exe and /dev/null differ diff --git a/Common.bas b/Common.bas index cd388ef..d4a1472 100644 --- a/Common.bas +++ b/Common.bas @@ -1,7 +1,7 @@ Attribute VB_Name = "Common" Option Explicit -Public VBE As VBE +Public VbeInst As VBE Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long @@ -66,6 +66,12 @@ Public g_Comps() As Object ' Public g_bUnicodePrefixU As Boolean '是否在UNICODE字符串前加前缀u Public g_PythonExe As String '用于GUI预览,保存python.exe全路径 +Public g_AppVerString As String + +Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hWnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long +Public Const OFFICIAL_SITE As String = "https://github.com/cdhigh/Vb6Tkinter" +Public Const OFFICIAL_RELEASES As String = "https://github.com/cdhigh/Vb6Tkinter/releases" +Public Const OFFICIAL_UPDATE_INFO As String = "https://api.github.com/repos/cdhigh/Vb6Tkinter/releases" 'PYTHON中UNICODE字符串前缀的处理函数,如果字符串中存在双字节字符,则根据选项增加适当的前缀 '否则,只是简单的增加单引号,即使空串也增加一对单引号 @@ -403,3 +409,74 @@ Public Sub SortWidgets(ByRef aCompsSorted() As Object, ByVal cnt As Long) Next End Sub + +'将版本号字符串前面和后面非数字部分都删除掉,比如:"v1.6.8 test" 将返回 "1.6.8" +Private Function purifyVerStr(txt As String) As String + Dim maxCnt As Integer, idx As Integer, startIdx As Integer, endIdx As Integer + Dim ch As String + txt = Trim(txt) + maxCnt = Len(txt) + startIdx = 1 + endIdx = maxCnt + '开头部分 + For idx = 1 To maxCnt + ch = Mid(txt, idx, 1) + If (ch >= "0") And (ch <= "9") Then + startIdx = idx + Exit For + End If + Next + '结尾部分 + For idx = maxCnt To 1 Step -1 + ch = Mid(txt, idx, 1) + If (ch >= "0") And (ch <= "9") Then + endIdx = idx + Exit For + End If + Next + + If startIdx <= endIdx Then + purifyVerStr = Mid(txt, startIdx, endIdx - startIdx + 1) + Else + purifyVerStr = "" + End If +End Function + +'比较两个版本号,确定新版本号是否比老版本号更新, +'版本号格式为:1.1.0 +Public Function isVersionNewerThan(newVer As String, currVer As String) As Boolean + Dim newArr As Variant, currArr As Variant, idx As Integer, maxCnt As Integer + Dim vn As Integer, vc As Integer + newVer = purifyVerStr(newVer) + currVer = purifyVerStr(currVer) + If Len(newVer) = 0 Or Len(currVer) = 0 Then + isVersionNewerThan = False + Exit Function + End If + + newArr = Split(newVer, ".") + currArr = Split(currVer, ".") + maxCnt = UBound(newArr) + If UBound(currArr) < maxCnt Then '两个数组最小的一个 + maxCnt = UBound(currArr) + End If + + For idx = 0 To maxCnt + vn = Val(newArr(idx)) + vc = Val(currArr(idx)) + If vn > vc Then + isVersionNewerThan = True + Exit Function + ElseIf vn < vc Then + isVersionNewerThan = False + Exit Function + End If + Next + + '如果前面都一样,则长的一个为大 + If UBound(newArr) > UBound(currArr) Then + isVersionNewerThan = True + Else + isVersionNewerThan = False + End If +End Function diff --git a/Connect.cls b/Connect.cls index c598371..2bdcd0c 100644 --- a/Connect.cls +++ b/Connect.cls @@ -11,7 +11,7 @@ Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = True Attribute VB_PredeclaredId = False Attribute VB_Exposed = True -Attribute VB_Description = "TkinterDesigner" +Attribute VB_Description = "Vb6Tkinter" Option Explicit Private mcbMenuItem As Office.CommandBarControl @@ -41,7 +41,7 @@ Private Sub IDTExtensibility_OnStartupComplete(custom() As Variant) End Sub Private Sub IDTExtensibility_OnConnection(ByVal VBInst As Object, ByVal ConnectMode As VBIDE.vbext_ConnectMode, ByVal AddInInst As VBIDE.AddIn, custom() As Variant) - Set Common.VBE = VBInst + Set VbeInst = VBInst If ConnectMode = vbext_cm_Startup Or ConnectMode = vbext_cm_AfterStartup Then AddToMenu (App.Title & "(&T)") @@ -84,14 +84,15 @@ End Sub '在外接程序菜单下增加一个菜单项 Private Sub AddToMenu(sCaption As String) Dim cbMenuCommandBar As Office.CommandBarControl - Dim cbMenu + Dim cbMenu As Variant On Error Resume Next '察看能否找到外接程序菜单 - Set cbMenu = VBE.CommandBars("Add-Ins") + Set cbMenu = VbeInst.CommandBars("外接程序") + If cbMenu Is Nothing Then Set cbMenu = VbeInst.CommandBars("Add-Ins") If cbMenu Is Nothing Then Exit Sub - + '添加它到命令栏 Set cbMenuCommandBar = cbMenu.Controls.Add(msoControlButton) If cbMenuCommandBar Is Nothing Then Exit Sub @@ -101,9 +102,13 @@ Private Sub AddToMenu(sCaption As String) '设置标题 cbMenuCommandBar.Caption = sCaption + 'DoEvents + 'Clipboard.SetData LoadResPicture(101, vbResBitmap) + 'cbMenuCommandBar.PasteFace + 'DoEvents + Set mcbMenuItem = cbMenuCommandBar - Set MenuHandler = VBE.Events.CommandBarEvents(mcbMenuItem) - + Set MenuHandler = VbeInst.Events.CommandBarEvents(mcbMenuItem) End Sub '在工具栏增加一个图标 @@ -113,26 +118,27 @@ Private Sub AddToToolBox(sCaption As String) '察看能否找到标准工具栏 On Error Resume Next - Set cbStandard = VBE.CommandBars("标准") - If Err.Number <> 0 Then Set cbStandard = VBE.CommandBars("Standard") - + Set cbStandard = VbeInst.CommandBars("标准") + If cbStandard Is Nothing Then Set cbStandard = VbeInst.CommandBars("Standard") + If cbStandard Is Nothing Then Set cbStandard = VbeInst.CommandBars(2) If cbStandard Is Nothing Then Exit Sub Err.Clear - On Error GoTo AddToAddInToolboxErr + 'On Error GoTo AddToAddInToolboxErr + On Error Resume Next '添加它到工具栏 Set cbToolboxCommandBar = cbStandard.Controls.Add(msoControlButton, , , cbStandard.Controls.Count) cbToolboxCommandBar.BeginGroup = True cbToolboxCommandBar.Caption = sCaption Set mcbToolBoxItem = cbToolboxCommandBar + DoEvents Clipboard.SetData LoadResPicture(101, vbResBitmap) cbToolboxCommandBar.PasteFace + DoEvents - Set ToolBoxHandler = VBE.Events.CommandBarEvents(mcbToolBoxItem) - -AddToAddInToolboxErr: - + Set ToolBoxHandler = VbeInst.Events.CommandBarEvents(mcbToolBoxItem) +'AddToAddInToolboxErr: End Sub Private Sub MenuHandler_Click(ByVal CommandBarControl As Object, handled As Boolean, CancelDefault As Boolean) diff --git a/Language.lng b/Language.lng deleted file mode 100644 index fc3ff8e..0000000 --- a/Language.lng +++ /dev/null @@ -1,396 +0,0 @@ -[简体中文(&C)] -CmdQuit=退出(&Q) -CmdRefsFormsList=刷新窗体列表(&R) -CmdSaveToFile=保存到文件(&F) -CmdCopyToClipboard=拷贝到剪贴板(&C) -CmdGenCode=生成代码(&G) -lblCurPrjName=当前工程: -mnuFile=文件(&F) -mnuRefreshForms=刷新窗体列表(&R) -mnuGenCode=生成代码(&G) -mnuAddProperty=增加一个自定义属性(&P) -mnuQuit=退出(&Q) -mnuOptions=选项(&O) -mnuOopCode=生成面向对象代码(&P) -mnuV2andV3Code=生成Python 2.x/3.x兼容代码(&C) -mnuUseTtk=启用TTK主题库(&T) -mnuRelPos=使用相对坐标(&R) -mnuUnicodePrefixU=Unicode字符串增加前缀u(&U) -mnuPythonExe=设置Python.exe位置(&E)... -mnuTools=工具(&T) -mnuPreview=界面预览(&P) -mnuEncodeAFile=编码磁盘文件为Base64字符串(&B) -mnuLanguage=Language(&L) -mnuSaveToFile=保存代码到文件(&F) -mnuSaveAll=保存全部内容(&A) -mnuSaveMainOnly=仅保存main()函数(&M) -mnuSaveUiOnly=仅保存界面生成类(&G) -mnuCopyToClipboard=拷贝代码到剪贴板(&C) -mnuCopyToClipAll=拷贝全部内容(&A) -mnuCopyToClipMainOnly=仅拷贝main()函数(&M) -mnuCopyToClipUiOnly=仅拷贝界面生成类(&G) -frmOption=配置 -lblPythonExe=Python主文件 -cmdOptionOK=确定(&O) -cmdOptionApply=应用(&A) -cmdOptionCancel=取消(&C) -frmEncodeAFile=编码文件为Base64字符串 -lblSourceToEncode=源文件 -lblCharsPerLine=每行字符数 -cmdBase64It=编码(&E) -cmdSaveBase64Result=保存(&S) -cmdCancelEncode=退出(&Q) -l_staTips=属性解析窗口,在有些属性状态下可以双击变大。 -l_staSrl=注意:仅保存那些被选择(选择框被打勾)的配置项。 -l_staComps=控件列表窗口,列出对应窗体上所有控件名和控件类型。 -l_staFrms=窗体列表,程序中支持多个设计窗口。 -l_staCopyCode=拷贝代码到剪贴板,可以选择拷贝全部还是仅拷贝界面生成部分。 -l_staRestoreCfg=仅恢复那些同名保存的控件配置项,新增的控件不受影响。 -l_staCmdGenCode=全部的控件属性都配置完成后,使用这个按钮生成Python代码。 -l_staQuit=直接退出! -l_staRefsFrms=刷新窗体和控件,如果插件运行后修改了窗体和控件,请刷新后再重新生成代码。 -l_staCmdSaveFile=如果必要,可以选择代码保存到文件(UTF-8带BOM格式)。 -l_staLstCfg=属性列表窗口,双击属性值或按F2键可以编辑,程序只生成对应前面打钩的属性的代码。 -l_staTxtCode=代码预览窗口,双击可以放大。如果需要,也可以直接在这里修改代码。 -l_ProForAddAttr=请输入属性和数值对,使用'属性=值'的形式,比如:x=20 。\n注意Python是大小写敏感的。 -l_msgCtlNotSupport=当前暂不支持'{0}'控件 (名字:{1})\n\n程序将不生成此控件的代码。\n\n'确定' : 继续。\n'取消' : 忽略同类型的控件,不再提醒。 -l_msgGetAttrOfFrmFailed=获取窗体属性失败,对应VB工程已经关闭?\n请重新刷新窗体列表或重新打开工程再试。\n现在重新刷新窗体列表吗? -l_msgFrameNotSupportInAbs=绝对坐标布局不支持Frame控件,请改用相对坐标或去掉Frame控件。 -l_msgCtlsSupported=支持控件列表: -l_msgNoMain=代码中找不到main()函数! -l_msgNoClsUi=代码中找不到Application_ui类! -l_msgFileNotExist={0} 文件不存在! -l_msgCantCancelTTK=窗体中有部分控件仅在TTK库中存在,不能取消TTK选项。 -l_msgMusthasVar=OptionMenu(ComboBox)必须要选择variable属性,现在将不生成OptionMenu的代码。 -l_msgReadFileError=读取文件{0}出错。 -l_msgWriteFileError=写文件{0}出错。 -l_msgFailedScaleMode=查找到窗体'{0}',但是ScaleMode={1},程序仅支持模式1/2/3。 -l_msgFileFieldNull=文件不能为空! -l_msgCreateTempFileFailed=创建临时文件失败! -l_msgCreateDictionaryFailed=创建Scripting.Dictionary对象失败,程序无法继续执行。\n请确认scrrun.dll是否存在! -l_msgChangePrefixU=改变UNICODE字符串的前缀选项需要全部刷新控件状态。\n继续吗? -l_msgFileTooBig=文件太大,速度会很慢,暂时不支持! -l_msgEncodeResultTooLong=转换后的编码字符串太长,文本框装不下,请选择一个文件直接用于保存结果! -l_msgCodeTooBig=生成的代码规模太大,文本框装不下,请选择一个文件直接用于保存结果! -l_fdOpen=请选择文件: -l_fdSave=将文件保存到: -l_cmtClsApp=#这个类实现具体的事件处理回调函数。界面生成代码在Application_ui中。 -l_cmtClsUi=#这个类仅实现界面生成功能,具体事件处理代码在子类Application中。 -l_cmtgComps=#所有控件和控件绑定变量引用字典,使用这个字典是为了方便在其他函数中引用所有控件。 -l_cmtTodoCols=#TODO在这里添加标题列表,第一列固定为树形显示 -l_cmtTodoDisCols=#TODO在这里添加显示标题列表,第一列固定为树形显示 -l_cmtTodoNBFrame=#TODO,请在各个Frame(代表各选项卡内容)里面添加需要的控件。 -l_cmtTreeviewSample=#以下四行为示例代码,请删掉写自己的项目代码 -l_TipText=控件的显示文本。 -l_TipXY=控件的放置位置。 -l_TipWidth=控件的宽度。 -l_TipHeight=控件的高度。 -l_TipRelXY=控件相对于父窗口的位置,值范围为0-1。 -l_TipRelWidth=控件相对于父窗口的宽度,值范围为0-1。 -l_TipRelHeight=控件相对于父窗口的高度,值范围为0-1。 -l_TipFg=前景色,请使用单引号或双引号括起来,格式为#RGB或red等单词,比如'#FF0000'。 -l_TipBg=背景色,请使用单引号或双引号括起来,格式为#RGB或red等单词,比如'#FF0000'。 -l_TipBd=边框宽度,单位为像素。 -l_TipAnchor=控件内文字的对齐方式,请使用单引号或双引号括起来,可能值为:\n'w'|'n'|'s'|'e'|'nw'|'ne'|'sw'|'se'|'center'. -l_TipRelief=外观效果,可选值有:FLAT, GROOVE, RAISED, RIDGE, SOLID, SUNKEN。 -l_TipOverRelief=鼠标悬停在控件上的外观效果,可选值有:FLAT, GROOVE, RAISED, RIDGE, SOLID, SUNKEN。 -l_TipTakeFocus=是否允许TAB选择控件。设置为1为允许,设置为0则TAB跳过此控件。 -l_TipUnderline=在哪个字母上添加下划线,做为快捷方式的表示,第一個字母索引為0。 -l_TipPadding=控件内部额外间距,一般不需要设置。如果需要设置,控件内部额外间距,一般不需要设置。如果需要设置,请提供'左 上 右 下'四个值,或三个值'左 上 右'(下=上),两个值'左 上'(右=左,下=上),一个值'左'(上=下=右=左)。 -l_TipOrient=控件方向类型,全大写不用括号,小写则需要括号括起来,可选值有:'horizontal', 'vertical'。 -l_TipCursor=鼠标指针。可以使用tk内置的指针,或在文件名前增加一个@符号使用外部指针,如'@custom.cur'。 -l_TipVariable=控件值和一个变量绑定,通过变量可以获取或设置控件的值。\n如果需要这个特性,这个属性设置为变量名。 -l_TipTextVariable=将显示文本和一个变量绑定,变量变化时控件的显示文本将改变,反正亦然。\n如果需要这个特性,这个属性设置为变量名。 -l_TipCommand=触发事件处理函数。触发不带参数。也可以设置为top.destroy等tk方法或使用lambda函数。 -l_TipBindCommand=使用bind()绑定的事件处理列表,绑定多个则使用逗号分隔(比如:,,)。\n双击文本框查看详情。 -l_TipFont=文字字体属性。是一个元组。\n元组前两个元素为:字体名,字体大小,之后的几个元素可选:'bold', 'italic', 'underline', 'overstrike'。 -l_TipXScrlCmd=水平滚动事件处理,如果需要水平滚动,设置这个值为水平滚动条的set方法。 -l_TipYScrlCmd=上下滚动事件处理,如果需要上下滚动,设置这个值为垂直滚动条的set方法。 -l_TipXScrlIncre=水平每次滚动增量,默认为0,可以随意滚动,可以设置为一个大于零的整数。 -l_TipYScrlIncre=上下每次滚动增量,默认为0,可以随意滚动,可以设置为一个大于零的整数。 -l_TipScrlregion=控件滚动范围(可以理解为控件实际上有多大),格式:(w,n,e,s)。\n如果要设置Canvas可以滚动,则必须设置此属性。 -l_TipConfine=是否限制在scrollregion内滚动,默认为true。 -l_TipHlbg=控件失去焦点时边框的颜色。 -l_TipHlColor=控件选中状态时边框的颜色。 -l_TipHlThickness=焦点状态边框宽度,默认为1。 -l_TipSltbg=控件内选中项的背景色。 -l_TipSltbd=控件内选中项的边框宽度。 -l_TipSltfg=控件内选中项的前景色。 -l_TipState=控件状态,可选值有:'normal', 'disabled' -l_TipDisplayRows=指定要显示行数。 -l_TipStateHasRO=控件状态,可选值有:'normal', 'readonly', 'disabled' -l_TipValues=控件的下拉文本列表,此属性值设置为变量名(为一个列表),如果需要运行时添加和删除下拉文本列表,需要重新使用组合框的configure方法设置values属性。 -l_TipJustify=控制(多行)字符的对齐方式,可能值为:'left','right','center' -l_TipPostCmd=每次下拉列表打开前调用此回调函数。 -l_TipExportSelection=默认为False,为True时连接至Window Manager selection。 -l_TipShow=设置用来作为代替显示的字符,比如设置为*则为密码输入框,要用单引号或双引号括起来。 -l_TipWrapLen=多少个字符后自动换行。用于多行显示。 -l_TipLblAnchor=边框上文字的位置,默认为左上角。\n可选值有:'nw','wn','en','n','ne','w','e','ws','es','sw','s','se' -l_TipListVariable=控件的列表项变量,这里设置为变量名。 -l_TipActiveStyle=选中的行的样式,可选值有:'underline','dotbox', 'none' -l_TipSelectMode=选择模式,可选值有:SINGLE, BROWSE, EXTENDED, MULTIPLE -l_TipTearOff=菜单是否可以变成单独窗口,设置为1(默认)时,菜单第一项为虚线,用户点击这条虚线会将菜单弹出为一个单独的窗口,就像PYTHON默认编辑器IDLE一样。 -l_TipPostCmdMenu=每次用户点击菜单弹出时调用的回调函数。 -l_TipAcceleratorMenu=全局快捷键定义。 -l_TipProgresLen=进度条长轴的长度。 -l_TipProgresMode=控件模式,可选值:'determinate'(默认)和'indeterminate','determinate'就是普通进度显示模式,'indeterminate'有一个小指示块移动,用于提示用户程序正在处理中。 -l_TipMaximum=设置最大值,默认100。 -l_TipProgresValue=设置当前值,可以不设置,使用variable变量设置和读取。 -l_TipIndicatorOn=是否显示文本坐标的标识,可选值有:0,1 -l_TipValue=控件的表示值,一组控件的每一个控件的值不能相同。 -l_TipVariableRadio=相同一组单选框则设置为同一个variable变量,每个控件的value设置为不同值,通过设置variable变量的实际值来选择哪个单选框选中或通过variable变量的实际值可以知道用户选择了哪个单选框。 -l_TipFrom=设置最小值。 -l_TipTo=设置最大值。 -l_TipResolution=设置步距值。 -l_TipShowValue=是否将当前值以文字形式显示在上方,默认为1。 -l_TipDigits=控制浮点数的显示位数。 -l_TipSliderLen=滑动指示块的长度,默认为30像素。 -l_TipSliderRelief=滑动指示块的外观效果,可选值有:FLAT, GROOVE, RAISED, RIDGE, SOLID, SUNKEN。 -l_TipTickInterval=滑动槽中是否显示周期定位点,默认不显示,如果要显示,这个值设置为多少步长一个点,可以为小数。 -l_TipJump=设置为0(默认值)则每次滚动条数值变化就调用一次回调函数,设置为1则等鼠标松开后才调一次回调函数。 -l_TipActiveRelief=设置鼠标指针移动在滚动条上时的式样,可选值:FLAT, GROOVE, RAISED, RIDGE, SOLID, SUNKEN。 -l_TipWrapMode=换行模式,CHAR(默认)为可以在任何一个字符后换行,WORD为在单词后换行,NONE为不换行(则需要提供滚动条)。 -l_TipSpacing1=每行和前一行之间的行间距。 -l_TipSpacing2=超过文本框宽度的行在每个绕行之间的行间距。 -l_TipSpacing3=每行和后一行之间的行间距。 -l_TipColumns=一个列表变量名,指定控件列数和列标题。不设置此参数则没有标题,并且只显示一列。 -l_TipDisplayColumns=一个列表变量名,指定显示列数、标题和顺序,或可设置为'#all'显示所有'columns'属性中设置的所有列。 -l_TipSelectModeTV=项目选择模式,需要括号括起来,可选值:'extended'(默认)可选多个项目, 'browse'只能选择一个项目 or 'none' 不显示 -l_TipShowTV=控件显示配置。需要括号括起来,默认为'tree headings',表示第一列显示树,显示标题行。配置为'tree'则不显示标题行。 -l_TipSide=状态栏放置位置\n可选值有:TOP,BOTTOM,留空则可以放置在任何位置。 -l_TipPanelWidths=一个元组或列表,状态栏各窗格的宽度(字符数),最后一个窗格总是占满剩余空间,不需要列出。 -l_TipFrmTitle=窗体的标题。 -l_TipFrmGeometry=窗体的大小(宽x高),单位为像素。 -l_TipFrmLeft=窗体的初始位置坐标,单位为像素。 -l_TipFrmTop=窗体的初始位置坐标,单位为像素。 -l_TipFrmResizable=用户是否可以改变窗体的大小。可选值:1/0。 -l_TipFrmState=窗体启动时的状态。'iconic':最小化,'zoomed':最大化,'normal':正常状态。 -l_TipFrmTopmost=窗体是否置顶。 -l_TipFrmAlpha=窗体透明度。取值范围为0-1,0为全透明,1为不透明。 -l_TipFrmIcon=图标文件名,支持ico,gif,ppm,pgm格式,省略路径名则在当前VB窗体目录下查找,建议icon文件放在py文件同一目录下。 -l_TipFrmIconEmbedding=是否将图标文件转换为base64编码嵌入源代码,仅支持GIF格式嵌入。 -l_TipFrmProtocol=处理窗口消息,比如设置为'WM_DELETE_WINDOW'则处理窗口关闭事件,如果要拦截多个消息,请使用逗号分隔,比如'WM_DELETE_WINDOW,WM_SAVE' -l_TipFrmPosition=窗体启动时位置。 -l_TipUnknown=未知属性 -l_TipHasNoControl=目前窗体上没有任何控件,请先在窗体上添加控件。 -l_TipTooltip=鼠标悬停在控件上弹出的信息提示文本。 -l_DescButton=按钮对象,对应到Tkinter的Button控件。 -l_DescCanvas=画布对象,对应到Tkinter的Canvas控件。 -l_DescCheckbutton=多选框对象,对应到Tkinter的Checkbutton控件。 -l_DescCombobox=文本组合框对象,对应到tkinter.ttk的Combobox控件。 -l_DescEntry=单行文本输入框对象,对应到Tkinter的Entry控件。 -l_DescLabel=标签条对象,对应到Tkinter的Label控件。 -l_DescLabelFrame=框架对象,可以作为其他控件的容器,对应到Tkinter的LabelFrame或Frame控件。 -l_DescListbox=列表框对象,对应到Tkinter的Listbox控件。 -l_DescMenu=主菜单对象,对应到Tkinter的Menu控件。 -l_DescMenuItem=菜单项对象,每一个对象对应到Tkinter的Menu响应命令的项目。 -l_DescNotebook=选项卡对象,对应到Tkinter.ttk的Notebook控件。 -l_DescNotebookTab=选项卡的页对象,对应到Tkinter.ttk的Notebook控件里面的每一页,没有可设置的属性。 -l_DescOptionmenu=组合框对象,需要预先设置要显示的字符列表,对应到Tkinter的Optionmenu控件。 -l_DescProgressbar=进度条对象,对应到Tkinter.ttk扩展库的ProgressBar控件,需要启用TTK扩展。 -l_DescRadiobutton=单选按钮对象,在Tkinter中单选按钮的分组方法和VB有区别,同一组单选按钮的variable属性要设置为同一个变量,对应到Tkinter的Radiobutton控件。 -l_DescScale=滑动条对象,对应到Tkinter的Scale控件。 -l_DescScrollbar=滚动条对象,对应到Tkinter的Scrollbar控件。 -l_DescText=多行文本框对象,对应到Tkinter的Text控件。 -l_DescTreeview=树形控件对象,对应到Tkinter.ttk扩展库的Treeview控件,需要启用TTK扩展。 -l_DescStatusbar=状态栏对象,为自定义控件,可设置多个窗格,直接使用控件的set()方法设置状态提示。 -l_DescForm=窗体对象,设置顶层窗口的属性。 -l_DescSeparator=分隔条对象,对应到Tkinter.ttk的Separator控件,只支持水平线和垂直线。 -[English(&E)] -CmdQuit=Quit(&Q) -CmdRefsFormsList=Refresh Forms(&R) -CmdSaveToFile=Save to File(&F) -CmdCopyToClipboard=Copy to Clipboard(&C) -CmdGenCode=Generate Code(&G) -lblCurPrjName=Current Project: -mnuFile=File(&F) -mnuRefreshForms=Refresh Forms(&R) -mnuGenCode=Generate Code(&G) -mnuAddProperty=Add One Property(&P) -mnuQuit=Quit(&Q) -mnuOptions=Options(&O) -mnuOopCode=Generate OOP Code(&P) -mnuV2andV3Code=Compatible Code for Python 2.x/3.x(&C) -mnuUseTtk=Use TTK Themed Library(&T) -mnuRelPos=Use Relative Position(&R) -mnuUnicodePrefixU=Add A Prefix 'u' to Unicode String(&U) -mnuPythonExe=Set diretory of python.exe(&E)... -mnuTools=Tools(&T) -mnuPreview=Preview(&P) -mnuEncodeAFile=Encode File to Base64(&B) -mnuLanguage=Languages(&L) -mnuSaveToFile=Save Code to File(&F) -mnuSaveAll=Save All Code(&A) -mnuSaveMainOnly=Save main() Only(&M) -mnuSaveUiOnly=Save Class UI Only(&G) -mnuCopyToClipboard=Copy Code To Clipboard(&C) -mnuCopyToClipAll=Copy All Code(&A) -mnuCopyToClipMainOnly=Copy main() Only(&M) -mnuCopyToClipUiOnly=Copy Class UI Only(&G) -frmOption=Config -lblPythonExe=Python EXE -cmdOptionOK=Ok(&O) -cmdOptionApply=Apply(&A) -cmdOptionCancel=Cancel(&C) -frmEncodeAFile=Encode File to Base64 -lblSourceToEncode=Source File -lblCharsPerLine=Chars Per Line -cmdBase64It=Encode(&E) -cmdSaveBase64Result=Save(&S) -cmdCancelEncode=Exit(&Q) -l_staTips=Tips of properties. -l_staSrl=Save Config to file. -l_staComps=List of controls. -l_staFrms=List of forms. -l_staCopyCode=Copy code to clipboard. -l_staRestoreCfg=Restore config of Controls from file. -l_staCmdGenCode=Generate python code after confirm properties of controls. -l_staQuit=Quit! -l_staRefsFrms=Resfresh list of forms and controls. -l_staCmdSaveFile=Save code to file (format utf-8 with BOM). -l_staLstCfg=List of properties of control, F2/Return/DblClick to modify a property. -l_staTxtCode=Preview python code here, DblClick to zoom out/in. -l_ProForAddAttr=Please input string format as 'Property=Value', for example x=20.\nCase sensitive. -l_msgCtlNotSupport=The addin not support '{0}' control (Name:{1}).\n\nIt will not be processed.\n\n'Ok' to continue.\n'Cancel' for ignoring controls of same type. -l_msgGetAttrOfFrmFailed=Failed in getting property of the form, please reopen the vb project and retry.\nRefresh list of forms now? -l_msgFrameNotSupportInAbs=The control 'Frame' is not support when menu 'Use Relative Position' unchecked. -l_msgCtlsSupported=Controls supported: -l_msgNoMain=Function 'main()' no founded in code! -l_msgNoClsUi=Class 'Application_ui' no founded in code! -l_msgFileNotExist=File '{0}' not exist! -l_msgCantCancelTTK=Can't uncheck the menu 'Use TTK Themed Library' for has some widgets specified in TTK. -l_msgMusthasVar='variable' is obligatory for OptionMenu(ComboBox), will not generate code for OptionMenu({0}) now. -l_msgReadFileError=Error in Reading File {0}. -l_msgWriteFileError=Error in Writing File {0}. -l_msgFailedScaleMode=Found form'{0}', but its ScaleMode={1}, now can only support mode 1/2/3. -l_msgFileFieldNull=File can't be null. -l_msgCreateTempFileFailed=Failed in creating a temp file. -l_msgCreateDictionaryFailed=Create 'Scripting.Dictionary' failed.\nplease confirm 'scrrun.dll' exists or not. -l_msgChangePrefixU=Change the prefix of UNICODE string will refresh all widgets of the form, \nContinue? -l_msgFileTooBig=File is too big, app will take too much time to convert, can't continue now! -l_msgEncodeResultTooLong=Size of encoded string is too big to load into TextBox, please choose a file to save it. -l_msgCodeTooBig=Size of generated code is too big to load into TextBox, please choose a file to save it. -l_fdOpen=Please Choose file: -l_fdSave=Save file to: -l_cmtClsApp=#The class will implement callback function for events and your logical code. -l_cmtClsUi=#The class will create all widgets for UI. -l_cmtgComps=#Global dictionary of widgets for using in others functions. -l_cmtTodoCols=#TODO Add list of titles here, first column fixed for tree view. -l_cmtTodoDisCols=#TODO Add list of titles will be displayed, first column fixed for tree view. -l_cmtTodoNBFrame=#TODO Add widgets in frame hereinafter. -l_cmtTreeviewSample=#The four lines of sample code hereinafter. -l_TipText=Text displayed on the widget. -l_TipXY=Position of widget. -l_TipWidth=Width of widget. -l_TipHeight=Height of widget. -l_TipRelXY=Relative position of widget. value between 0 and 1. -l_TipRelWidth=Relative width of widget. value between 0 and 1. -l_TipRelHeight=Relative height of widget. value between 0 and 1. -l_TipFg=Normal foreground (text) color. format is #RRGGBB, for example : #FF0000. -l_TipBg=Normal background color. format is #RRGGBB, for example : #FF0000. -l_TipBd=Width of the border around the outside of widget. -l_TipAnchor=Controls where the text is positioned.\nThey are: 'w'|'n'|'s'|'e'|'nw'|'ne'|'sw'|'se'|'center'. -l_TipRelief=Refers to certain simulated 3-D effects around the outside of widget.\nThey are: FLAT, GROOVE, RAISED, RIDGE, SOLID, SUNKEN. -l_TipOverRelief=The relief style to be used while the mouse is on the widget.\nThey are: FLAT, GROOVE, RAISED, RIDGE, SOLID, SUNKEN. -l_TipTakeFocus=Normally, keyboard focus does visit widget.\nSet to zero to prevent focus from visiting the widget. -l_TipUnderline=If nonnegative, the corresponding text character will be underlined, index of first char is 0. -l_TipPadding=Specifies the amount of extra space to add around the outside of the widget. -l_TipOrient=One of 'horizontal' or 'vertical'. Specifies the orientation of the widget. -l_TipCursor=cursor of widget. Choose a curor embeddin in tk, or add a prefix '@' in a filename to use a custom cursor, for example '@custom.cur'. -l_TipVariable=The control variable that tracks the current state/value of the widget. -l_TipTextVariable=The control variable that tracks the current text displayed of the widget. -l_TipCommand=A procedure to be called when the widget is activated or clicked. can be set to 'top.destroy' and other method of tk or lambda function too. -l_TipBindCommand=Used to attach events binding to a widget. for example:,,. -l_TipFont=Font to be used for widget. is a tuple, the first two elements is name, size, the following are some of 'bold', 'italic', 'underline', 'overstrike'. -l_TipXScrlCmd=If widget is scrollable, this attribute should be the .set() method of the horizontal scrollbar. -l_TipYScrlCmd=If widget is scrollable, this attribute should be the .set() method of the vertical scrollbar. -l_TipXScrlIncre=Default is 0, If set a positive value, widget can be positioned only on multiples of that distance. -l_TipYScrlIncre=Default is 0, If set a positive value, widget can be positioned only on multiples of that distance. -l_TipScrlregion=A tuple (w, n, e, s) that defnes over how large an area the canvas can be scrolled. -l_TipConfine=If true (the default), the canvas cannot be scrolled outside of the scrollregion. -l_TipHlbg=Color of the focus highlight when the widget does not have focus. -l_TipHlColor=Color shown in the focus highlight. -l_TipHlThickness=Thickness of the focus highlight. The default value is 1. -l_TipSltbg=The background color to use displaying selected items. -l_TipSltbd=The width of the border to use around selected items. -l_TipSltfg=The foreground color to use displaying selected items. -l_TipState=State of the widget. They are 'normal', 'disabled' -l_TipStateHasRO=State of the widget. They are 'normal', 'readonly', 'disabled' -l_TipDisplayRows=How many rows be displayed. -l_TipValues=List of text of widget. This attribute set to a name of variable (type list). -l_TipJustify=How the (Multiline) text are justified: 'left','right','center' -l_TipPostCmd=A procedure that is called immediately before displaying the values -l_TipExportSelection=If set to True, the widget selection is linked to the Window Manager selection -l_TipShow=To make a 'password' entry that echoes each character as an asterisk, set to '*'. -l_TipWrapLen=You can limit the number of characters in each line by setting this option to the desired number -l_TipLblAnchor=Specifies the position of the label on the widget's border.\nThey are 'nw','wn','en','n','ne','w','e','ws','es','sw','s','se' -l_TipListVariable=A StringVar that is connected to the complete list of values in the listbox. -l_TipActiveStyle=Specifies the appearance of the active line. They are 'underline','dotbox', 'none' -l_TipSelectMode=Determines how many items can be selected. They are: SINGLE, BROWSE, EXTENDED, MULTIPLE -l_TipTearOff=Determines menu can be torn off or not. -l_TipPostCmdMenu=A procedure will be called every time someone brings up this menu. -l_TipAcceleratorMenu=To display an keystroke combination on the right side of a menu choice, -l_TipProgresLen=Specifies the length of the long axis of the progress bar. -l_TipProgresMode=One of 'determinate' or 'indeterminate'.\n 'determinate' represents the amount of work completed. -l_TipMaximum=A number specifying the maximum value. Defaults to 100. -l_TipProgresValue=The current value of the progress bar. -l_TipIndicatorOn=Specifies if displays its indicator or not. -l_TipValue=Value of widget. -l_TipVariableRadio=The control variable that this radiobutton shares with the other radiobuttons in the group. -l_TipFrom=A float or integer value that defines one end of the scale's range. -l_TipTo=A float or integer value that defines one end of the scale's range. -l_TipResolution=The smallest increment of the scale's value. -l_TipShowValue=The value of the scale is displayed in text form by the slider when set to 1(default). -l_TipDigits=How many digits to use for display. -l_TipSliderLen=Normally the slider is 30 pixels along the length of the scale. You can change the value. -l_TipSliderRelief=Relief of the slider. They are: FLAT, GROOVE, RAISED, RIDGE, SOLID, SUNKEN -l_TipTickInterval=To display periodic scale values, set this option to a number, and ticks will be displayed on multiples of that value. -l_TipJump=Set to 1, the callback isn't called until the user releases the mouse button. -l_TipActiveRelief=To display the slider with a different relief style when the mouse is over the slider. -l_TipWrapMode=Controls the display of lines that are too wide.\n'CHAR':will be broken at any character.\n'WORD': will break the line after the last word that will fit.\n'NONE':provide a horizontal scrollbar. -l_TipSpacing1=Specifies how much extra vertical space is put above each line of text. -l_TipSpacing2=Specifies how much extra vertical space to add between displayed lines of text when a logical line wraps. -l_TipSpacing3=Specifies how much extra vertical space is added below each line of text. -l_TipColumns=A list of column identifiers, specifying the number of columns and their names. -l_TipDisplayColumns=A list of column identifiers specifying which data columns are displayed and the order in which they appear, or the string '#all'. -l_TipSelectModeTV=Controls how the built-in class bindings manage the selection.\nThey are:'extended','browse','none' -l_TipShowTV=Specifying which elements of the tree to display.\nDefault is 'tree headings'.\nSet to 'tree' hide the heading. -l_TipSide=Position of statusbar. they are TOP,BOTTOM, or blank. -l_TipPanelWidths=A tuple or list of number of chars of panels. -l_TipFrmTitle=Title of Form. -l_TipFrmGeometry=Geometry of Form(width x height), unit is pixel. -l_TipFrmLeft=Coordinate of Form on startup, unit is pixel. -l_TipFrmTop=Coordinate of Form on startup, unit is pixel. -l_TipFrmResizable=Form is resizable or not, They are 1/0. -l_TipFrmState=window state of Form on startup. 'iconic':minimized, 'zoomed':maximized, 'normal': normal. -l_TipFrmTopmost=Specifies whether this is a topmost window (displays above all other windows). -l_TipFrmAlpha=Specifies the alpha transparency level of the toplevel. It accepts a value from 0.0 (fully transparent) to 1.0 (opaque). -l_TipFrmIcon=Icon file of Form, supports ico,gif,ppm,pgm. -l_TipFrmIconEmbedding=Is icon embedding in source code or not, suports gif only. -l_TipFrmProtocol=Process window events, for example 'WM_DELETE_WINDOW', separate events using comma like 'WM_DELETE_WINDOW,WM_SAVE'. -l_TipFrmPosition=The Startup position of Window. -l_TipUnknown=Unknown Attribute -l_TipHasNoControl=Has no control on Form, please add at least one control on it. -l_TipTooltip=The tooltip text of the widget. -l_DescButton=Button widget. -l_DescCanvas=Canvas widget. -l_DescCheckbutton=Checkbutton widget. -l_DescCombobox=Combobox widget. TTK needed. -l_DescEntry=Entry widget. -l_DescLabel=Label widget. -l_DescLabelFrame=LabelFrame or Frame widget. -l_DescListbox=Listbox widget. -l_DescMenu=Menu widget. -l_DescMenuItem=Menu item in Menu widget. -l_DescNotebook=Notebook widget. TTK needed. -l_DescNotebookTab=Tab of widget Notebook. TTK needed. -l_DescOptionmenu=Optionmenu widget. -l_DescProgressbar=ProgressBar widget. TTK needed. -l_DescRadiobutton=Radiobutton widget. -l_DescScale=Scale widget. -l_DescScrollbar=Scrollbar widget. -l_DescText=Text widget. -l_DescTreeview=Treeview widget. TTK needed. -l_DescStatusbar=Statusbar widget. it has method set(), text(), panelwidth(), clear() -l_DescForm=Main Form. -l_DescSeparator=Separator widget. It only supports horizontal or vertical style. diff --git a/MainForm.frm b/MainForm.frm index b1f0761..cf6c75a 100644 --- a/MainForm.frm +++ b/MainForm.frm @@ -1,7 +1,7 @@ VERSION 5.00 Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.2#0"; "MSCOMCTL.OCX" Begin VB.Form FrmMain - Caption = "Tkinter Designer - cdhigh@sohu.com" + Caption = "Vb6Tkinter https://github.com/cdhigh" ClientHeight = 8130 ClientLeft = 45 ClientTop = 675 @@ -44,7 +44,7 @@ Begin VB.Form FrmMain Visible = 0 'False Width = 1095 End - Begin TkinterDesigner.xpcmdbutton CmdRefsFormsList + Begin Vb6Tkinter.xpcmdbutton CmdRefsFormsList Height = 495 Left = 120 TabIndex = 0 @@ -128,7 +128,7 @@ Begin VB.Form FrmMain Top = 1200 Width = 2415 End - Begin TkinterDesigner.GridOcx LstCfg + Begin Vb6Tkinter.GridOcx LstCfg Height = 6855 Left = 2640 TabIndex = 8 @@ -164,7 +164,7 @@ Begin VB.Form FrmMain Top = 840 Width = 4095 End - Begin TkinterDesigner.xpcmdbutton CmdGenCode + Begin Vb6Tkinter.xpcmdbutton CmdGenCode Height = 495 Left = 2760 TabIndex = 1 @@ -183,7 +183,7 @@ Begin VB.Form FrmMain Strikethrough = 0 'False EndProperty End - Begin TkinterDesigner.xpcmdbutton CmdCopyToClipboard + Begin Vb6Tkinter.xpcmdbutton CmdCopyToClipboard Height = 495 Left = 5340 TabIndex = 2 @@ -202,7 +202,7 @@ Begin VB.Form FrmMain Strikethrough = 0 'False EndProperty End - Begin TkinterDesigner.xpcmdbutton CmdSaveToFile + Begin Vb6Tkinter.xpcmdbutton CmdSaveToFile Height = 495 Left = 7950 TabIndex = 3 @@ -221,7 +221,7 @@ Begin VB.Form FrmMain Strikethrough = 0 'False EndProperty End - Begin TkinterDesigner.xpcmdbutton CmdQuit + Begin Vb6Tkinter.xpcmdbutton CmdQuit Height = 495 Left = 10560 TabIndex = 4 @@ -332,6 +332,15 @@ Begin VB.Form FrmMain Begin VB.Menu mnuEncodeAFile Caption = "Encode File to Base64(&B)" End + Begin VB.Menu mnuSeparator6 + Caption = "-" + End + Begin VB.Menu mnuCheckUpdate + Caption = "Check Update(&U)" + End + Begin VB.Menu mnuAbout + Caption = "About(&A)" + End End Begin VB.Menu mnuLanguage Caption = "Language(&L)" @@ -368,8 +377,9 @@ Private Declare Function GetSystemDefaultLCID Lib "kernel32" () As Long Private Sub Form_Load() Dim s As String - ReDim g_Comps(0) As Object + + g_AppVerString = App.Major & "." & App.Minor & IIf(App.Revision > 0, "." & App.Revision, "") g_DefaultFontName = "" m_HasCommonDialog = False m_TxtCodeExpanded = False @@ -391,14 +401,14 @@ Private Sub Form_Load() LstCfg.SelectBackColor = &HFCC597 'vbHighlight LstCfg.Redraw = True - m_BriefCaption = "Tkinter Designer - cdhigh@sohu.com - v" & App.Major & "." & App.Minor & IIf(App.Revision > 0, "." & App.Revision, "") + m_BriefCaption = "Vb6Tkinter v" & g_AppVerString #If DebugVer Then m_BriefCaption = m_BriefCaption & " [Debug Mode] " #End If Me.Caption = m_BriefCaption mnuOopCode.Checked = GetSetting(App.Title, "Settings", "OopCode", "1") = "1" - mnuV2andV3Code.Checked = GetSetting(App.Title, "Settings", "V2andV3Code", "1") = "1" + mnuV2andV3Code.Checked = GetSetting(App.Title, "Settings", "V2andV3Code", "0") = "1" mnuUseTtk.Checked = GetSetting(App.Title, "Settings", "UseTtk", "1") = "1" mnuRelPos.Checked = GetSetting(App.Title, "Settings", "RelPos", "1") = "1" mnuUnicodePrefixU.Checked = GetSetting(App.Title, "Settings", "UnicodePrefix", "0") = "1" @@ -495,7 +505,7 @@ Private Sub cmbFrms_Click() '查找到对应的窗体引用 Set m_curFrm = Nothing If Len(cmbFrms.Text) Then - For Each frm In VBE.ActiveVBProject.VBComponents + For Each frm In VbeInst.ActiveVBProject.VBComponents If frm.Type = vbext_ct_VBForm And frm.Name = cmbFrms.Text Then Set m_curFrm = frm Exit For @@ -992,24 +1002,25 @@ Private Sub CmdGenCode_Click() '在输出代码前先更新一下当前显示的数据 UpdateCfgtoCls LstComps.ListIndex - strHead.Append "#!/usr/bin/env python" - strHead.Append "#-*- coding:utf-8 -*-" & vbCrLf - strHead.Append "import os, sys" - If OutOnlyV3 Then '输出仅针对PYTHON 3.X的代码 + strHead.Append "#!/usr/bin/env python3" + strHead.Append "#-*- coding:utf-8 -*-" & vbCrLf + strHead.Append "import os, sys" strHead.Append "from tkinter import *" strHead.Append "from tkinter.font import Font" If usettk Then strHead.Append "from tkinter.ttk import *" strHead.Append "#Usage:showinfo/warning/error,askquestion/okcancel/yesno/retrycancel" strHead.Append "from tkinter.messagebox import *" - strHead.Append "#Usage:f=tkFileDialog.askopenfilename(initialdir='E:/Python')" - strHead.Append IIf(m_HasCommonDialog, "", "#") & "import tkinter.filedialog as tkFileDialog" - strHead.Append IIf(m_HasCommonDialog, "", "#") & "import tkinter.simpledialog as tkSimpleDialog #askstring()" + strHead.Append IIf(m_HasCommonDialog, "", "#") & "from tkinter import filedialog #.askopenfilename()" + strHead.Append IIf(m_HasCommonDialog, "", "#") & "from tkinter import simpledialog #.askstring()" If m_HasCommonDialog Then - strHead.Append "import tkinter.colorchooser as tkColorChooser #askcolor()" + strHead.Append "from tkinter import colorchooser #.askcolor()" End If strHead.Append vbCrLf Else + strHead.Append "#!/usr/bin/env python" + strHead.Append "#-*- coding:utf-8 -*-" & vbCrLf + strHead.Append "import os, sys" strHead.Append "if sys.version_info[0] == 2:" strHead.Append " from Tkinter import *" strHead.Append " from tkFont import Font" @@ -1042,7 +1053,7 @@ Private Sub CmdGenCode_Click() '如果存在状态栏控件,则先输出状态栏控件的类定义 For i = 1 To UBound(g_Comps) '0固定为窗体,不用判断 If TypeName(g_Comps(i)) = "clsStatusbar" Then - strHead.Append g_Comps(i).WidgetCode() + strHead.Append g_Comps(i).WidgetCode(OutOnlyV3) Exit For End If Next @@ -1060,12 +1071,20 @@ Private Sub CmdGenCode_Click() strCmd.Append "class Application(Application_ui):" strCmd.Append " " & L("l_cmtClsApp", "#The class will implement callback function for events and your logical code.") strCmd.Append " def __init__(self, master=None):" - strCmd.Append " Application_ui.__init__(self, master)" & vbCrLf + If OutOnlyV3 Then + strCmd.Append " super().__init__(master)" & vbCrLf + Else + strCmd.Append " Application_ui.__init__(self, master)" & vbCrLf + End If strOut.Append "class Application_ui(Frame):" strOut.Append " " & L("l_cmtClsUi", "#The class will create all widgets for UI.") strOut.Append " def __init__(self, master=None):" - strOut.Append " Frame.__init__(self, master)" + If OutOnlyV3 Then + strOut.Append " super().__init__(master)" + Else + strOut.Append " Frame.__init__(self, master)" + End If g_Comps(0).toString strOut, strCmd, OutRelPos, OutOOP, usettk 'g_Comps(0)固定是Form strOut.Append " self.createWidgets()" & vbCrLf strOut.Append " def createWidgets(self):" @@ -1222,7 +1241,7 @@ Private Sub CmdRefsFormsList_Click() LstComps.Clear LstCfg.Clear - If VBE.ActiveVBProject Is Nothing Then + If VbeInst.ActiveVBProject Is Nothing Then CmdGenCode.Enabled = False CmdCopyToClipboard.Enabled = False CmdSaveToFile.Enabled = False @@ -1233,10 +1252,10 @@ Private Sub CmdRefsFormsList_Click() Exit Sub End If - Me.Caption = m_BriefCaption & " [" & VBE.ActiveVBProject.Name & "]" + Me.Caption = m_BriefCaption & " [" & VbeInst.ActiveVBProject.Name & "]" '查找工程中所有的窗体,全部添加到组合框供选择输出 - For Each frm In VBE.ActiveVBProject.VBComponents + For Each frm In VbeInst.ActiveVBProject.VBComponents If frm.Type = vbext_ct_VBForm Then nScaleMode = frm.Properties("ScaleMode") If nScaleMode <> vbTwips And nScaleMode <> vbPoints And nScaleMode <> vbPixels Then @@ -1462,6 +1481,10 @@ Private Sub UpdateCfgtoCls(idx As Long) End Sub +Private Sub mnuAbout_Click() + frmAbout.Show vbModal +End Sub + '增加自定义配置 Private Sub mnuAddProperty_Click() @@ -1536,10 +1559,48 @@ Private Sub mnuCopyToClipUiOnly_Click() End Sub +'使用base64编码文件 Private Sub mnuEncodeAFile_Click() frmEncodeAFile.Show vbModal End Sub +'检查更新 +Private Sub mnuCheckUpdate_Click() + Dim data As String, ver As String, currVer As String, skipVer As String + Dim info As Variant, lastestVerInfo As Variant + data = HttpGetResponse(OFFICIAL_UPDATE_INFO) + If Len(data) = 0 Then + MsgBox L("l_msgFetchVerInfoFail", "Error fetching version update information."), vbInformation + Exit Sub + End If + data = Trim(data) + ParseJSONString2 data, info + If IsArray(info) = False Then + MsgBox L("l_msgParseVerInfoFail", "Unable to parse the version information."), vbInformation + Exit Sub + End If + If IsObject(info(0)) = False Then + MsgBox L("l_msgParseVerInfoFail", "Unable to parse the version information."), vbInformation + Exit Sub + End If + + On Error GoTo verErrHandler: + Set lastestVerInfo = info(0) '第一个元素为最新版本,为一个字典对象 + ver = lastestVerInfo("tag_name") '作者在github上发布版本时使用tag_name保存版本号 + If Len(ver) > 0 Then + currVer = g_AppVerString + If isVersionNewerThan(ver, currVer) Then + Load frmNewVer + frmNewVer.lblInfo.Caption = L("l_msgFoundNewVersion", "Found new version: ") & ver + frmNewVer.lblInfo.Tag = ver + frmNewVer.Show vbModal + Exit Sub + End If + End If +verErrHandler: + MsgBox L("l_msgYourVerIsLastest", "Your version is lastest."), vbInformation +End Sub + Private Sub mnuFile_Click() mnuGenCode.Enabled = LstComps.ListCount > 0 End Sub @@ -1867,7 +1928,7 @@ End Sub Private Sub stabar_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single) If Shift = vbCtrlMask Then Clipboard.Clear - Clipboard.SetText "https://github.com/cdhigh/tkinter-designer" + Clipboard.SetText OFFICIAL_SITE End If End Sub @@ -2003,8 +2064,8 @@ End Sub Private Sub TxtCode_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single) stabar.SimpleText = L("l_staTxtCode", "Preview python code here, DblClick to zoom out/in.") End Sub - + Private Sub stabar_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single) - stabar.SimpleText = "https://github.com/cdhigh/tkinter-designer ['Ctrl+Click' copy url to clipboard]" + stabar.SimpleText = OFFICIAL_SITE & " ['Ctrl+Click' copy url to clipboard]" End Sub diff --git a/MultiLanguage.bas b/MultiLanguage.bas index 012004b..4d05f2f 100644 --- a/MultiLanguage.bas +++ b/MultiLanguage.bas @@ -1,6 +1,6 @@ Attribute VB_Name = "MultiLanguage" '多语言支持模块 -'语言文件: Language.lng +'语言文件: Vb6Tkinter.lng ' 文件格式: ' [语言名称] ' 控件名=字符串 @@ -9,11 +9,11 @@ Attribute VB_Name = "MultiLanguage" 'ChangeLanguage(语言名) : 切换控件显示语言,这个函数也会一次性缓存对应语种的所有字符串到内存 'L(名字,默认字符串) : 获取指定字符串 'L_F(名字,默认字符串,其他参数) : 类似Python的{0}{1}格式化字符串 -'GetAllLanguageName() : Language.lng中所有语种的名称,字符串数组 +'GetAllLanguageName() : Vb6Tkinter.lng中所有语种的名称,字符串数组 Option Explicit Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long -Private Const LanguageFile = "Language.lng" +Private Const LanguageFile = "Vb6Tkinter.lng" Private m_Lng As New Dictionary '对应语种的{名称,字符串}字典 Public Const DEF_LNG = "English(&E)" @@ -27,12 +27,12 @@ End Function '支持类似python的{0}{1}格式化字符串,从{0}开始编号,不支持{}形式(没有数字索引) Public Function L_F(sKey As String, ByVal sDefault As String, ParamArray v() As Variant) As String - Dim s As String, i As Long + Dim s As String, I As Long s = L(sKey, sDefault) - For i = 0 To UBound(v) - s = Replace(s, "{" & i & "}", CStr(v(i))) + For I = 0 To UBound(v) + s = Replace(s, "{" & I & "}", CStr(v(I))) Next L_F = s @@ -54,26 +54,26 @@ Public Function GetAllLanguageName() As String() End Function Public Function ChangeLanguage(Language As String) As Boolean - Dim i As Long, Ctrl As Control, s As String, ns As Long, sa() As String + Dim I As Long, Ctrl As Control, s As String, ns As Long, sa() As String '先缓存对应语种的语言字符串 s = Space(10000) ns = GetPrivateProfileString(Language, vbNullString, vbNullString, s, 10000, LngFile()) sa = Split(Trim(Replace(Left(s, ns), Chr(0) & Chr(0), "")), Chr(0)) m_Lng.RemoveAll - For i = 0 To UBound(sa) + For I = 0 To UBound(sa) s = Space(256) - ns = GetPrivateProfileString(Language, sa(i), "", s, 256, LngFile()) + ns = GetPrivateProfileString(Language, sa(I), "", s, 256, LngFile()) s = Trim(Replace(Replace(Left(s, ns), Chr(0), ""), "\n", vbCrLf)) - If Len(s) Then m_Lng.Add sa(i), s + If Len(s) Then m_Lng.Add sa(I), s Next '切换所有控件的语言 - For i = 0 To Forms.Count - 1 - For Each Ctrl In Forms(i).Controls + For I = 0 To Forms.Count - 1 + For Each Ctrl In Forms(I).Controls ChangeControlLanguage Ctrl, Language Next - Next i + Next I ChangeLanguage = ns > 0 diff --git a/Bin/Setup for TkinterDesigner.exe b/Patchs/Setup for Vb6Tkinter.exe similarity index 65% rename from Bin/Setup for TkinterDesigner.exe rename to Patchs/Setup for Vb6Tkinter.exe index 4111d3f..3f8b402 100644 Binary files a/Bin/Setup for TkinterDesigner.exe and b/Patchs/Setup for Vb6Tkinter.exe differ diff --git a/Bin/VB6_AppCompat(patcher for win10).zip b/Patchs/VB6_AppCompat(patcher for win10).zip similarity index 100% rename from Bin/VB6_AppCompat(patcher for win10).zip rename to Patchs/VB6_AppCompat(patcher for win10).zip diff --git a/Patchs/Vb6_SP6_Fix_for_Win7_and_Upper.zip b/Patchs/Vb6_SP6_Fix_for_Win7_and_Upper.zip new file mode 100644 index 0000000..9a98eab Binary files /dev/null and b/Patchs/Vb6_SP6_Fix_for_Win7_and_Upper.zip differ diff --git a/Bin/readme_for_win7_win10.txt b/Patchs/readme_for_win7_win10.txt similarity index 100% rename from Bin/readme_for_win7_win10.txt rename to Patchs/readme_for_win7_win10.txt diff --git a/Readme.md b/Readme.md index 3949811..007e636 100644 --- a/Readme.md +++ b/Readme.md @@ -1,125 +1,149 @@ -Readme of english version refers to [Readme_EN.md](https://github.com/cdhigh/tkinter-designer/blob/master/Readme_EN.md) --------------------------------- # 绠浠 -杩欐槸涓涓猇B6鐨凙DDIN锛堝鎺ョ▼搴忥級锛岀敤浜庝娇鐢╒B6寮鍙戝伐鍏风洿鎺ユ嫋鏀炬帶浠讹紝鐩存帴鍙鍖栧畬鎴怭ython鐨凾Kinter鐨凣UI甯冨眬鍜岃璁★紝鍙互鍦╒B鐣岄潰涓婅缃帶浠剁殑涓浜涘睘鎬э紝鏈缁堣嚜鍔ㄧ敓鎴愬繀瑕佺殑浠g爜锛堝寘鎷洖璋冨嚱鏁版鏋讹級锛屼唬鐮佺敓鎴愬悗浠呴渶瑕佸湪瀵瑰簲鐨勫洖璋冨嚱鏁颁腑澧炲姞鐩稿簲鐨勯昏緫鍔熻兘浠g爜鍗冲彲銆 -![Screenshot](https://raw.githubusercontent.com/cdhigh/tkinter-designer/master/Setup/Screenshots/TkinterDesigner_ScrPrnt.JPG) +杩欐槸涓涓猇B6鐨凙ddin锛堝鎺ョ▼搴忥級锛岀敤浜庝娇鐢╒B6寮鍙戝伐鍏风洿鎺ユ嫋鏀炬帶浠讹紝鐩存帴鍙鍖栧畬鎴怭ython鐨凾kinter鐨凣UI甯冨眬鍜岃璁★紝鍙互鍦╒B鐣岄潰涓婅缃帶浠剁殑澶ч儴鍒嗗睘鎬э紝鏈缁堣嚜鍔ㄧ敓鎴愬繀瑕佺殑浠g爜锛堝寘鎷洖璋冨嚱鏁版鏋讹級锛屼唬鐮佺敓鎴愬悗浠呴渶瑕佸湪瀵瑰簲鐨勫洖璋冨嚱鏁颁腑澧炲姞鐩稿簲鐨勯昏緫鍔熻兘浠g爜鍗冲彲銆 +![Screenshot](https://raw.githubusercontent.com/cdhigh/vb6tkinter/master/Setup/Screenshots/Vb6Tkinter_ScrPrnt.png) -杩欎釜宸ュ叿鏀寔缁濆ぇ閮ㄥ垎TKiner鎺т欢锛屽彲搴斾粯涓鑸珿UI鐨勯渶姹傘 +杩欎釜宸ュ叿鏀寔缁濆ぇ閮ㄥ垎Tkinter鎺т欢锛屽彲搴斾粯涓鑸珿UI鐨勯渶姹傘 锛堝垪琛ㄥ弬瑙佷笅闈㈢殑鎺т欢璇存槑锛夈 -# 閫傜敤瀵硅薄 -* 閫傜敤浜庡涔犱簡TKinter骞朵笉鎯冲お楹荤儲鎵嬪啓GUI鐢熸垚鍜屾帓鐗堜唬鐮侊紝涔熶笉鎯崇敤鍏朵粬绗笁鏂瑰伐鍏峰拰妗嗘灦姣斿wxPython/PyQt鐨勫悓瀛︺ + + +# 閫傜敤鐢ㄦ埛 +* 閫傜敤浜庡涔犱簡Tkinter骞朵笉鎯冲お楹荤儲鎵嬪啓GUI鐢熸垚鍜屾帓鐗堜唬鐮侊紝涔熶笉鎯崇敤鍏朵粬绗笁鏂瑰伐鍏峰拰妗嗘灦姣斿wxPython/PyQt鐨勫悓瀛︺ * 閫傜敤浜庣晫闈笉澶鏉傜殑灏忕▼搴忓紑鍙戯紝鐣岄潰澶嶆潅鐨勮繕鏄傜敤wxPython/PyQt绛夋鏋跺惂銆 -* 鍥犱负TKinter涓篜ython鏍囧噯搴擄紝浣跨敤TKinter瀹屾垚鐨凱ython绋嬪簭鍙互绉颁负"缁胯壊杞欢"锛屼笉闇瑕佺洰鏍囨満鍣ㄤ笂瀹夎wxPython/PyQt绛夋鏋讹紝鍙鏈塒ython鐨勬満鍣ㄥ氨鑳借繍琛屻傚嵆浣夸娇鐢╬yinstaller/cx_freeze绛夋墦鍖呮垚exe锛屾渶缁堟枃浠朵篃涓嶄細寰堝ぇ銆 -* 濡傛灉杞欢閫昏緫涓嶆槸寰堝鏉傦紝閫氬父涓涓*.py鎼炲畾锛屼笉鍍忓叾浠栦竴浜涜緟鍔╂鏋讹紝闇瑕佸嚑涓枃浠躲 +* 鍥犱负Tkinter涓篜ython鏍囧噯搴擄紝浣跨敤Tkinter瀹屾垚鐨凱ython绋嬪簭鍙互绉颁负"缁胯壊杞欢"锛屼笉闇瑕佺洰鏍囨満鍣ㄤ笂瀹夎wxPython/PyQt绛夋鏋讹紝鍙鏈塒ython鐨勬満鍣ㄥ氨鑳借繍琛屻傚嵆浣夸娇鐢╬yinstaller/cx_freeze绛夋墦鍖呮垚exe锛屾渶缁堟枃浠朵篃涓嶄細寰堝ぇ銆 +* 濡傛灉杞欢閫昏緫涓嶆槸寰堝鏉傦紝閫氬父涓涓 py 鏂囦欢鎼炲畾锛屼笉鍍忓叾浠栦竴浜涜緟鍔╂鏋讹紝闇瑕佸嚑涓枃浠躲 > 锛堝鏋滀笉甯屾湜py鐩存帴瑙i噴杩愯鏃跺脊鍑洪粦婕嗘紗鐨勫懡浠よ绐楀彛锛屽悗缂鍚嶈鏀逛负pyw锛 -# 浣跨敤鏂规硶绠浠 -1. 棣栧厛娉ㄥ唽姝ゆ彃浠讹紝鍙互浣跨敤鑷甫鐨勫畨瑁呯▼搴忥紝鎴栬嚜宸辨墜鍔ㄥ畬鎴愩 - 1. 杩愯regsvr32 /s diretory\TkinerDesigner.dll - 2. 鍦–:\Windows\VBADDIN.INI鐨勬[Add-Ins32]澧炲姞涓琛岋細 - `TkinterDesigner.Connect=3` -2. 鎵撳紑VB6锛屾柊寤轰竴涓爣鍑咵XE宸ョ▼锛屽湪绐椾綋涓婅璁¤嚜宸辩殑GUI甯冨眬锛岃繖涓伐浣滀及璁℃病鏈塚B鍩虹鐨勫悓瀛﹂兘鍙互瀹屾垚锛屽悓鏃跺彲浠ヨ缃浉搴旂殑鎺т欢灞炴с -3. 濡傛灉浣跨敤鑷甫瀹夎绋嬪簭瀹夎浜嗘彃浠讹紝鐜板湪VB鐨勫伐鍏锋潯涓婂簲璇ユ湁涓涓柊鍥炬爣锛堜竴鐗囨绾㈣壊缇芥瘺锛夛紝濡傛灉娌℃湁锛屽埌鑿滃崟"澶栨帴绋嬪簭"|"澶栨帴绋嬪簭绠$悊鍣"閲岄潰鍚姩Tkinter Designer锛孴kinter Designer鍥炬爣鍜岃彍鍗曞簲璇ヤ細鍑虹幇銆 +# 瀹夎 +鏈変袱涓柟寮忥紝鍙互浠婚変竴涓細 +1. 鏁村悎瀹夎鏂瑰紡锛 +鍦 涓嬭浇鏁村悎浜嗙簿绠鐗圴B6鐨勫畨瑁呭寘锛屽凡棰勫厛鎵撳ソ鍚勭琛ヤ竵锛屽弻鍑绘墽琛屽畨瑁呭嵆鍙紝涓嶉渶瑕佽繘琛屼笅闈㈢浜岃妭鐨勬搷浣溿 + +2. 鐙珛瀹夎鏂瑰紡锛 +2.1. 鍦 涓嬭浇鎻掍欢鍘嬬缉鍖咃紝瑙e帇鍒版煇涓洰褰曘 +2.2. 鍏堣嚜琛屽湪鍏朵粬缃戠珯涓嬭浇骞跺畨瑁匳B6锛屽彲浠ユ槸瀹屾暣鐗堟垨绮剧畝鐗 + 2.2.1. 濡傛灉鏄 Windows 7 鍙婁互涓婄増鏈, 鐢 Vb6_SP6_Fix_for_Win7.zip 涓殑 Vb6.exe 瑕嗙洊鍘熸潵鐨刅b6.exe + 2.2.2. 濡傛灉鏄 Windows 10 鍙婁互涓婄増鏈紝璇峰簲鐢 VB6_AppCompat 琛ヤ竵 +2.3. 娉ㄥ唽姝ゆ彃浠讹紝鍙互浣跨敤鑷甫鐨勬敞鍐屽伐鍏"Setup for Vb6Tkinter.exe"锛屾垨鑷繁鎵嬪姩瀹屾垚銆 + 2.3.1. 杩愯 `regsvr32 /s diretory\Vb6Tkinter.dll` + 2.3.2. 鍦–:\Windows\VBADDIN.INI鐨勬[Add-Ins32]澧炲姞涓琛岋細`Vb6Tkinter.Connect=3` + +3. 涓鏃︿綘瀹夎鍜屾敞鍐屽畬鎴愬悗锛屼互鍚庣殑鍗囩骇鍙互浠呬笅杞芥柊鐗堟湰鐨 Vb6Tkinter.dll/Vb6Tkinter.lng 瑕嗙洊鏃х殑鏂囦欢鍗冲彲銆 + + + + +# 浣跨敤鏂规硶绠浠 +1. 鎵撳紑VB6锛屾柊寤轰竴涓爣鍑咵XE宸ョ▼锛屽湪绐椾綋涓婅璁¤嚜宸辩殑GUI甯冨眬锛岃繖涓伐浣滀及璁℃病鏈塚B鍩虹鐨勫悓瀛﹂兘鍙互瀹屾垚锛屽悓鏃跺彲浠ヨ缃浉搴旂殑鎺т欢灞炴с + 濡傛灉涓嶅笇鏈涚獥浣撳ぇ灏忓彲鍙橈紝寤鸿鍦╒B6涓慨鏀圭獥浣撶殑BorderStyle灞炴т负"Fixed Single"鎴"Fixed Dialog"銆 + +2. 濡傛灉浣跨敤鑷甫瀹夎绋嬪簭瀹夎浜嗘彃浠讹紝鐜板湪VB鐨勫伐鍏锋潯涓婂簲璇ユ湁涓涓柊鍥炬爣锛堜竴鐗囨绾㈣壊缇芥瘺锛夛紝 + 濡傛灉娌℃湁锛屽埌鑿滃崟"澶栨帴绋嬪簭"|"澶栨帴绋嬪簭绠$悊鍣"閲岄潰鍚姩 Vb6Tkinter锛 Vb6Tkinter 鍥炬爣鍜岃彍鍗曞簲璇ヤ細鍑虹幇銆 -4. 鍚姩Tkinter Designer鍚庯紝鍏堟寜鈥滃埛鏂扮獥浣撳垪琛ㄢ濇寜閽紝鍒楀嚭褰撳墠宸ョ▼鐨勬墍鏈夌獥浣撳拰鎺т欢鍒楄〃銆 +3. 鍚姩Vb6Tkinter鍚庯紝鍏堟寜鈥滃埛鏂扮獥浣撳垪琛ㄢ濇寜閽紝鍒楀嚭褰撳墠宸ョ▼鐨勬墍鏈夌獥浣撳拰鎺т欢鍒楄〃銆 -5. 閫愪釜纭鍚勬帶浠剁殑杈撳嚭灞炴э紝鍦ㄨ杈撳嚭鐨勯夐」鍓嶆墦閽╋紝濡傛灉蹇呰锛屽彲浠ュ湪灞炴у垪琛ㄤ腑鍙屽嚮淇敼灞炴х殑鍊笺傦紙涓鑸儏鍐典笉闇瑕佸啀淇敼鎺т欢灞炴э級銆 - Tkinter Designer灏介噺鐨勫皢VB鎺т欢灞炴х炕璇戞垚Tkinter鎺т欢灞炴э紝姣斿瀛椾綋銆侀鑹层佸垵濮嬪笺佸瑙傘佺姸鎬佺瓑锛岀敋鑷冲寘鎷寜閽被鍜岃彍鍗曠殑蹇嵎閿缃瓑绛夈傚綋鐒朵簡锛屽鏋滈儴鍒嗗睘鎬ф病鏈夊搴斿叧绯荤殑锛岄渶瑕佸湪TkinterDesigner鐣岄潰涓婅缃 +4. 閫愪釜纭鍚勬帶浠剁殑杈撳嚭灞炴э紝鍦ㄨ杈撳嚭鐨勯夐」鍓嶆墦閽╋紝濡傛灉蹇呰锛屽彲浠ュ湪灞炴у垪琛ㄤ腑鍙屽嚮淇敼灞炴х殑鍊笺傦紙涓鑸儏鍐典笉闇瑕佸啀淇敼鎺т欢灞炴э級銆 + Vb6Tkinter灏介噺鐨勫皢VB鎺т欢灞炴х炕璇戞垚Tkinter鎺т欢灞炴э紝姣斿瀛椾綋銆侀鑹层佸垵濮嬪笺佸瑙傘佺姸鎬佺瓑锛岀敋鑷冲寘鎷寜閽被鍜岃彍鍗曠殑蹇嵎閿缃瓑绛夈傚綋鐒朵簡锛屽鏋滈儴鍒嗗睘鎬ф病鏈夊搴斿叧绯荤殑锛岄渶瑕佸湪Vb6Tkinter鐣岄潰涓婅缃 -6. 鎸夆滅敓鎴愪唬鐮佲濇寜閽垯鍦ㄤ唬鐮侀瑙堢獥鍙g敓鎴愪唬鐮侊紝鍙互鍙屽嚮浠g爜棰勮绐楀彛鏀惧ぇ闃呰锛屼篃鍙互鐩存帴淇敼浠g爜銆 +5. 鎸夆滅敓鎴愪唬鐮佲濇寜閽垯鍦ㄤ唬鐮侀瑙堢獥鍙g敓鎴愪唬鐮侊紝鍙互鍙屽嚮浠g爜棰勮绐楀彛鏀惧ぇ闃呰锛屼篃鍙互鐩存帴淇敼浠g爜銆 -7. 纭瀹屾垚鍚庡彲浠ュ皢浠g爜鎷疯礉鍒板壀璐存澘鎴栦繚瀛樺埌鏂囦欢銆 +6. 纭瀹屾垚鍚庡彲浠ュ皢浠g爜鎷疯礉鍒板壀璐存澘鎴栦繚瀛樺埌鏂囦欢銆 甯冨眬鍙互浣跨敤鐧惧垎姣斿畾浣嶏紙鐩稿瀹氫綅锛夋垨缁濆鍧愭爣瀹氫綅锛堟寜鍍忕礌瀹氫綅锛夛紝鐧惧垎姣斿畾浣嶄负鏈変竴涓ソ澶勶紝涓荤晫闈㈠ぇ灏忓彉鍖栧悗锛屾帶浠朵篃鍙互鐩稿鍙樺寲澶у皬銆傚鏋滀笉甯屾湜涓荤晫闈㈠ぇ灏忓彉鍖栧悗鎺т欢璺熼殢鍙樺寲锛屽彲浠ラ夋嫨缁濆鍧愭爣瀹氫綅銆 娉細濡傛灉淇敼浜嗕互鍓嶈璁$殑鐣岄潰锛屽彲浠ラ夋嫨浠呰緭鍑簃ain鍑芥暟鎴栫晫闈㈢敓鎴愮被銆備笉褰卞搷澶栭儴宸茬粡瀹炵幇鐨勯昏緫浠g爜銆 -8. 濡傛灉绋嬪簭鏈夊涓狦UI鐣岄潰锛屽彲浠ュ湪VB宸ョ▼涓坊鍔犵獥浣擄紝灏卞彲浠ラ夋嫨浜х敓鍝釜绐椾綋鐨勫搴斾唬鐮併 +7. 濡傛灉绋嬪簭鏈夊涓狦UI鐣岄潰锛屽彲浠ュ湪VB宸ョ▼涓坊鍔犵獥浣擄紝灏卞彲浠ラ夋嫨浜х敓鍝釜绐椾綋鐨勫搴斾唬鐮併 -9. 閽堝缁撴瀯鍖栦唬鐮侊紝濡傛灉瑕佸湪Python浠g爜涓紩鐢ㄥ拰淇敼鍏朵粬鎺т欢鐨勫硷紝鍙互浣跨敤鍏ㄥ眬瀛楀吀gComps锛岃繖涓瓧鍏镐繚瀛樹簡鎵鏈夌殑GUI鍏冪礌鍜屼竴浜涘搴旂殑鎺т欢鍙橀噺锛屽彲浠ョ洿鎺ヤ娇鐢ㄥ舰濡俫Comps["Text1Var"].set("new Text")鐨勪唬鐮佹潵璁块棶瀵瑰簲鎺т欢銆 +8. 閽堝缁撴瀯鍖栦唬鐮侊紝濡傛灉瑕佸湪Python浠g爜涓紩鐢ㄥ拰淇敼鍏朵粬鎺т欢鐨勫硷紝鍙互浣跨敤鍏ㄥ眬瀛楀吀gComps锛岃繖涓瓧鍏镐繚瀛樹簡鎵鏈夌殑GUI鍏冪礌鍜屼竴浜涘搴旂殑鎺т欢鍙橀噺锛屽彲浠ョ洿鎺ヤ娇鐢ㄥ舰濡俫Comps["Text1Var"].set("new Text")鐨勪唬鐮佹潵璁块棶瀵瑰簲鎺т欢銆 濡傛灉杈撳嚭鐨勬槸闈㈠悜瀵硅薄浠g爜锛屽垯鍙互鍦ㄧ晫闈㈡淳鐢熺被Application涓娇鐢╯elf.widgetName鏂瑰紡鐩存帴璁块棶瀵瑰簲鐨勬帶浠躲 -10. 涓鑸殑GUI妗嗘灦閮戒細灏哢I閮ㄥ垎鍜岄昏緫浠g爜閮ㄥ垎鍒嗗埆鏀惧湪涓嶅悓鐨勬枃浠朵腑锛屽湪閫昏緫浠g爜鏂囦欢涓鍏I鏂囦欢锛屽疄鐜颁慨鏀筓I涓嶅奖鍝嶉昏緫浠g爜銆傚洜涓哄浜庡疄鐜扮畝鍗曠殑绋嬪簭鏉ヨ锛屾垜鍋忕埍鍗曟枃浠讹紝鎵浠ユ垜灏哢I绫诲拰閫昏緫浠g爜绫婚兘鏀惧湪鍚屼竴涓枃浠朵腑锛屽湪淇敼鐣岄潰鍚庯紝浣犲彲浠ョ洿鎺ヨ鐩栧搴旂殑Application_ui绫诲嵆鍙疄鐜扮晫闈㈢殑鍙樻洿锛屼笉杩囧鏋滃鍔犱簡鏂扮殑浜嬩欢鍥炶皟鍑芥暟锛岄渶瑕佸湪瀛愮被Application涓鍔犳墠琛屻 +9. 涓鑸殑GUI妗嗘灦閮戒細灏哢I閮ㄥ垎鍜岄昏緫浠g爜閮ㄥ垎鍒嗗埆鏀惧湪涓嶅悓鐨勬枃浠朵腑锛屽湪閫昏緫浠g爜鏂囦欢涓鍏I鏂囦欢锛屽疄鐜颁慨鏀筓I涓嶅奖鍝嶉昏緫浠g爜銆傚洜涓哄浜庡疄鐜扮畝鍗曠殑绋嬪簭鏉ヨ锛屾垜鍋忕埍鍗曟枃浠讹紝鎵浠ユ垜灏哢I绫诲拰閫昏緫浠g爜绫婚兘鏀惧湪鍚屼竴涓枃浠朵腑锛屽湪淇敼鐣岄潰鍚庯紝浣犲彲浠ョ洿鎺ヨ鐩栧搴旂殑Application_ui绫诲嵆鍙疄鐜扮晫闈㈢殑鍙樻洿锛屼笉杩囧鏋滃鍔犱簡鏂扮殑浜嬩欢鍥炶皟鍑芥暟锛岄渶瑕佸湪瀛愮被Application涓鍔犳墠琛屻 + + + # 鐩墠鏀寔鐨勬帶浠跺垪琛 -1. Label +1. **Form** + VB6涓殑绐椾綋(Form)瀵瑰簲鍒癟kinter鐨凢rame锛岀敤浜庝富绐椾綋鍛堢幇銆 + 涓轰簡鏇村ソ鐨勬晥鏋滐紝寤鸿鍦╒B6閲岄潰璁剧疆绐椾綋鐨凚orderStyle灞炴т负"Fixed Single"鎴"Fixed Dialog"銆 +2. **Label** 鏍囩鏉″湪VB鍜孭ython涓熀鏈竴鏍枫傚彲浠ュ湪鏂囨湰涓彃鍏n鏉ユ崲琛岋紝濡傛灉鍚敤ttk锛岃繕鍙互璁剧疆wraplength灞炴с -2. TextBox +3. **TextBox** Python鏂囨湰妗嗘湁涓ょ锛欵ntry鍜孴ext锛屽鏋淰B鐨凾extBox鐨凪ultiLine=False锛屽垯 鐢熸垚Entry锛屽惁鍒欑敓鎴怲ext銆 -3. Frame +4. **Frame** 瀵瑰簲Python鐨凩abelFrame鎺т欢锛屽仛涓哄叾浠栨帶浠剁殑瀹瑰櫒锛屾垨鍋氫负鐣岄潰鍏冪礌瑙嗚鍒嗙被銆 -4. CommandButton +5. **CommandButton** 瀵瑰簲Python鐨凚utton锛屾病鏈夊お澶氬尯鍒 涓轰簡浠g爜绠娲侊紝绐椾綋鐨勯鍑烘寜閽彲浠ヨ缃瓹ancel灞炴т负True锛岀劧鍚庣▼搴忚嚜鍔ㄧ敓鎴 瀵瑰簲Tkinter鐨刣estroy鍥炶皟锛岃繖鏍峰氨涓嶉渶瑕佸啀瀹炵幇涓涓洖璋冨嚱鏁般 鍦╒B閲岄潰瀛楁瘝鍓嶅鍔犱竴涓"&"绗﹀彿鍙互鐩存帴缁戝畾涓涓揩鎹烽敭 'Alt+瀵瑰簲瀛楁瘝'锛 - TkinterDesigner涔熸敮鎸佹璁剧疆锛岃嚜鍔ㄧ敓鎴愬搴旂殑浜嬩欢缁戝畾浠g爜銆 + Vb6Tkinter涔熸敮鎸佹璁剧疆锛岃嚜鍔ㄧ敓鎴愬搴旂殑浜嬩欢缁戝畾浠g爜銆 鍏朵粬鎺т欢姣斿CheckBox绛夋湁"鏍囬"灞炴х殑鎺т欢涓鏍峰姝ゅ鐞嗐 -5. CheckBox +6. **CheckBox** 澶氶夋寜閽搴擯ython鐨凜heckbutton銆 -6. OptionButton +7. **OptionButton** 鍗曢夋寜閽搴擯ython鐨凴adiobutton銆 tkinter涓璕adiobutton鐨勫垎缁勬柟娉曞拰VB鏈変簺涓嶄竴鏍凤紙鍒嗙粍鎰忓懗鐫缁勫唴鐨勫崟閫夋寜閽嚜鍔 浜掓枼锛岀敤鎴烽夋嫨涓涓垯鍏朵粬鐨勮嚜鍔ㄥ彇娑堬級銆 鍦╒B涓紝濡傛灉浣跨敤Frame灏嗗嚑涓狾ptionButton鍦堣捣鏉ワ紝鍒欒繖鍑犱釜OptionButton鑷姩鎴愪负涓缁勩 - TkinterDesigner涔熸敮鎸佽繖鏍风殑鎿嶄綔锛屽悓涓鐖舵帶浠剁殑Radiobutton鑷姩鎴愪负涓缁勩 + Vb6Tkinter涔熸敮鎸佽繖鏍风殑鎿嶄綔锛屽悓涓鐖舵帶浠剁殑Radiobutton鑷姩鎴愪负涓缁勩 濡傛灉闇瑕佹墜鍔ㄥ鐞嗭紝浣犺灏嗛渶瑕佸垎鎴愪竴缁勭殑Radiobutton鐨剉ariable灞炴ц缃负鍚屼竴涓彉閲忥紝 鐒跺悗鍚勪釜Radiobutton鐨剉alue鍊艰涓嶄竴鏍凤紙榛樿涓烘帶浠跺悕锛夛紝鍏蜂綋鏄粈涔堝间綘鍙互闅忎究璁剧疆锛 鍙嶆涓嶄竴鏍峰氨琛岋紝鏈绠鍗曠殑灏辨槸1/2/3绛夛紝鎴栬呬竴涓缃负man锛屽彟涓涓缃负woman锛 鍦ㄥ搴旂殑Radiobutton琚夋嫨鍚庯紝variable鍙橀噺鑷姩璁剧疆涓哄搴旂殑value鍊硷紝璇诲彇鍗冲彲 鐭ラ亾鍝釜Radiobutton琚変腑浜嗭紝鍙嶄箣璁剧疆variable鍙橀噺浼氬鑷村搴旂殑Radiobutton 琚変腑銆 -7. ComboBox +8. **ComboBox** 缁勫悎妗嗗湪Tkinter涓病鏈夊搴旂殑鎺т欢锛屾瘮杈冪被浼肩殑鍙湁OptionMenu锛岀被浼糃omboBox 鐨凷tyle=2 (Dropdown List)鏃剁殑琛ㄧ幇锛屼竴涓笅鎷夊垪琛紝鍙兘鍦ㄥ垪琛ㄤ腑閫夋嫨涓涓硷紝 涓嶈兘鐩存帴杈撳叆銆傛墍浠ュ缓璁湪VB鐨凜omboBox涓啓涓嬫墍鏈夌殑涓嬫媺鍒楄〃鍊笺 濡傛灉鍚敤浜員TK涓婚鎵╁睍搴撴敮鎸侊紝鍒欑洿鎺ュ搴斿埌TTK鐨凜ombobox锛屽褰㈠拰琛屼负鍩烘湰 涓鑷淬 -8. ListBox +9. **ListBox** 鍒楄〃妗嗗搴擯ython鐨凩istbox锛岃涓轰篃绫讳技锛屽彲浠ュ湪璁捐闃舵璁剧疆鍒濆鍒楄〃銆 濡傛灉闇瑕佹粴鍔紝鍒欏湪閫傚綋浣嶇疆鍒涘缓婊氬姩鏉★紝濡傛灉婊氬姩鏉$揣闈犵潃鍒楄〃妗嗙殑鍙宠竟鎴栦笅杈癸紝 骞朵笖闀垮害(姘村钩婊氬姩鏉)鎴栭珮搴(鍨傜洿婊氬姩鏉)宸笉澶氾紝鍒欐粴鍔ㄦ潯鍜屽垪琛ㄦ鑷姩缁戝畾锛 濡傛灉娌℃湁鑷姩缁戝畾锛屽垯鍙互鍦ˋddin鐣岄潰閫夋嫨鍏秞scrollcommand鎴杫scrollcommand 灞炴т负瀵瑰簲婊氬姩鏉$殑.set鏂规硶銆 -9. HScrollBar, VScrollBar +10. **HScrollBar, VScrollBar** 婊氬姩鏉″湪Python涓负Scrollbar锛岄氳繃璁剧疆orient鏉ユ帶鍒舵按骞宠繕鏄瀭鐩淬 -10. PictureBox +11. **PictureBox** 绠鍗曞搴斿埌Python涓殑Canvas锛岀敤鍋氬叾浠栨帶浠剁殑瀹瑰櫒鎴栫敾鍥惧鍣ㄤ娇鐢ㄣ 濡傛灉闇瑕佹粴鍔紝鍒欏湪閫傚綋浣嶇疆鍒涘缓婊氬姩鏉★紝濡傛灉婊氬姩鏉$揣闈犵潃鍥惧儚妗嗙殑鍙宠竟鎴栦笅杈癸紝 骞朵笖闀垮害(姘村钩婊氬姩鏉)鎴栭珮搴(鍨傜洿婊氬姩鏉)宸笉澶氾紝鍒欐粴鍔ㄦ潯鍜屽浘鍍忔鑷姩缁戝畾锛 濡傛灉娌℃湁鑷姩缁戝畾锛屽彲浠ュ湪Addin鐣岄潰閫夋嫨鍏秞scrollcommand鍜寉scrollcommand 灞炴т负瀵瑰簲婊氬姩鏉$殑.set鏂规硶銆 -11. Menu +12. **Menu** 鍙互浣跨敤VB鐨勮彍鍗曠紪杈戝櫒鏉ヨ璁ython鐨勮彍鍗曘 鍦╒B涓殑鑿滃崟鏍囬璁剧疆涓"-"鍒欏垱寤哄垎闅旀潯銆 涔熷彲浠ュ湪姝e父鐨勮彍鍗曟爣棰樹腑澧炲姞(&+瀛楁瘝)鐨勬柟寮忔坊鍔 'Alt蹇嵎閿'銆 闄 'Alt蹇嵎閿' 澶栵紝鍦╒B鑿滃崟缂栬緫鍣ㄤ腑閫夋嫨鑿滃崟瀵瑰簲鐨勫揩鎹烽敭鍒欎細鐩存帴鏄剧ず蹇嵎閿 淇℃伅鍦ㄨ彍鍗曟爣棰樺悗闈紝骞惰嚜鍔ㄦ敞鍐屽搴旂殑bind鍛戒护銆 -12. Line +13. **Line** 鍙互鐢ㄤ簬缁勭粐澶嶆潅鐣岄潰锛屼粎鏀寔姘村钩鎴栧瀭鐩寸嚎銆 - > 浠ヤ笅鐨勬帶浠堕渶瑕佸湪VB鐨'鎺т欢宸ュ叿绠'涓寜鍙抽敭娣诲姞'閮ㄤ欢'锛岄夋嫨鈥淢icrosoft Windows Common Controls 6.0鈥 + > *浠ヤ笅鐨勬帶浠堕渶瑕佸湪VB鐨'鎺т欢宸ュ叿绠'涓寜鍙抽敭娣诲姞'閮ㄤ欢'锛岄夋嫨 "Microsoft Windows Common Controls 6.0"* -13. Slider +14. **Slider** 绫讳技瀵瑰簲Python涓殑Scale銆 -14. ProgressBar +15. **ProgressBar** 瀵瑰簲鍒癙ython鐨凱rogressbar锛岄渶瑕佸惎鐢═TK涓婚鎵╁睍锛堥粯璁わ級 -15. TreeView +16. **TreeView** 瀵瑰簲鍒癙ython鐨凾reeview锛屾爲褰㈡樉绀烘帶浠讹紝鍙互閫夋嫨鏄惁鏄剧ず鏍囬琛, 闇瑕佸惎鐢═TK涓婚鎵╁睍锛堥粯璁わ級 濡傛灉闇瑕佹粴鍔紝鍒欏湪閫傚綋浣嶇疆鍒涘缓婊氬姩鏉★紝濡傛灉婊氬姩鏉$揣闈犵潃TreeView鐨勫彸杈规垨涓嬭竟锛 骞朵笖闀垮害(姘村钩婊氬姩鏉)鎴栭珮搴(鍨傜洿婊氬姩鏉)宸笉澶氾紝鍒欐粴鍔ㄦ潯鍜孴reeView鑷姩缁戝畾锛 濡傛灉娌℃湁鑷姩缁戝畾锛屽彲浠ュ湪Addin鐣岄潰閫夋嫨鍏秞scrollcommand鍜寉scrollcommand 灞炴т负瀵瑰簲婊氬姩鏉$殑.set鏂规硶銆 -16. TabStrip +17. **TabStrip** 閫夐」鍗℃帶浠讹紝瀵瑰簲鍒癙ython鐨凬otebook锛岄渶瑕佸惎鐢═TK涓婚鎵╁睍锛堥粯璁わ級銆 濡傛灉瑕佸竷灞鍚勪釜椤甸潰鍐呯殑鎺т欢锛屾寜浠ヤ笅姝ラ锛 1. 姣忎釜閫夐」椤靛搴斾竴涓狥rame鎴朠ictureBox锛屽懡鍚嶄负锛歍abStrip鐨勫悕瀛 - 鍔 '__Tab'(鍙屼笅鍒掔嚎)锛屽啀鍔犱竴涓簭鍙凤紝浠1寮濮嬶紝姣斿TabStrip鐨勫悕瀛椾负TabStrip1锛 - 鍒欎綘鍙互鍦ㄧ獥浣撲笂鍒涘缓涓涓狿ictureBox锛屽懡鍚嶄负 'TabStrip1__Tab1' (娉ㄦ剰澶у皬鍐)銆 + 鍔 `__Tab` (鍙屼笅鍒掔嚎)锛屽啀鍔犱竴涓簭鍙凤紝浠1寮濮嬶紝姣斿TabStrip鐨勫悕瀛椾负TabStrip1锛 + 鍒欎綘鍙互鍦ㄧ獥浣撲笂鍒涘缓涓涓狿ictureBox锛屽懡鍚嶄负 `TabStrip1__Tab1` (娉ㄦ剰澶у皬鍐)銆 2. 鐒跺悗鍦≒ictureBox/Frame鍐呮憜鏀句綘闇瑕佺殑鍏朵粬鎺т欢锛岀敓鎴愪唬鐮佸悗姝ゅ鍣ㄥ唴鑷姩娣诲姞 - 鍒板搴旂殑閫夐」椤碉紝TkinterDesigner浼氬湪鍚庡彴涓烘偍鍋氳繖涓鍒囥 + 鍒板搴旂殑閫夐」椤碉紝Vb6Tkinter浼氬湪鍚庡彴涓烘偍鍋氳繖涓鍒囥 鏍囩椤靛搴旂殑PictureBox/Frame鍙互鏀剧疆鍦ㄧ獥浣撶殑鍙鑼冨洿澶栵紝涔熷氨鏄璁捐濂 瀵瑰簲鐨勯夐」椤靛悗锛岀缉灏廔DE涓殑绐椾綋涓轰綘闇瑕佺殑澶у皬銆 娉ㄦ剰锛 @@ -131,20 +155,23 @@ Readme of english version refers to [Readme_EN.md](https://github.com/cdhigh/tki 鎵浠ヨ繕鏄缓璁鏋滄湁TabStrip鎺т欢鐨勮瘽锛屼娇鐢ㄧ粷瀵瑰潗鏍囥 * Frame鍜孭ictureBox鍧囧彲浣滀负瀹瑰櫒锛屽鏋滀娇鐢‵rame浣滀负瀹瑰櫒锛屽垯鍏舵爣棰樺彲浠ヤ綔涓洪夐」椤 鏍囬锛屽鏋滀綘娌℃湁璁剧疆閫夐」椤垫爣棰樼殑璇濄傦紙閫夐」鍗℃帶浠剁殑鏍囬璁剧疆浼樺厛锛 -17. CommonDialog - 杩欎釜鎺т欢涔熺畻鏀寔锛屽鏋淰B绐椾綋涓湁杩欎釜鎺т欢锛屽垯鍦≒ython浠g爜涓鍏 - filedialog銆乻impledialog銆乧olorchooser杩欎笁涓ā鍧楋紝杩欎笁涓ā鍧楁彁渚涚畝鍗曠殑 - 鏂囦欢閫夋嫨銆佽緭鍏ユ銆侀鑹查夋嫨瀵硅瘽妗嗗姛鑳姐 - 闇瑕佸湪鎺т欢宸ュ叿绠卞鍔"Microsoft Common Dialog Control 6.0" +18. **CommonDialog** + 杩欎釜鎺т欢涔熺畻鏀寔锛屽鏋淰B绐椾綋涓湁杩欎釜鎺т欢锛屽垯鍦≒ython浠g爜涓鍏 + filedialog銆乻impledialog銆乧olorchooser杩欎笁涓ā鍧楋紝杩欎笁涓ā鍧楁彁渚涚畝鍗曠殑 + 鏂囦欢閫夋嫨銆佽緭鍏ユ銆侀鑹查夋嫨瀵硅瘽妗嗗姛鑳姐 + 闇瑕佸湪鎺т欢宸ュ叿绠卞鍔 "Microsoft Common Dialog Control 6.0" -# 鏈簲鐢ㄥtkinter鐨勬墿灞曞拰"灏佽" + + + +# 鏈簲鐢ㄥtkinter鐨勬墿灞曞拰"灏佽" 1. tkinter娌℃湁Statusbar鎺т欢锛屾墍浠ユ垜浣跨敤Label瀹炵幇浜嗕竴涓畝鍗曠殑Statusbar锛屽湪VB绐椾綋涓坊鍔燬tatusbar鍚庝細鎻掑叆杩欓儴鍒嗗疄鐜颁唬鐮併 锛圴B闇瑕佸厛娣诲姞鈥淢icrosoft Windows Common Controls 6.0鈥濋儴浠舵墠鏈塖tatusbar锛 2. tkinter鎺т欢娌℃湁Tooltip(榧犳爣鎮仠鎻愮ず)灞炴э紝鎵浠ユ垜瀹炵幇浜嗕竴涓畝鍗曠殑Tooltip绫荤粰tkinter鎺т欢鍔犱笂Tooltip鍔熻兘锛岃缃甐B鎺т欢鐨 ToolTipText灞炴у嵆鑷姩缁欏搴旂殑鎺т欢鍒涘缓涓涓猅ooltip绫汇俆oolTipText鏀寔鑷姩鎹㈣锛屽鏋滆鎵嬪姩鎺у埗鎹㈣锛屼篃鍙互浣跨敤 '\n'銆 3. 闅愯棌鍙嶄汉绫荤殑TK鎺т欢璁剧疆鍜岃幏鍙栨帶浠舵樉绀哄肩殑鏈哄埗锛堥渶瑕侀氳繃鎺т欢鍙橀噺textvariable锛夛紝缁橢ntry/Label/Button/Checkbutton/Radiobutton鎺т欢 娣诲姞鏇寸鍚堢洿瑙夌殑 setText()/text() 鏂规硶锛屽彲浠ョ洿鎺ヨ缃拰鑾峰彇鍏舵帶浠舵樉绀虹殑鏂囨湰鍊笺 - 锛圕heckbutton/Radiobutton榛樿涓嶆坊鍔狅紝濡傞渶瑕侊紝鍙互鍦╰kinter-designer灏唗extvariable鎵撳嬀锛屽洜涓哄緢灏戦渶瑕佽繍琛屾椂淇敼杩欎袱涓帶浠剁殑鏂囨湰銆傦級 + 锛圕heckbutton/Radiobutton榛樿涓嶆坊鍔狅紝濡傞渶瑕侊紝鍙互鍦╒b6Tkinter灏唗extvariable鎵撳嬀锛屽洜涓哄緢灏戦渶瑕佽繍琛屾椂淇敼杩欎袱涓帶浠剁殑鏂囨湰銆傦級 4. 鍚屾牱绫讳技绗笁鏉★紝缁機heckbutton/Radiobutton娣诲姞 setValue()/value() 鏂规硶锛屽弬鏁颁负1/0銆 `self.Text1.setText('new text')` `print(self.Text1.text())` @@ -152,21 +179,40 @@ Readme of english version refers to [Readme_EN.md](https://github.com/cdhigh/tki `self.Option1.setValue(1)` `print(self.Option1.value())` -# 鍏朵粬寤鸿 -1. 涓嶆敮鎸佷娇鐢ㄦ帶浠舵暟缁勶紝鐣岄潰鍙互鏄剧ず锛屼絾鏄悗闈㈢殑鍚屽悕鎺т欢鍚嶄細瑕嗙洊鍓嶉潰瀹氫箟鐨勶紝瀵艰嚧鍦ㄤ唬鐮佷腑鏃犳硶鍐嶅拰姝ゆ帶浠朵簰鍔ㄣ -2. 绐椾綋鐨凷caleMode寤鸿淇濇寔榛樿鍊(vbTwips)锛屽鏋滆璁剧疆涓哄叾浠栧硷紝鍒橣rame鎺т欢鍐呭氨涓嶈鍐嶆斁Frame鎺т欢浜嗭紝鍚﹀垯鍏跺唴閮ㄧ殑鎺т欢甯冨眬閿欒銆 -3. 濡傛灉闇瑕佺畝浣撴眽瀛楃晫闈紝鍒欓渶瑕丩anguage.lng鏂囦欢鍦═kinterDesigner.dll鍚屼竴鐩綍銆 -4. 姝ゆ彃浠舵敮鎸佹洿澶氱殑涓浜涗究鎹风壒鎬э紝鍒嗘暎鍦ㄧ増鏈巻鍙蹭腑锛岃繖閲屽氨涓嶄竴涓鍒椾妇浜嗭紝鏈夐渶瑕佺殑鍙互鍘讳簡瑙c + + + +# 鍏朵粬寤鸿 +1. 鎴戞渶鍠滄VB IDE鐨勭獥浣撹璁″櫒鐨勫叾涓竴鐐规槸瀹冩湁涓涓彍鍗曢」 "**鏍煎紡**"锛岀敤娉曟槸閫夋嫨澶氫釜鎺т欢鍚庯紝 閫氳繃姝よ彍鍗曢」鍙互璁剧疆鎺т欢鐨勫ぇ灏忓榻愮浉瀵逛綅缃瓑锛屽杽鐢ㄨ繖涓姛鑳藉湪鐣岄潰璁捐涓潪甯哥渷蹇冪渷鍔涳紝鑰屼笖鐣岄潰浼氭洿缇庤銆 + * 瀵归綈锛 宸﹀榻 椤跺榻愮瓑 + * 缁熶竴灏哄锛 瀹藉害鐩稿悓锛岄珮搴︾浉鍚岋紝涓よ呴兘鐩稿悓 + * 姘村钩闂磋窛锛 鐩稿悓闂磋窛锛岄掑锛岄掑噺绛 + * 鍨傜洿闂磋窛锛 鐩稿悓闂磋窛锛岄掑锛岄掑噺绛 + * 鍦ㄧ獥浣撲腑灞呬腑瀵归綈锛氭按骞冲榻愶紝鍨傜洿瀵归綈 +2. 鎻掍欢涓嶆敮鎸佷娇鐢ㄦ帶浠舵暟缁勶紝鐣岄潰鍙互鏄剧ず锛屼絾鏄悗闈㈢殑鍚屽悕鎺т欢鍚嶄細瑕嗙洊鍓嶉潰瀹氫箟鐨勶紝瀵艰嚧鍦ㄤ唬鐮佷腑鏃犳硶鍐嶅拰姝ゆ帶浠朵簰鍔ㄣ +3. VB绐椾綋鐨凷caleMode寤鸿淇濇寔榛樿鍊(vbTwips)锛屽鏋滆璁剧疆涓哄叾浠栧硷紝鍒橣rame鎺т欢鍐呭氨涓嶈鍐嶆斁Frame鎺т欢浜嗭紝鍚﹀垯鍏跺唴閮ㄧ殑鎺т欢甯冨眬閿欒銆 +4. 濡傛灉闇瑕佺畝浣撴眽瀛楃晫闈紝鍒欓渶瑕乂b6Tkinter.lng鏂囦欢鍦╒b6Tkinter.dll鍚屼竴鐩綍銆 +5. 姝ゆ彃浠舵敮鎸佹洿澶氱殑涓浜涗究鎹风壒鎬э紝鍒嗘暎鍦ㄧ増鏈巻鍙蹭腑锛岃繖閲屽氨涓嶄竴涓鍒椾妇浜嗭紝鏈夐渶瑕佺殑鍙互鍘讳簡瑙c + + # ttk搴撻澶栬鏄 - ttk涓婚鎵╁睍鐪嬭捣鏉ュ緢婕備寒锛屽湪涓嶅悓鎿嶄綔绯荤粺涓嬬晫闈㈠憟鐜颁负鏈湴鍖栭鏍硷紝寤鸿浣跨敤锛 + ttk鏄痶kinter鐨勪富棰樻墿灞曞簱锛屼篃鏄爣鍑嗗簱锛岀湅璧锋潵寰堟紓浜紝鍦ㄤ笉鍚屾搷浣滅郴缁熶笅鐣岄潰鍛堢幇涓烘湰鍦板寲椋庢牸锛屽缓璁娇鐢紝 鍙槸瑕佹敞鎰忎互涓嬪嚑涓猼tk鐨凚UG锛 1. TTK鐨凟ntry鍜孋ombobox鎺т欢鑳屾櫙鑹茶缃棤鏁堬紙鍙互璁剧疆锛屼笉鎶ラ敊锛屼絾鏄晫闈笉鍙橈級銆 2. LabelFrame鍜孨otebook鎺т欢鐨勫瓧浣撳崟鐙缃棤鏁堬紝浣嗘槸鍙互璁剧疆ttk鐨勫叏灞瀛椾綋灞炴ф潵鏀瑰彉锛屾瘮濡傦細self.style.configure('.', font=('瀹嬩綋',12))銆 3. Python 2.7.3闄勫甫鐨則tk涓殑Treeview瀛椾綋璁剧疆鏃犳晥锛屼絾3.2.3鍙婁箣鍚庣殑鐨凾reeview鐨勫瓧浣撹缃湁鏁堛 + + + # 鐗堟湰鍘嗗彶 +* v1.7 + 1. 鎻掍欢鍚嶄粠 TkinterDesigner 鏇村悕涓 Vb6Tkinter + 2. 澧炲姞鍦ㄧ嚎妫鏌ョ増鏈洿鏂板姛鑳 + 3. 濡傛灉浠呴渶瑕丳ython3浠g爜锛屼慨鏀归儴鍒嗚緭鍑虹殑浠g爜鏇寸鍚圥ython3涔犳儻 + 4. 榛樿鍙栨秷閰嶇疆椤"鍏煎Python2/3浠g爜"锛岄粯璁よ緭鍑篜ython3浠g爜 * v1.6.8 1. Notebook鎺т欢鐨勯紶鏍囩偣鍑讳簨浠跺搴斿埌 <> 浜嬩欢 * v1.6.7 @@ -181,7 +227,7 @@ Readme of english version refers to [Readme_EN.md](https://github.com/cdhigh/tki * v1.6.3 1. 鏀寔璁捐鏃跺湪绐椾綋涓婅缃垎缁勪腑鍏朵腑涓涓猂adiobutton鐨勯変腑鐘舵併 * v1.6.2 - 1. 鏀寔ToolTipText灞炴э紝瀹炵幇榧犳爣鎮仠寮瑰嚭鎻愮ず妗嗗姛鑳斤紝tkiner娌℃湁Tooltip鍔熻兘锛岃嚜宸卞疄鐜颁簡涓涓猅ooltip绫绘潵鏀寔銆 + 1. 鏀寔ToolTipText灞炴э紝瀹炵幇榧犳爣鎮仠寮瑰嚭鎻愮ず妗嗗姛鑳斤紝Vb6Tkinter娌℃湁Tooltip鍔熻兘锛岃嚜宸卞疄鐜颁簡涓涓猅ooltip绫绘潵鏀寔銆 * v1.6.1 1. 缁機heckbutton/Radiobutton娣诲姞setValue()/value()鍑芥暟锛屽弬鏁颁负鏁村瀷1/0銆 * v1.6 @@ -295,8 +341,8 @@ Readme of english version refers to [Readme_EN.md](https://github.com/cdhigh/tki * v1.2.2 1. 瀵瑰簲涓浜涘睘鎬у硷紝濡傛灉鍙湁鏈夐檺鐨勫彲閫夊硷紝鍒欏彲浠ュ湪涓嬪垪鍒楄〃涓夋嫨銆 * v1.2 - 1. 澧炲姞澶氳绉嶆敮鎸侊紝璇█鏂囦欢涓篢kinterDesigner.dll鐩綍涓嬬殑language.lng锛 - 鐗堟湰鍙戝竷鏃舵敮鎸佺畝浣撲腑鏂囥佺箒浣撲腑鏂囥佽嫳鏂囥 + 1. 澧炲姞澶氳绉嶆敮鎸侊紝璇█鏂囦欢涓篤b6Tkinter.dll鐩綍涓嬬殑Vb6Tkinter.lng锛 + 鐗堟湰鍙戝竷鏃舵敮鎸佺畝浣撲腑鏂囥佽嫳鏂囥 濡傛灉娌℃湁璇█鏂囦欢锛屾樉绀鸿蒋浠跺唴缃殑绠浣撲腑鏂囥 2. 澧炲姞鐘舵佹爮鎺т欢鏀寔锛屽洜涓篢K鍜孴TK閮戒笉鏀寔Statusbar锛屽氨鑷繁浣跨敤Label 绠鍗曟ā鎷熶簡涓涓紝鏀寔澶氱獥鏍硷紝鎺т欢绫诲畾涔夌洿鎺ユ坊鍔犲埌Python婧愮爜銆 diff --git a/Readme_EN.md b/Readme_EN.md index d99cd44..41899da 100644 --- a/Readme_EN.md +++ b/Readme_EN.md @@ -1,94 +1,193 @@ -# Introduce -The program is a addin of VB6(Visual Basic 6), It allows you design your GUI layout of Tkinter (standard GUI library of Python) in VB6 Integrated Development Environment. +# Introduction + +The program is an addin for VB6, It allows you design your GUI layout of Tkinter (standard GUI library of Python) in VB6 Integrated Development Environment. The addin will generate python code of GUI framework for you. the only thing you need to do is that add your logical code in Callback of GUI framework. -![screenshot](https://raw.githubusercontent.com/cdhigh/tkinter-designer/master/Setup/Screenshots/TkinterDesigner_ScrPrnt_EN.JPG) - -# Install and Usage -1. Install VB6 (You can install VB6 Lite or nano version). - (if your os is windows 7 or later, please install VB6 SP6 version and - overwrite VB6.EXE using Vb6_SP6_Fix_for_Win7.exe) - -2. Download Tkinter Designer from github. - [https://github.com/cdhigh/tkinter-designer](https://github.com/cdhigh/tkinter-designer) - -3. Copy directory 'Bin' to other directory you want, execute 'Setup for TkinterDesigner.exe' to register TkinterDesigner.dll. Or you can do it manual. - 1. run regsvr32 /s diretory\TkinerDesigner.dll - 2. Add a line to sector [Add-Ins32] of C:\Windows\VBADDIN.INI: - `TkinterDesigner.Connect=3` - -4. Open VB6, create a standard EXE project, design your layout firstly, - and than click the icon 'Tkinter Designer' in toolbox of VB6. - -5. Enjoy TkinterDesigner. - -# List of VB Controls Supported -1. Label - Has same appearance and behavior in Tkinter. -2. TextBox - If the property MultiLine=False, the addin generate code for widget - 'Entry' of Tkinter, otherwise for widget 'Text'. -3. Frame - Similar to widget LabelFrame of Tkinter. It can be container of other - widget. -4. CommandButton - It represent the widget Button of Tkinter. - You can also add a '&' befor a corresponding letter to make a keyboard - shortcut like 'Alt-letter', the addin generate code for shortcurts too. -5. CheckBox - Similar to widget Checkbutton. -6. OptionButton - Similar to widget Radiobutton. -7. ComboBox - If the menu 'Use TTK library' checked, it translate to widget Combobox - of TTK, otherwise, it translate to widget OptionMenu of Tkinter. -8. ListBox - Similar to widget Listbox of tkinter. you can add list of text in IDE. -9. HScrollBar, VScrollBar - The widget Scrollbar of tkinter. -10. Slider - Similar to widget Scale of tkinter. -11. PictureBox - It tranlate to Canvas. -12. Menu - Has same appearance and behavior in Tkinter. - you can create a separator by setting the caption of menuitem to '-'. - Add a keyboard shortcut by using format of '&+letter'. - -> Adding the component 'Microsoft Windows Common Controls 6.0' to toolbox of VB IDE to support the other controls. - -13. ProgressBar - Similar to widget Progressbar of TTK library. -14. TreeView - Similar to widget Treeview of TTK library. -15. TabStrip - Similar to widget Notebook of TTK libray. - If you want to design the tabs of Notebook in VB IDE, please use a - PictureBox or Frame as container for widgets, you have to name the - PictureBox or Frame following format: - "Name of TabStrip" + "\__Tab" + sequence number(start in 1) - For example, if name of TabStrip is 'TabStrip1'(by default), you can - Create a PictureBox named 'TabStrip1\__Tab1' as container for Tab1 of - Notebook widget. - -16. CommonDialog - if the form has this control, then the addin will create code for - import modules filedialog, simpledialog, colorchooser. - -# Extends to tkinter -1. Added a Statusbar widget. - (Statusbar in component "Microsoft Windows Common Controls 6.0" in VB IDE) -2. Added a Tooltip class to implement a Tooltip hover box for almost all widgets, supports wrap automatic or wrap manual(using '\n'). -3. Added More intuitive setText()/text() methods to Entry/Label/Button/Checkbutton/Radiobutton. - (not apply to CheckBCheckbutton/Radiobutton by default, please select 'textvariable' in tkinter-designer.) -4. Similar to 3, Added setValue()/value() to Checkbutton/Radiobutton, parameter is 1/0. - `self.Text1.setText('new text')` - `print(self.Text1.text())` - `print(self.Check1.value())` - `self.Option1.setValue(1)` - `print(self.Option1.value())` - -# History +![screenshot](https://raw.githubusercontent.com/cdhigh/vb6tkinter/master/Setup/Screenshots/Vb6Tkinter_ScrPrnt_EN.png) + + +This tool supports the majority of TKinter widgets, making it suitable for most GUI requirements. +(List of widgets can be found in the section "List of VB Controls Supported" below). + + + + +# Target user + +Suitable for those who have learned TKinter and prefer not to manually write GUI code, without relying on third-party tools or frameworks like wxPython/PyQt. +Ideal for small program development with relatively simple UI; for complex interfaces, frameworks like wxPython/PyQt are more suitable. +As TKinter is part of the Python standard library, programs developed with TKinter can be considered "green software" or "portable software", They don't require the installation of third-party frameworks like wxPython/PyQt on the target machine. as long as Python is present, the program can run. Even when packaged into executables using tools like pyinstaller/cx_freeze, the final files remain relatively small. +If software logic is not overly complex, typically handled with a single .py file. +(If you don't want a command prompt window to pop up during direct interpretation of the .py file, change the extension to .pyw) + + + + +# Installation + +There are two methods, choose either: +1. Integrated Installation: + Download the pre-integrated and pre-patched VB6 nano installer at , Double-click to execute the installation, Do not need the operations in the following section. + +2. Standalone Installation: +2.1. Download the addin from extract it to a directory. +2.2. Install VB6 independently, either the complete version or a lite/nano version. + 2.2.1. In Windows 7 and newer, please install VB6 SP6 version and overwrite VB6.EXE using Vb6_SP6_Fix_for_Win7.zip. + 2.2.2. In Windows 10 and newer, please apply VB6_AppCompat. +2.3. Register the addin using the provided registration tool "Setup for Vb6Tkinter.exe" or manually: + 2.3.1. Run `regsvr32 /s directory\Vb6Tkinter.dll`. + 2.3.2. Add a line in the [Add-Ins32] section of C:\Windows\VBADDIN.INI: + `Vb6Tkinter.Connect=3` + +3. Once the addin have been installed and registered, future updates can be done by simply downloading the new versions of Vb6Tkinter.dll/Vb6Tkinter.lng and overwriting the existing files. + + + + +# Usage + +1. Open VB6 and create a new standard EXE project. Design your GUI layout on the form. This task should be easy even for those without experience in VB6. Don't forget to set the corresponding control properties. If you prefer a non-resizable window, consider changing the VB6 form's "BorderStyle" property to "Fixed Single" or "Fixed Dialog". + +2. If the addin is registered properly, you should now see a new icon (an orange-red feather) on the VB toolbar. If not, navigate to "Add-Ins" | "Add-In Manager" and launch Vb6Tkinter from there. The Vb6Tkinter icon and menu should appear accordingly. + +3. After launching Vb6Tkinter, click the "Refresh Forms" button to display all forms and controls in the current project. + +4. Review each control's properties, checking the desired options. If needed, double-click on a property in the list to modify its value. Typically, there's no need for additional modifications to control properties. Vb6Tkinter try it's best to translate VB control properties into Tkinter properties, covering aspects like font, color, initial value, appearance, and state. It even includes settings for buttons and menu shortcuts. If certain properties lack a direct correspondence, adjustments may be necessary within the Vb6Tkinter interface. + +5. Click the "Generate Code" button to produce code in the code preview window. You can either double-click on the code preview window to view it in detail or make direct modifications to the code. + +6. Once confirmed, copy the code to the clipboard or save it to a file. Layouts can utilize percentage-based (relative) or absolute coordinate-based (pixel) positioning. The advantage of percentage positioning is that controls can adjust relative to changes in the main interface size. For a fixed layout, opt for absolute coordinate positioning. Note: If altering a previously designed UI, consider outputting only the ui class to avoid affecting existing external logic code. + +7. In the case of multiple GUI dialog/form application, add forms within the VB project. This allows you to select which form to generate code. + +8. Regarding structured code, if you need to reference and modify other widgets values in Python, use the global dictionary gComps. This dictionary stores all GUI elements and some corresponding control variables. Access widgets directly using code like gComps["Text1Var"].set("new Text"). For object-oriented code, access widgets directly in the derived class Application using self.widgetName. + +9. GUI frameworks typically segregate UI and logic code into different files. In logic code files, import the UI file to ensure UI modifications don't impact the logic. While many prefer this separation, for simpler programs, I've chosen to keep both the UI class and logic code class in the same file. After modifying the interface, overwrite the corresponding Application_ui class to implement interface changes. If new event callback functions are added, remember to include them in the subclass Application. + + + + + +# List of VB Controls Supported + +1. **Form** + The VB6 window (Form) corresponds to Tkinter's Frame, serving as the main interface presentation. For a more polished appearance, it's recommended to set the VB6 Form's BorderStyle property to "Fixed Single" or "Fixed Dialog." + +2. **Label** + Label in VB and Python is essentially the same. Line breaks can be achieved by inserting "\n" in the text, and with ttk enabled(default), the wraplength property becomes available. + +3. **TextBox** + Python offers two types of text boxes: Entry and Text. If VB's TextBox has property MultiLine=False, it generates an Entry; otherwise, it produces a Text. + +4. **Frame** + Corresponding to Python's LabelFrame widget, the Frame acts as a container for other controls or visually classifies interface elements. + +5. **CommandButton** + Corresponding to Python's Button with minimal differences. For concise code, setting the Cancel property to True for the form's exit button generates the Tkinter destroy callback, eliminating the need for a separate callback function. In VB, prefixing a letter with "&" directly binds a shortcut key 'Alt + corresponding letter'(forexample &A). Vb6Tkinter supports this, automatically generating the associated event binding code. The same approach applies to other controls with a "Caption" property, such as CheckBox. + +6. **CheckBox** + The CheckBox corresponds to Python's Checkbutton. + +7. **OptionButton** + The OptionButton corresponds to Python's Radiobutton. The grouping method for Radiobuttons in tkinter differs slightly from VB (grouping implies mutual exclusivity; selecting one automatically deselects others). In VB, placing several OptionButtons within a Frame automatically groups them, a feature supported by Vb6Tkinter. For manual handling, set the variable property of Radiobuttons in the same group to the same variable. Ensure that the value property of each Radiobutton is unique (default is the control name). Setting different values (e.g., 1/2/3 or "man"/"woman") ensures that when a Radiobutton is selected, the variable is set to the corresponding value. Reading the variable indicates the selected Radiobutton, and vice versa, setting the variable selects the corresponding Radiobutton. + +8. **ComboBox** + There is no direct equivalent for ComboBox in Tkinter legacy. The closest match is OptionMenu, behaving similarly to a VB ComboBox with Style=2 (Dropdown List)鈥攁 list where you can only choose from provided values and cannot input directly. Hence, it's advisable to list all dropdown values in VB's ComboBox. If TTK theme extension library support is enabled (default enabled), it directly corresponds to TTK's Combobox with a similar appearance and behavior. + +9. **ListBox** + The ListBox corresponds to Python's Listbox, behaving similarly, and allowing the setting of an initial list during design. If scrolling is required, create a scrollbar at an appropriate position. If the scrollbar is close to the right or bottom of the ListBox, and the length (horizontal scrollbar) or height (vertical scrollbar) is roughly similar, the scrollbar and ListBox are automatically bound. If not automatically bound, you can select its xscrollcommand or yscrollcommand properties in the Addin interface to correspond to the set method of the respective scrollbar. + +10. **HScrollBar, VScrollBar** + Scrollbars in Python are Scrollbar, with orientation controlled by the orient property. + +11. **PictureBox** + Roughly corresponds to Canvas in Python, serving as a container for other controls or as a drawing container. If scrolling is needed, create a scrollbar at an appropriate position. If the scrollbar is close to the right or bottom of the PictureBox, and the length (horizontal scrollbar) or height (vertical scrollbar) is roughly similar, the scrollbar and PictureBox are automatically bound. If not automatically bound, you can choose its xscrollcommand and yscrollcommand properties in the Addin interface to correspond to the set method of the respective scrollbar. + +12. **Menu** + You can use VB's menu editor to design menus in Python. In VB, setting the menu title to "-" creates a separator. You can also add Alt shortcuts to normal menu titles using the format (&+letter). Apart from Alt shortcuts, choosing a shortcut key for the menu in the VB menu editor will display the shortcut key information directly after the menu title and automatically bind the corresponding command. + +13. **Line** + This can be used to organize complex interfaces and supports only horizontal or vertical lines. + + > *Adding the component 'Microsoft Windows Common Controls 6.0' to toolbox of VB IDE to support the following controls.* + +14. **Slider** + Similar to Python's Scale, it corresponds to the Slider control in VB. To use, add it from the 'Control Toolbox' in VB by right-clicking, selecting 'Components,' and choosing "Microsoft Windows Common Controls 6.0." + +15. **ProgressBar** + Corresponds to Python's Progressbar. Enable TTK theme extension (default) and add it from the 'Control Toolbox' in VB by right-clicking, selecting 'Components,' and choosing "Microsoft Windows Common Controls 6.0." + +16. **TreeView** + Corresponds to Python's Treeview, a tree-like display control. You can choose whether to display header rows. Enable TTK theme extension (default) and add it from the 'Control Toolbox' in VB by right-clicking, selecting 'Components,' and choosing "Microsoft Windows Common Controls 6.0." If scrolling is required, create a scrollbar at an appropriate position. If the scrollbar is close to the right or bottom of the TreeView, and the length (horizontal scrollbar) or height (vertical scrollbar) is roughly similar, the scrollbar and TreeView are automatically bound. If not, you can select its xscrollcommand and yscrollcommand properties in the Addin interface to correspond to the set method of the respective scrollbar. + +17. **TabStrip** + The TabStrip control, corresponding to Python's Notebook, requires TTK theme extension (default). To layout controls within each page: + 1. Each tab corresponds to a Frame or PictureBox, named: TabStrip's name + `__Tab` (double underscore) + a number starting from 1 (e.g., if the TabStrip's name is TabStrip1, you can create a PictureBox named `TabStrip1__Tab1`). + 2. Place other controls you need within the PictureBox/Frame. After generating the code, this container is automatically added to the corresponding tab. Vb6Tkinter handles this behind the scenes. + Tab pages' PictureBox/Frame can be placed outside the visible range of the form. Once you've designed the corresponding tab, resize the form in the IDE to your desired size. + Note: + - If using relative coordinates, make sure the PictureBox or Frame container's size matches or is close to the size inside the TabStrip. Otherwise, the controls inside the tab may stretch or shrink to fit the available space, leading to an odd appearance. If using absolute coordinates, the PictureBox/Frame doesn't need to be the same size as the TabStrip, and the controls inside will be placed with the top-left corner of the TabStrip as the origin, maintaining the same proportions as designed. Therefore, it's recommended to use absolute coordinates if you have a TabStrip control. + +18. **CommonDialog** + This control is also supported. If your VB form contains this control, you can import the filedialog, simpledialog, and colorchooser modules in Python. These modules provide simple file selection, input box, and color selection dialog functions. Add the "Microsoft Common Dialog Control 6.0" from the 'Control Toolbox' in VB by right-clicking, selecting 'Components,' and choosing "Microsoft Windows Common Controls 6.0." + + + + + +# Extensions and "Wrappings" for Tkinter +1. Since tkinter lacks a Statusbar control, I have implemented a simple Statusbar using a Label. After adding a Statusbar to the VB form, the corresponding implementation code will be inserted. (VB needs to add the "Microsoft Windows Common Controls 6.0" component to have a Statusbar). + +2. As tkinter widgets do not have a Tooltip property, I have implemented a basic Tooltip class to add Tooltip functionality to tkinter controls. Setting the ToolTipText property of VB controls will automatically create a Tooltip class for the corresponding widget. ToolTipText supports automatic line breaks, and if manual control is needed, '\n' can be used. + +3. The application hides the counterintuitive TK control setting and retrieving mechanism for displaying values (requires the use of control variable textvariable). For Entry/Label/Button/Checkbutton/Radiobutton controls, more intuitive `setText()` and `text()` methods have been added for directly setting and retrieving the displayed text values of the controls. (Checkbutton/Radiobutton are not added by default. If needed, you can check the textvariable in Vb6Tkinter, as these two controls rarely require runtime modification of text). + +4. Similar to the third point, `setValue()` and `value()` methods have been added for Checkbutton/Radiobutton, with parameters 1/0. + ``` + self.Text1.setText('new text') + print(self.Text1.text()) + print(self.Check1.value()) + self.Option1.setValue(1) + print(self.Option1.value()) + ``` + + + + +# Other tips +1. One of the features I love most about the VB IDE's form designer is the "Format" menu. By selecting multiple controls, you can easily set their size, alignment, and relative positions using this menu. Leveraging this functionality in UI design is not only effortless but also results in a more aesthetically pleasing UI. + * Align: Left, top, etc. + * Make same size: width, height, both the same. + * Horizontal Spacing: Equal, increase, decrease, etc. + * Vertical Spacing: Equal, increase, decrease, etc. + * Center in Form: Horizontally, vertically. + +2. The addin does not support the use of control arrays. While the UI can display them, subsequent controls with the same name will overwrite the previously defined ones, making it impossible to interact with these controls in the code. + +3. It is recommended to keep the default value (vbTwips) for the ScaleMode property of VB forms. If you need to set it to another value, avoid placing Frame controls inside other Frame controls, as this may lead to layout errors for the controls within. + +4. For a Simplified Chinese addin interface, the Vb6Tkinter.lng file should be in the same directory as Vb6Tkinter.dll. + +5. The addin offers additional convenient features scattered throughout its version changelog. Here, we won't list them all, but those interested can explore them as needed. + + + +# Additional Explanation for the ttk Library +The standard built-in ttk themes extension provides native style on different operating systems. It is recommended for use, but be aware of the following ttk bugs: + +1. Setting the background color for TTK's Entry and Combobox controls is ineffective (you can set it without errors, but the interface remains unchanged). +2. Individually setting the font for LabelFrame and Notebook controls has no effect, but you can use ttk's global font attributes to change it, for example: `self.style.configure('.', font=('Arial', 12))`. +3. Font settings for Treeview in ttk accompanying Python 2.7.3 are ineffective, but they work for Treeview in version 3.2.3 and later. + + + + +# Changelog +* v1.7 + 1. Rename the add-in from TkinterDesigner to Vb6Tkinter. + 2. Add check update feature. + 3. If only Python3 code is required, generate better Python3-style code. + 4. By default, disable the option "Compatibile with Python 2/3 code". * v1.6.8 1. Translate the click event of Notebook widget to the <> event. * v1.6.7 diff --git a/Setup/Main.frm b/Setup/Main.frm index eb4b050..4c6ac56 100644 --- a/Setup/Main.frm +++ b/Setup/Main.frm @@ -1,40 +1,40 @@ VERSION 5.00 Begin VB.Form Form1 - Caption = "Setup for Tkinter Designer" + Caption = "Setup for Vb6Tkinter.dll" ClientHeight = 3405 ClientLeft = 60 ClientTop = 450 - ClientWidth = 7770 + ClientWidth = 7860 Icon = "Main.frx":0000 LinkTopic = "Form1" MaxButton = 0 'False ScaleHeight = 3405 - ScaleWidth = 7770 + ScaleWidth = 7860 StartUpPosition = 3 '窗口缺省 Begin VB.CommandButton CmdUninstall Caption = "卸载(&U)" Enabled = 0 'False Height = 615 - Left = 2760 + Left = 2820 TabIndex = 3 Top = 2745 - Width = 1935 + Width = 2175 End Begin VB.CommandButton CmdQuit Caption = "退出(&Q)" Height = 615 - Left = 5280 + Left = 5520 TabIndex = 2 Top = 2745 - Width = 1935 + Width = 2175 End Begin VB.CommandButton CmdSetup - Caption = "安装(&S)" + Caption = "注册(&R)" Height = 615 - Left = 240 + Left = 120 TabIndex = 1 Top = 2745 - Width = 1935 + Width = 2175 End Begin VB.Label Label1 Caption = "Label1" @@ -70,15 +70,15 @@ Private Declare Function GetSystemDefaultLCID Lib "kernel32" () As Long Private m_English As Boolean Private Sub AddToINI() - WritePrivateProfileString "Add-Ins32", "TkinterDesigner.Connect", "3", "VBADDIN.INI" + WritePrivateProfileString "Add-Ins32", "Vb6Tkinter.Connect", "3", "VBADDIN.INI" End Sub Private Sub DelFromINI() - WritePrivateProfileString "Add-Ins32", "TkinterDesigner.Connect", vbNullString, "VBADDIN.INI" + WritePrivateProfileString "Add-Ins32", "Vb6Tkinter.Connect", vbNullString, "VBADDIN.INI" End Sub Private Sub DelRegister() On Error Resume Next - DeleteSetting "Tkinter Designer" + DeleteSetting "Vb6Tkinter" End Sub Private Sub CmdQuit_Click() @@ -89,13 +89,13 @@ Private Sub CmdSetup_Click() Dim sf As String - sf = App.Path & IIf(Right(App.Path, 1) = "\", "", "\") & "TkinterDesigner.dll" + sf = App.Path & IIf(Right(App.Path, 1) = "\", "", "\") & "Vb6Tkinter.dll" If Dir(sf) = "" Then If m_English Then - MsgBox "Please run the setup program in directory of TkinterDesigner.dll", vbInformation + MsgBox "Please run the setup program in directory of Vb6Tkinter.dll", vbInformation Else - MsgBox "请在TkinterDesigner.dll的同一目录下执行此软件。", vbInformation + MsgBox "请在 Vb6Tkinter.dll 的同一目录下执行此软件。", vbInformation End If Exit Sub End If @@ -122,13 +122,13 @@ Private Sub CmdUninstall_Click() Dim sf As String - sf = App.Path & IIf(Right(App.Path, 1) = "\", "", "\") & "TkinterDesigner.dll" + sf = App.Path & IIf(Right(App.Path, 1) = "\", "", "\") & "Vb6Tkinter.dll" If Dir(sf) = "" Then If m_English Then - MsgBox "Please run the setup program in directory of TkinterDesigner.dll", vbInformation + MsgBox "Please run the setup program in directory of Vb6Tkinter.dll", vbInformation Else - MsgBox "请在TkinterDesigner.dll的同一目录下执行此软件。", vbInformation + MsgBox "请在 Vb6Tkinter.dll 的同一目录下执行此软件。", vbInformation End If Exit Sub End If @@ -161,25 +161,25 @@ Private Sub Form_Load() n = GetSystemDefaultLCID() Select Case n Case &H804, &H1004, &H404, &HC04 - Label1.Caption = "这个程序用于注册Tkinter Designer插件,你也可以手工完成:" & vbCrLf & vbCrLf & _ - "1. 运行:regsvr32 /s 你的目录\TkinterDesigner.dll" & vbCrLf & _ + Label1.Caption = "这个程序用于注册Vb6Tkinter插件,你也可以手工完成:" & vbCrLf & vbCrLf & _ + "1. 运行:regsvr32 /s 你的目录\Vb6Tkinter.dll" & vbCrLf & _ "2. 在C:\WINDOWS\VBADDIN.INI的段[Add-Ins32]增加一行:" & vbCrLf & _ - " TkinterDesigner.Connect=3" + " Vb6Tkinter.Connect=3" m_English = False Case Else - CmdSetup.Caption = "Install(&S)" - CmdUninstall.Caption = "Uninstall(&U)" + CmdSetup.Caption = "Register(&R)" + CmdUninstall.Caption = "UnRegister(&U)" CmdQuit.Caption = "Quit(&Q)" - Label1.Caption = "The programe will finish the setup procedure for addin of VB 'TkinterDesigner', you can do it manually too." & vbCrLf & vbCrLf & _ - "1. Run Command : regsvr32 /s path\TkinterDesigner.dll" & vbCrLf & _ - "2. Add a line in section Add-Ins32 of c:\windows\vbaddin.ini:" & vbCrLf & _ - " TkinterDesigner.Connect=3" + Label1.Caption = "The programe will finish the setup procedure for addin of VB 'Vb6Tkinter', you can do it manually too." & vbCrLf & vbCrLf & _ + "1. Run Command : regsvr32 /s path\Vb6Tkinter.dll" & vbCrLf & _ + "2. Add a line in section [Add-Ins32] of c:\windows\vbaddin.ini:" & vbCrLf & _ + " Vb6Tkinter.Connect=3" m_English = True End Select '确认是否已经安装 - CmdUninstall.Enabled = IsRegistered("TkinterDesigner.Connect") + CmdUninstall.Enabled = IsRegistered("Vb6Tkinter.Connect") End Sub diff --git a/Setup/Screenshots/TkinterDesigner_ScrPrnt.JPG b/Setup/Screenshots/TkinterDesigner_ScrPrnt.JPG deleted file mode 100644 index 2db3e26..0000000 Binary files a/Setup/Screenshots/TkinterDesigner_ScrPrnt.JPG and /dev/null differ diff --git a/Setup/Screenshots/TkinterDesigner_ScrPrnt_EN.JPG b/Setup/Screenshots/TkinterDesigner_ScrPrnt_EN.JPG deleted file mode 100644 index 34c9739..0000000 Binary files a/Setup/Screenshots/TkinterDesigner_ScrPrnt_EN.JPG and /dev/null differ diff --git a/Setup/Screenshots/Vb6Tkinter_ScrPrnt.png b/Setup/Screenshots/Vb6Tkinter_ScrPrnt.png new file mode 100644 index 0000000..67c2cc1 Binary files /dev/null and b/Setup/Screenshots/Vb6Tkinter_ScrPrnt.png differ diff --git a/Setup/Screenshots/Vb6Tkinter_ScrPrnt_EN.png b/Setup/Screenshots/Vb6Tkinter_ScrPrnt_EN.png new file mode 100644 index 0000000..c7d4bda Binary files /dev/null and b/Setup/Screenshots/Vb6Tkinter_ScrPrnt_EN.png differ diff --git a/Setup/Setup for Tkinter Designer.vbp b/Setup/Setup for Vb6Tkinter.vbp similarity index 86% rename from Setup/Setup for Tkinter Designer.vbp rename to Setup/Setup for Vb6Tkinter.vbp index 56b49d4..3d8a78d 100644 --- a/Setup/Setup for Tkinter Designer.vbp +++ b/Setup/Setup for Vb6Tkinter.vbp @@ -5,15 +5,15 @@ ResFile32="XP.RES" IconForm="Form1" Startup="Form1" HelpFile="" -Title="Setup for Tkinter Designer" -ExeName32="Setup for TkinterDesigner.exe" +Title="Setup for Vb6Tkinter" +ExeName32="Setup for Vb6Tkinter.exe" Path32="..\Bin" Command32="" -Name="SetupForTkinterDesigner" +Name="SetupForVb6Tkinter" HelpContextID="0" CompatibleMode="0" MajorVer=1 -MinorVer=1 +MinorVer=2 RevisionVer=0 AutoIncrementVer=0 ServerSupportFiles=0 diff --git a/Setup/Setup for Tkinter Designer.vbw b/Setup/Setup for Vb6Tkinter.vbw similarity index 100% rename from Setup/Setup for Tkinter Designer.vbw rename to Setup/Setup for Vb6Tkinter.vbw diff --git a/TkinterDesigner.vbw b/TkinterDesigner.vbw deleted file mode 100644 index f8a389f..0000000 --- a/TkinterDesigner.vbw +++ /dev/null @@ -1,38 +0,0 @@ -GridOcx = 0, 0, 0, 0, C, 175, 175, 1048, 606, C -Common = 125, 125, 998, 556, C -FileDlg = 150, 150, 981, 581, Z -clsBaseControl = 100, 100, 931, 531, -clsButton = 75, 75, 906, 506, -clsCanvas = 0, 0, 0, 0, C -clsCheckbutton = 0, 0, 0, 0, C -clsEntry = 75, 75, 954, 481, -clsLabel = 0, 0, 0, 0, C -clsLabelFrame = 0, 0, 0, 0, C -clsListbox = 0, 0, 0, 0, C -clsOptionMenu = 25, 25, 904, 431, -clsRadiobutton = 0, 0, 0, 0, C -clsScale = 0, 0, 0, 0, C -clsScrollbar = 0, 0, 0, 0, C -clsSerialization = 0, 0, 0, 0, C -clsText = 0, 0, 879, 406, -cStrBuilder = 0, 0, 0, 0, C -Dictionary = 0, 0, 0, 0, C -FrmMain = 25, 25, 898, 456, , 50, 50, 923, 481, C -clsMenu = 0, 0, 0, 0, C -clsMenuItem = 0, 0, 0, 0, C -clsProgressBar = 0, 0, 0, 0, C -clsCombobox = 175, 175, 1054, 581, -clsComboboxAdapter = 0, 0, 0, 0, C -clsTreeview = 200, 200, 1079, 606, -clsNotebook = 50, 50, 929, 456, -MultiLanguage = 0, 0, 0, 0, C -Base64 = 0, 0, 0, 0, C -clsForm = 125, 125, 956, 556, -clsStatusbar = 0, 0, 0, 0, C -Resizer = 0, 0, 0, 0, C -frmOption = 0, 0, 0, 0, C, 200, 200, 1073, 631, C -xpcmdbutton = 0, 0, 0, 0, C, 0, 0, 873, 431, C -clsNotebookTab = 0, 0, 0, 0, C -clsSeparator = 0, 0, 0, 0, C -Connect = 0, 0, 0, 0, C -frmEncodeAFile = 100, 100, 973, 531, , 25, 25, 898, 456, C diff --git a/TkinterDesigner.PDM b/Vb6Tkinter.PDM similarity index 99% rename from TkinterDesigner.PDM rename to Vb6Tkinter.PDM index 8b0bb0b..4fb5880 100644 --- a/TkinterDesigner.PDM +++ b/Vb6Tkinter.PDM @@ -80,7 +80,7 @@ Applicable=Yes [Package|标准安装软件包 1|Distribution] Type=single Size= -Title=Tkinter Designer +Title=Vb6Tkinter [Package|标准安装软件包 1|Package] PackageFolder=D:\My Documents\编程类\Python\pack diff --git a/Bin/Language.lng b/Vb6Tkinter.lng similarity index 96% rename from Bin/Language.lng rename to Vb6Tkinter.lng index fc3ff8e..6915c97 100644 --- a/Bin/Language.lng +++ b/Vb6Tkinter.lng @@ -20,6 +20,8 @@ mnuPythonExe= mnuTools=工具(&T) mnuPreview=界面预览(&P) mnuEncodeAFile=编码磁盘文件为Base64字符串(&B) +mnuCheckUpdate=检查版本更新(&U) +mnuAbout=关于(&A) mnuLanguage=Language(&L) mnuSaveToFile=保存代码到文件(&F) mnuSaveAll=保存全部内容(&A) @@ -40,6 +42,14 @@ lblCharsPerLine=每 cmdBase64It=编码(&E) cmdSaveBase64Result=保存(&S) cmdCancelEncode=退出(&Q) +frmNewVer=发现新版本 +cmdDownload=下载 +cmdSkipVersion=跳过 +cmdCancelVer=取消 +frmAbout=关于 +lblAboutAuthor=cdhigh 作品 +lblAbout1=使用Vb6Tkinter,您可以用最直觉的方法创建您的Tkinter界面 +lblAbout2=访问 获取详细信息 l_staTips=属性解析窗口,在有些属性状态下可以双击变大。 l_staSrl=注意:仅保存那些被选择(选择框被打勾)的配置项。 l_staComps=控件列表窗口,列出对应窗体上所有控件名和控件类型。 @@ -59,6 +69,10 @@ l_msgFrameNotSupportInAbs= l_msgCtlsSupported=支持控件列表: l_msgNoMain=代码中找不到main()函数! l_msgNoClsUi=代码中找不到Application_ui类! +l_msgFetchVerInfoFail=从网络下载版本信息错误。 +l_msgParseVerInfoFail=分析版本信息错误。 +l_msgFoundNewVersion=发现新版本: +l_msgYourVerIsLastest=您的版本是最新的。 l_msgFileNotExist={0} 文件不存在! l_msgCantCancelTTK=窗体中有部分控件仅在TTK库中存在,不能取消TTK选项。 l_msgMusthasVar=OptionMenu(ComboBox)必须要选择variable属性,现在将不生成OptionMenu的代码。 @@ -218,6 +232,8 @@ mnuPythonExe=Set diretory of python.exe(&E)... mnuTools=Tools(&T) mnuPreview=Preview(&P) mnuEncodeAFile=Encode File to Base64(&B) +mnuCheckUpdate=Check Update(&U) +mnuAbout=About(&A) mnuLanguage=Languages(&L) mnuSaveToFile=Save Code to File(&F) mnuSaveAll=Save All Code(&A) @@ -238,6 +254,14 @@ lblCharsPerLine=Chars Per Line cmdBase64It=Encode(&E) cmdSaveBase64Result=Save(&S) cmdCancelEncode=Exit(&Q) +frmNewVer=New version found +cmdDownload=Download +cmdSkipVersion=Skip +cmdCancelVer=Cancel +frmAbout=About +lblAboutAuthor=Made by cdhigh +lblAbout1=With Vb6Tkinter, you can create your Tkinter UI in the most intuitive way +lblAbout2=Visit for more detailed information l_staTips=Tips of properties. l_staSrl=Save Config to file. l_staComps=List of controls. @@ -257,6 +281,10 @@ l_msgFrameNotSupportInAbs=The control 'Frame' is not support when menu 'Use Rela l_msgCtlsSupported=Controls supported: l_msgNoMain=Function 'main()' no founded in code! l_msgNoClsUi=Class 'Application_ui' no founded in code! +l_msgFetchVerInfoFail=Error fetching version update information. +l_msgParseVerInfoFail=Unable to parse the version information. +l_msgFoundNewVersion=Found new version: +l_msgYourVerIsLastest=Your version is lastest. l_msgFileNotExist=File '{0}' not exist! l_msgCantCancelTTK=Can't uncheck the menu 'Use TTK Themed Library' for has some widgets specified in TTK. l_msgMusthasVar='variable' is obligatory for OptionMenu(ComboBox), will not generate code for OptionMenu({0}) now. diff --git a/TkinterDesigner.vbp b/Vb6Tkinter.vbp similarity index 81% rename from TkinterDesigner.vbp rename to Vb6Tkinter.vbp index ea2e800..1686c78 100644 --- a/TkinterDesigner.vbp +++ b/Vb6Tkinter.vbp @@ -1,9 +1,11 @@ Type=OleDll Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\Windows\SysWOW64\stdole2.tlb#OLE Automation -Reference=*\G{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}#2.0#0#C:\Program Files (x86)\VB6Expr\MSO97RT.DLL#Microsoft Office 8.0 Object Library +Reference=*\G{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}#2.0#0#C:\Program Files (x86)\office2010\MShared\OFFICE14\MSO.DLL#Microsoft Office 8.0 Object Library Reference=*\G{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}#1.0#0#C:\Program Files (x86)\Common Files\designer\MSADDNDR.TLB#Add-In Designer/Instance Control Library Reference=*\G{EF404E00-EDA6-101A-8DAF-00DD010F7EBB}#5.3#0#C:\Program Files (x86)\VB6Expr\VB6EXT.OLB#Microsoft Visual Basic 6.0 Extensibility Reference=*\G{2A75196C-D9EB-4129-B803-931327F72D5C}#2.8#0#C:\Program Files (x86)\Common Files\System\ado\msado28.tlb#Microsoft ActiveX Data Objects 2.8 Library +Reference=*\G{662901FC-6951-4854-9EB2-D9A2570F2B2E}#5.1#0#C:\Windows\system32\winhttp.dll#Microsoft WinHTTP Services, version 5.1 +Object={831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.2#0; MSCOMCTL.OCX UserControl=GridOcx.ctl Module=Common; Common.bas Module=FileDlg; FileDlg.bas @@ -42,31 +44,34 @@ Class=clsNotebookTab; clsNotebookTab.cls Class=clsSeparator; clsSeparator.cls Class=Connect; Connect.cls Form=frmEncodeAFile.frm -Object={831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.2#0; MSCOMCTL.OCX +Module=http; http.bas +Module=modJson; modJson.bas +Form=frmNewVer.frm +Form=frmAbout.frm ResFile32="XP.RES" IconForm="FrmMain" Startup="(None)" HelpFile="" -Title="TkinterDesigner" -ExeName32="TkinterDesigner.dll" +Title="Vb6Tkinter" +ExeName32="Vb6Tkinter.dll" Path32="Bin" Command32="" -Name="TkinterDesigner" +Name="Vb6Tkinter" HelpContextID="0" -Description="TkinterDesigner" +Description="VB6 Tkinter Designer" CompatibleMode="2" -CompatibleEXE32="Bin\TkinterDesigner.dll" +CompatibleEXE32="Bin\Vb6Tkinter.dll" VersionCompatible32="1" MajorVer=1 -MinorVer=6 -RevisionVer=8 +MinorVer=7 +RevisionVer=0 AutoIncrementVer=0 ServerSupportFiles=0 DllBaseAddress=&H1f390000 -VersionComments="GUI Designer for Tkinter(Python). A addin for VB6" +VersionComments="GUI Designer for Tkinter(Python). A add-in for VB6" VersionCompanyName="https://github.com/cdhigh" VersionFileDescription="GUI Designer for Tkinter(Python)" -VersionProductName="Tkinter Designer" +VersionProductName="VB6 Tkinter Designer" CompilationType=0 OptimizationType=0 FavorPentiumPro(tm)=-1 @@ -83,6 +88,7 @@ Retained=0 ThreadPerObject=0 MaxNumberOfThreads=1 DebugStartupOption=0 +UseExistingBrowser=0 [MS Transaction Server] AutoRefresh=1 diff --git a/Vb6Tkinter.vbw b/Vb6Tkinter.vbw new file mode 100644 index 0000000..c7e5553 --- /dev/null +++ b/Vb6Tkinter.vbw @@ -0,0 +1,42 @@ +GridOcx = 125, 125, 851, 574, C, 175, 175, 1048, 606, C +Common = 125, 125, 998, 556, C +FileDlg = 150, 150, 981, 581, C +clsBaseControl = 100, 100, 931, 531, C +clsButton = 75, 75, 906, 506, C +clsCanvas = 0, 0, 0, 0, C +clsCheckbutton = 0, 0, 0, 0, C +clsEntry = 75, 75, 954, 481, C +clsLabel = 0, 0, 0, 0, C +clsLabelFrame = 0, 0, 0, 0, C +clsListbox = 0, 0, 0, 0, C +clsOptionMenu = 25, 25, 904, 431, C +clsRadiobutton = 0, 0, 0, 0, C +clsScale = 0, 0, 0, 0, C +clsScrollbar = 0, 0, 0, 0, C +clsSerialization = 0, 0, 0, 0, C +clsText = 0, 0, 879, 406, C +cStrBuilder = 0, 0, 0, 0, C +Dictionary = 0, 0, 0, 0, C +FrmMain = 25, 25, 898, 456, C, 50, 50, 923, 481, C +clsMenu = 0, 0, 0, 0, C +clsMenuItem = 0, 0, 0, 0, C +clsProgressBar = 0, 0, 0, 0, C +clsCombobox = 175, 175, 1054, 581, C +clsComboboxAdapter = 0, 0, 0, 0, C +clsTreeview = 200, 200, 1079, 606, C +clsNotebook = 50, 50, 929, 456, C +MultiLanguage = 175, 175, 1054, 608, Z +Base64 = 0, 0, 0, 0, C +clsForm = 125, 125, 956, 556, C +clsStatusbar = 75, 75, 801, 497, C +Resizer = 100, 100, 826, 549, C +frmOption = 0, 0, 0, 0, C, 200, 200, 1073, 631, C +xpcmdbutton = 0, 0, 0, 0, C, 0, 0, 873, 431, C +clsNotebookTab = 0, 0, 0, 0, C +clsSeparator = 0, 0, 0, 0, C +Connect = 25, 25, 904, 458, +frmEncodeAFile = 100, 100, 973, 531, C, 25, 25, 898, 456, C +http = 125, 125, 1004, 558, C +modJson = 25, 25, 904, 458, C +frmNewVer = 100, 100, 979, 533, C, 75, 75, 954, 508, C +frmAbout = 50, 50, 776, 472, C, 25, 25, 927, 447, C diff --git a/about.gif b/about.gif new file mode 100644 index 0000000..4f04566 Binary files /dev/null and b/about.gif differ diff --git a/clsStatusbar.cls b/clsStatusbar.cls index ae89de1..f746fc3 100644 --- a/clsStatusbar.cls +++ b/clsStatusbar.cls @@ -31,8 +31,9 @@ Const DefineStatusbar1 As String = "class Statusbar(Frame):" & vbCrLf & _ " def __init__(self, master, **kw):" & vbCrLf & _ " """ & """" & """Options:" & vbCrLf & _ " panelwidths - a tuple of width of panels, atual number of panels is len(panelwidths)+1." & vbCrLf & _ -" """ & """" & """" & vbCrLf & _ -" Frame.__init__(self, master)" & vbCrLf & _ +" """ & """" & """" & vbCrLf + +Const DefineStatusbar2 As String = vbCrLf & _ " panelwidths = kw['panelwidths'] if 'panelwidths' in kw else []" & vbCrLf & _ " self.lbls = []" & vbCrLf & _ " for pnlwidth in panelwidths:" & vbCrLf & _ @@ -43,7 +44,7 @@ Const DefineStatusbar1 As String = "class Statusbar(Frame):" & vbCrLf & _ " self.lbls.append(lbl)" & vbCrLf & _ " lbl.pack(fill=BOTH, expand=1)" & vbCrLf & vbCrLf -Const DefineStatusbar2 As String = " def set(self, panel, format, *args):" & vbCrLf & _ +Const DefineStatusbar3 As String = " def set(self, panel, format, *args):" & vbCrLf & _ " if panel >= len(self.lbls): raise IndexError" & vbCrLf & _ " self.lbls[panel]['text'] = format % args" & vbCrLf & _ " self.lbls[panel].update_idletasks()" & vbCrLf & vbCrLf & _ @@ -63,8 +64,15 @@ Private m_Base As clsBaseControl Private m_CanbeOutByMainForm As Boolean '输出状态栏控件的定义 -Public Property Get WidgetCode() As String - WidgetCode = DefineStatusbar1 & DefineStatusbar2 +'OutOnlyV3: True-仅输出Python3代码,False-输出兼容Python2/3的代码 +Public Property Get WidgetCode(OutOnlyV3 As Boolean) As String + Dim sInit As String + If OutOnlyV3 Then + sInit = " super().__init__(master)" + Else + sInit = " Frame.__init__(self, master)" + End If + WidgetCode = DefineStatusbar1 & sInit & DefineStatusbar2 End Property '输出PYTHON代码, diff --git a/developer.md b/developer.md index 34a9ef7..c2a30b0 100644 --- a/developer.md +++ b/developer.md @@ -1,4 +1,4 @@ -濡傛灉鎵撳紑宸ョ▼TkinterDesigner.vbp澶辫触锛屾彁绀哄璞″簱鏈敞鍐岋紝涓鑸槸Windows Common Controls 6.0 (mscomctl.ocx)鏈垚鍔熷姞杞姐 +濡傛灉鎵撳紑宸ョ▼Vb6Tkinter.vbp澶辫触锛屾彁绀哄璞″簱鏈敞鍐岋紝涓鑸槸Windows Common Controls 6.0 (mscomctl.ocx)鏈垚鍔熷姞杞姐 鍙互鍏堝皾璇曟敞鍐 'regsvr32 mscomctl.ocx'锛屽鏋滆繕涓嶆垚鍔燂紝鍒欏彲浠 'regtlib msdatsrc.tlb'銆 鑷充簬 mscomctl.ocx/msdatsrc.tlb 鍦ㄥ摢涓洰褰曪紝涓嶅悓鐗堟湰浣嶇疆涓嶅悓锛屾悳绱竴涓嬪嵆鍙 diff --git a/frmAbout.frm b/frmAbout.frm new file mode 100644 index 0000000..18c67ee --- /dev/null +++ b/frmAbout.frm @@ -0,0 +1,123 @@ +VERSION 5.00 +Begin VB.Form frmAbout + BorderStyle = 1 'Fixed Single + Caption = "About" + ClientHeight = 4230 + ClientLeft = 4755 + ClientTop = 3660 + ClientWidth = 10830 + Icon = "frmAbout.frx":0000 + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 4230 + ScaleWidth = 10830 + Begin VB.PictureBox picAbout + BorderStyle = 0 'None + Height = 3735 + Left = 240 + Picture = "frmAbout.frx":058A + ScaleHeight = 3735 + ScaleWidth = 3975 + TabIndex = 0 + Top = 240 + Width = 3975 + End + Begin VB.Label lblAbout2 + Caption = "Visit for more detailed information" + BeginProperty Font + Name = "宋体" + Size = 14.25 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + ForeColor = &H00000040& + Height = 975 + Left = 4440 + TabIndex = 4 + Top = 2760 + Width = 6015 + End + Begin VB.Label lblAbout1 + Caption = "With Vb6Tkinter, you can create your Tkinter UI in the most intuitive way" + BeginProperty Font + Name = "宋体" + Size = 14.25 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + ForeColor = &H00000040& + Height = 975 + Left = 4440 + TabIndex = 3 + Top = 1680 + Width = 6015 + End + Begin VB.Label lblAboutAuthor + Caption = "Made by cdhigh" + BeginProperty Font + Name = "宋体" + Size = 14.25 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + ForeColor = &H00000040& + Height = 495 + Left = 4440 + TabIndex = 2 + Top = 840 + Width = 6015 + End + Begin VB.Label lblAboutVer + Caption = "Vb6Tkinter v1.7.0" + BeginProperty Font + Name = "宋体" + Size = 14.25 + Charset = 134 + Weight = 700 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + ForeColor = &H00000040& + Height = 495 + Left = 4440 + TabIndex = 1 + Top = 240 + Width = 6015 + End +End +Attribute VB_Name = "frmAbout" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Option Explicit + +Private Sub Form_Load() + lblAboutVer.Caption = "Vb6Tkinter v" & g_AppVerString + + '多语种支持 + Me.Caption = L(Me.Name, Me.Caption) + lblAboutAuthor.Caption = L("lblAboutAuthor", "Made by cdhigh") + lblAbout1.Caption = L("lblAbout1", "With Vb6Tkinter, you can create your Tkinter UI in the most intuitive way") + lblAbout2.Caption = L("lblAbout2", "Visit for more detailed information") +End Sub + +Private Sub lblAbout2_Click() + Call ShellExecute(FrmMain.hWnd, "open", OFFICIAL_SITE, vbNullString, vbNullString, &H0) + Unload Me +End Sub + +Private Sub picAbout_Click() + Unload Me +End Sub diff --git a/frmAbout.frx b/frmAbout.frx new file mode 100644 index 0000000..18b34ce Binary files /dev/null and b/frmAbout.frx differ diff --git a/frmEncodeAFile.frm b/frmEncodeAFile.frm index 97d60fd..b0bb130 100644 --- a/frmEncodeAFile.frm +++ b/frmEncodeAFile.frm @@ -30,7 +30,7 @@ Begin VB.Form frmEncodeAFile Top = 720 Width = 975 End - Begin TkinterDesigner.xpcmdbutton cmdCancelEncode + Begin Vb6Tkinter.xpcmdbutton cmdCancelEncode Height = 495 Left = 10320 TabIndex = 6 @@ -49,7 +49,7 @@ Begin VB.Form frmEncodeAFile Strikethrough = 0 'False EndProperty End - Begin TkinterDesigner.xpcmdbutton cmdSaveBase64Result + Begin Vb6Tkinter.xpcmdbutton cmdSaveBase64Result Height = 495 Left = 5640 TabIndex = 5 @@ -68,7 +68,7 @@ Begin VB.Form frmEncodeAFile Strikethrough = 0 'False EndProperty End - Begin TkinterDesigner.xpcmdbutton cmdBase64It + Begin Vb6Tkinter.xpcmdbutton cmdBase64It Height = 495 Left = 960 TabIndex = 4 @@ -97,7 +97,7 @@ Begin VB.Form frmEncodeAFile Top = 1200 Width = 12975 End - Begin TkinterDesigner.xpcmdbutton cmdChooseSourceToEncode + Begin Vb6Tkinter.xpcmdbutton cmdChooseSourceToEncode Height = 375 Left = 12480 TabIndex = 2 diff --git a/frmNewVer.frm b/frmNewVer.frm new file mode 100644 index 0000000..13d720f --- /dev/null +++ b/frmNewVer.frm @@ -0,0 +1,95 @@ +VERSION 5.00 +Begin VB.Form frmNewVer + BorderStyle = 1 'Fixed Single + Caption = "New version found" + ClientHeight = 2595 + ClientLeft = 5955 + ClientTop = 4425 + ClientWidth = 6900 + Icon = "frmNewVer.frx":0000 + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 2595 + ScaleWidth = 6900 + Begin Vb6Tkinter.xpcmdbutton cmdCancelVer + Height = 615 + Left = 4200 + TabIndex = 2 + Top = 1680 + Width = 2175 + _ExtentX = 3836 + _ExtentY = 1085 + Caption = "Cancel" + BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + End + Begin Vb6Tkinter.xpcmdbutton cmdDownload + Height = 615 + Left = 600 + TabIndex = 1 + Top = 1680 + Width = 2175 + _ExtentX = 3836 + _ExtentY = 1085 + Caption = "Download" + BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + End + Begin VB.Label lblInfo + BeginProperty Font + Name = "宋体" + Size = 15.75 + Charset = 134 + Weight = 700 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Height = 735 + Left = 960 + TabIndex = 0 + Top = 480 + Width = 5655 + End +End +Attribute VB_Name = "frmNewVer" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Option Explicit + +Private Sub cmdCancelVer_Click() + Unload Me +End Sub + +Private Sub cmdDownload_Click() + Call ShellExecute(FrmMain.hWnd, "open", OFFICIAL_RELEASES, vbNullString, vbNullString, &H0) +End Sub + +Private Sub Form_Load() + Dim ctl As Control + + '多语种支持 + Me.Caption = L(Me.Name, Me.Caption) + For Each ctl In Me.Controls + If TypeName(ctl) = "xpcmdbutton" Then + ctl.Caption = L(ctl.Name, ctl.Caption) + End If + Next +End Sub diff --git a/frmNewVer.frx b/frmNewVer.frx new file mode 100644 index 0000000..75a8682 Binary files /dev/null and b/frmNewVer.frx differ diff --git a/frmOption.frm b/frmOption.frm index c21c96f..2c5833d 100644 --- a/frmOption.frm +++ b/frmOption.frm @@ -24,7 +24,7 @@ Begin VB.Form frmOption ScaleWidth = 8010 ShowInTaskbar = 0 'False StartUpPosition = 2 '屏幕中心 - Begin TkinterDesigner.xpcmdbutton cmdOptionCancel + Begin Vb6Tkinter.xpcmdbutton cmdOptionCancel Height = 375 Left = 5640 TabIndex = 5 @@ -43,7 +43,7 @@ Begin VB.Form frmOption Strikethrough = 0 'False EndProperty End - Begin TkinterDesigner.xpcmdbutton cmdOptionOK + Begin Vb6Tkinter.xpcmdbutton cmdOptionOK Height = 375 Left = 3000 TabIndex = 4 @@ -62,7 +62,7 @@ Begin VB.Form frmOption Strikethrough = 0 'False EndProperty End - Begin TkinterDesigner.xpcmdbutton cmdOptionApply + Begin Vb6Tkinter.xpcmdbutton cmdOptionApply Height = 375 Left = 360 TabIndex = 3 @@ -81,7 +81,7 @@ Begin VB.Form frmOption Strikethrough = 0 'False EndProperty End - Begin TkinterDesigner.xpcmdbutton cmdPythonExe + Begin Vb6Tkinter.xpcmdbutton cmdPythonExe Height = 255 Left = 7080 TabIndex = 2 diff --git a/http.bas b/http.bas new file mode 100644 index 0000000..812a250 --- /dev/null +++ b/http.bas @@ -0,0 +1,37 @@ +Attribute VB_Name = "http" +Option Explicit +'连接网络获取信息,需要引用 "Microsoft WinHTTP Services, version 5.1" + +'参数:sUrl,URL +'参数:postData,post内容(如果为POST) +'参数:method,方法,为"POST"或"GET" +'参数:cookies,post或get带上的cookie +'返回:post或get返回的内容 +Public Function HttpGetResponse(sUrl As String, Optional ByVal postData As String = "", Optional ByVal method As String = "GET", Optional ByVal cookies As String = "") As String + Dim request As winhttp.WinHttpRequest + If Len(Trim(cookies)) = 0 Then + cookies = "a:x," ' cookie为空则随便弄个cookie,不然容易报错 + End If + + On Error Resume Next + Set request = CreateObject("WinHttp.WinHttpRequest.5.1") + + With request + .Open UCase(method), sUrl, True 'True:同步接收数据 + .SetTimeouts 30000, 30000, 30000, 30000 '设置超时时间为30s + .Option(WinHttpRequestOption_SslErrorIgnoreFlags) = &H3300 '非常重要(忽略错误) + .SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" + .SetRequestHeader "Accept", "text/html, application/xhtml+xml, */*" + .SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" + .SetRequestHeader "Cookie", cookies + .SetRequestHeader "Content-Length", Len(postData) + .Send postData '' 开始发送 + + .WaitForResponse '等待请求 + 'MsgBox WinHttp.Status'请求状态 + HttpGetResponse = .ResponseText '得到返回文本(或者是其它) + End With + Set request = Nothing +End Function + + diff --git a/modJson.bas b/modJson.bas new file mode 100644 index 0000000..6231968 --- /dev/null +++ b/modJson.bas @@ -0,0 +1,529 @@ +Attribute VB_Name = "modJson" +Option Explicit +'VB6 原生JSON解析库,没有引用JS库 +'使用方法: +'调用 ParseJSONString() 函数或者 ParseJSONString2() 过程来解析 JSON 字符串,得到一个返回的 Variant 类型的变量 +'数值类型被解析为 Long 或者 Currency,取决于数值的范围,数值比较小就用 Long,比较大就用 Currency,而如果数值包含小数点或者科学计数法,则使用 Double 类型。 +'JSON 字符串被解析为 VB 字符串,其中字符串的转义字符 \ 会按规范进行转义。 +'列表 [] 被解析为 VB6 的 Variant 数组,每个数组元素都可以是不同的类型。 +'对象 {} 被解析为字典(Scripting.Dictionary)。注意 对象变量需要用 Set 来赋值。 +'函数 JSONToString() 做相反的工作:把解析出来的 Variant 转换回 JSON 字符串。 +'ParseJSONString: 使用函数返回值保存解析后的Variant,要根据目标类型,使用"set varName=ParseJSONString(str)"或"varName=ParseJSONString(str)" +'ParseJSONString2: 使用传入参数返回,不管是否是对象类型都可以正常工作,ParseJSONString2(str, retVariant) +'得到解析结果后,如何判断 Variant 的具体类型? +'先判断它是不是对象,使用 IsObject() 来判断。 +'如果不是对象,此时判断它是不是数组,使用 IsArray() 来判断。 +'如果不是数组,则需要判断它是不是字符串,先用 VarType() 来获取 Variant 的类型号,然后判断类型号是不是 vbString。 +'不能直接用 IsNumeric() 进行判断,因为它会把字符串格式存储的数值也判定为是数值。 +'如果不是字符串,那它应该是数值了。根据刚才调用的 VarType() 的返回值,可以判断它是否为 Long、Currency、Double。类型号分别为 vbLong、vbCurrency、vbDouble。 + +Private Type ParserContext + JSONString As String + I As Long + Length As Long + LineNo As Long + Column As Long +End Type + +Const JSONErrCode As Long = 2000 + +Private Function IsSpace(ByVal Char As String) As Boolean +IsSpace = True +Select Case Char +Case vbCr +Case vbLf +Case vbTab +Case " " +Case Else + IsSpace = False +End Select +End Function + +Private Function GetPositionString(Ctx As ParserContext) As String +GetPositionString = "line " & Ctx.LineNo & " column " & Ctx.Column +End Function + +Private Function IsEndOfString(Ctx As ParserContext) As Boolean +IsEndOfString = Ctx.I > Ctx.Length +End Function + +Private Function PeekChar(Ctx As ParserContext) As String +PeekChar = Mid$(Ctx.JSONString, Ctx.I, 1) +End Function + +Private Sub SkipChar(Ctx As ParserContext, PeekedChar As String) +Ctx.I = Ctx.I + 1 +If PeekedChar = vbLf Then + Ctx.LineNo = Ctx.LineNo + 1 + Ctx.Column = 1 +Else + Ctx.Column = Ctx.Column + 1 +End If +End Sub + +Private Function GetChar(Ctx As ParserContext) As String +GetChar = PeekChar(Ctx) +SkipChar Ctx, GetChar +End Function + +Private Sub SkipSpaces(Ctx As ParserContext) +Dim CurChar As String +Do + CurChar = PeekChar(Ctx) + If IsSpace(CurChar) = False Then Exit Do + SkipChar Ctx, CurChar +Loop +End Sub + +Private Function HexCharToVal(ByVal HexCharAsc As Long) As Long +If HexCharAsc >= &H30 And HexCharAsc <= &H39 Then + HexCharToVal = HexCharAsc - &H30 +ElseIf HexCharAsc >= &H41 And HexCharAsc <= &H46 Then + HexCharToVal = HexCharAsc - &H41 + 10 +ElseIf HexCharAsc >= &H61 And HexCharAsc <= &H66 Then + HexCharToVal = HexCharAsc - &H61 + 10 +Else + Err.Raise JSONErrCode, "JSON Parser" +End If +End Function + +Private Function ParseString(Ctx As ParserContext, Optional ByVal IsObjectKey As Boolean = False) As String +Dim CurChar As String +Dim Escape As Boolean +Dim EscapeHex As Boolean +Dim HexNumDigits As Long +Dim HexVal As Long +Dim StartLineNo As Long, StartColumn As Long +StartLineNo = Ctx.LineNo +StartColumn = Ctx.Column - 1 +Do + CurChar = GetChar(Ctx) + If Len(CurChar) = 0 Then Err.Raise JSONErrCode, "JSON Parser", "Unterminated string starting at " & "line " & StartLineNo & " column " & StartColumn + If Escape Then + If EscapeHex Then + HexVal = HexVal * &H10 + HexCharToVal(AscW(CurChar)) + HexNumDigits = HexNumDigits + 1 + If HexNumDigits = 4 Then + If IsObjectKey And HexVal < &H20 Then Err.Raise JSONErrCode, "JSON Parser", "Invalid control character at " & GetPositionString(Ctx) + ParseString = ParseString & ChrW$(HexVal) + EscapeHex = False + Escape = False + End If + Else + Escape = False + Select Case CurChar + Case """" + ParseString = ParseString & CurChar + Case "\" + ParseString = ParseString & CurChar + Case "/" + ParseString = ParseString & CurChar + Case "b" + ParseString = ParseString & vbBack + Case "f" + ParseString = ParseString & vbFormFeed + Case "n" + ParseString = ParseString & vbLf + Case "r" + ParseString = ParseString & vbCr + Case "t" + ParseString = ParseString & vbTab + Case "u" + Escape = True + EscapeHex = True + HexNumDigits = 0 + HexVal = 0 + Err.Description = "Invalid \uXXXX escape at " & GetPositionString(Ctx) + Case Else + Err.Raise JSONErrCode, "JSON Parser", "Invalid \escape at " & GetPositionString(Ctx) + End Select + End If + Else + If IsObjectKey And AscW(CurChar) < &H20 Then Err.Raise JSONErrCode, "JSON Parser", "Invalid control character at " & GetPositionString(Ctx) + If CurChar = "\" Then + Escape = True + ElseIf CurChar = """" Then + Exit Do + Else + ParseString = ParseString & CurChar + End If + End If +Loop +End Function + +Private Function GetNumeric(Ctx As ParserContext) As String +Dim CurChar As String +Do + CurChar = PeekChar(Ctx) + If IsNumeric(CurChar) Then + GetNumeric = GetNumeric & CurChar + SkipChar Ctx, CurChar + Else + Exit Do + End If +Loop +If Len(GetNumeric) = 0 Then Err.Raise JSONErrCode, "JSON Parser", "Expecting value at " & GetPositionString(Ctx) +End Function + +Private Function NumericToInteger(Numeric As String) As Variant +On Error GoTo Try1 + +NumericToInteger = CLng(Numeric) +Exit Function + +Try1: +NumericToInteger = CCur(Numeric) +End Function + +Private Function NumericToVariant(Numeric As String) As Variant +On Error GoTo Try1 + +NumericToVariant = NumericToInteger(Numeric) +Exit Function + +Try1: +NumericToVariant = CDbl(Numeric) +End Function + +Private Function ParseNumber(Ctx As ParserContext, ByVal FirstChar As String) As Variant +Dim IsSigned As Boolean +Dim NumberString As String +Dim CurChar As String +Dim IsSignedExp As Boolean + +If FirstChar = "-" Then + IsSigned = True + SkipChar Ctx, FirstChar +End If +NumberString = GetNumeric(Ctx) +ParseNumber = NumericToVariant(NumberString) + +CurChar = PeekChar(Ctx) +If CurChar = "." Then + SkipChar Ctx, CurChar + NumberString = GetNumeric(Ctx) + ParseNumber = CDbl(ParseNumber) + CDbl(NumberString) / (10 ^ Len(NumberString)) +End If + +CurChar = PeekChar(Ctx) +If LCase$(CurChar) = "e" Then + SkipChar Ctx, CurChar + CurChar = PeekChar(Ctx) + If CurChar = "-" Then + SkipChar Ctx, CurChar + IsSignedExp = True + End If + NumberString = GetNumeric(Ctx) + If IsSignedExp Then NumberString = "-" & NumberString + ParseNumber = CDbl(ParseNumber) * (10 ^ CDbl(NumberString)) +End If + +If IsSigned Then ParseNumber = -ParseNumber +End Function + +Function IsEmptyArray(TestArray As Variant) As Boolean +IsEmptyArray = True +On Local Error Resume Next +Dim I As Long +I = -1 +I = UBound(TestArray) +If I >= 0 Then IsEmptyArray = False +End Function + +Private Function ParseList(Ctx As ParserContext) As Variant +Dim CurChar As String +Dim RetList() As Variant +Dim ItemCount As Long + +SkipSpaces Ctx +CurChar = PeekChar(Ctx) +If CurChar = "]" Then + SkipChar Ctx, CurChar + ParseList = RetList + Exit Function +End If + +ReDim RetList(8) +Do + ParseSubString Ctx, RetList(ItemCount) + ItemCount = ItemCount + 1 + If ItemCount >= UBound(RetList) + 1 Then ReDim Preserve RetList(ItemCount * 3 / 2 + 1) + + SkipSpaces Ctx + CurChar = PeekChar(Ctx) + If CurChar = "]" Then + SkipChar Ctx, CurChar + If ItemCount Then + ReDim Preserve RetList(ItemCount - 1) + Else + Erase RetList + End If + ParseList = RetList + Exit Function + ElseIf CurChar = "," Then + SkipChar Ctx, CurChar + Else + Err.Raise JSONErrCode, "JSON Parser", "Unexpected `" & CurChar & "` at " & GetPositionString(Ctx) + End If +Loop + +End Function + +Private Function ParseObject(Ctx As ParserContext) As Variant +Dim JObject As Object +Dim SubItem As Variant +Dim CurChar As String + +Set JObject = CreateObject("Scripting.Dictionary") + +SkipSpaces Ctx +CurChar = PeekChar(Ctx) +If CurChar = "}" Then + SkipChar Ctx, CurChar + Set ParseObject = JObject + Exit Function +End If + +Dim KeyName As String +Do + CurChar = PeekChar(Ctx) + If CurChar = """" Then + SkipChar Ctx, CurChar + KeyName = ParseString(Ctx, True) + ElseIf CurChar = "'" Then + Err.Raise JSONErrCode, "JSON Parser", "Expecting property name enclosed in double quotes at " & GetPositionString(Ctx) + Else + Err.Raise JSONErrCode, "JSON Parser", "Key name must be string at " & GetPositionString(Ctx) + End If + + SkipSpaces Ctx + CurChar = PeekChar(Ctx) + If CurChar <> ":" Then Err.Raise JSONErrCode, "JSON Parser", "Expecting ':' delimiter at " & GetPositionString(Ctx) + SkipChar Ctx, CurChar + SkipSpaces Ctx + ParseSubString Ctx, SubItem + JObject.Add KeyName, SubItem + + SkipSpaces Ctx + CurChar = PeekChar(Ctx) + If CurChar = "}" Then + SkipChar Ctx, CurChar + Exit Do + ElseIf CurChar = "," Then + SkipChar Ctx, CurChar + SkipSpaces Ctx + Else + Err.Raise JSONErrCode, "JSON Parser", "Expecting ',' delimiter at " & GetPositionString(Ctx) + End If +Loop + +Set ParseObject = JObject +End Function + +Private Function ParseBoolean(Ctx As ParserContext, ByVal ExpectedValue As Boolean) As Variant +Dim CurChar As String +Dim Word As String, ExpectedWord As String +Dim I As Long + +If ExpectedValue = False Then + ExpectedWord = "false" +Else + ExpectedWord = "true" +End If + +For I = 1 To Len(ExpectedWord) + CurChar = GetChar(Ctx) + If Len(CurChar) Then Word = Word & CurChar Else Err.Raise JSONErrCode, "JSON Parser", "Expecting value at " & GetPositionString(Ctx) +Next +If Word = ExpectedWord Then + ParseBoolean = ExpectedValue +Else + Err.Raise JSONErrCode, "JSON Parser", "Unknown identifier `" & Word & "` at " & GetPositionString(Ctx) +End If + +End Function + +Private Function ParseNull(Ctx As ParserContext) As Variant +Dim CurChar As String +Dim Word As String, ExpectedWord As String +Dim I As Long + +ExpectedWord = "null" + +For I = 1 To Len(ExpectedWord) + CurChar = GetChar(Ctx) + If Len(CurChar) Then Word = Word & CurChar Else Err.Raise JSONErrCode, "JSON Parser", "Expecting value at " & GetPositionString(Ctx) +Next +If Word <> ExpectedWord Then + Err.Raise JSONErrCode, "JSON Parser", "Unknown identifier `" & Word & "` at " & GetPositionString(Ctx) +End If +End Function + +Private Sub ParseSubString(Ctx As ParserContext, outParsed As Variant) +SkipSpaces Ctx +If IsEndOfString(Ctx) Then Err.Raise JSONErrCode, "JSON Parser", "Expecting value at " & GetPositionString(Ctx) + +Dim CurChar As String +CurChar = PeekChar(Ctx) +If CurChar = """" Then + SkipChar Ctx, CurChar + outParsed = ParseString(Ctx) +ElseIf IsNumeric(CurChar) = True Or CurChar = "-" Then + outParsed = ParseNumber(Ctx, CurChar) +ElseIf CurChar = "[" Then + SkipChar Ctx, CurChar + outParsed = ParseList(Ctx) +ElseIf CurChar = "{" Then + SkipChar Ctx, CurChar + Set outParsed = ParseObject(Ctx) +ElseIf CurChar = "t" Then + outParsed = ParseBoolean(Ctx, True) +ElseIf CurChar = "f" Then + outParsed = ParseBoolean(Ctx, False) +ElseIf CurChar = "n" Then + outParsed = ParseNull(Ctx) +Else + Err.Raise JSONErrCode, "JSON Parser", "Unexpected `" & CurChar & "` at " & GetPositionString(Ctx) +End If +End Sub + +Private Function NewParserContext(JSONString As String) As ParserContext +With NewParserContext +.JSONString = JSONString +.I = 1 +.Length = Len(JSONString) +.LineNo = 1 +.Column = 1 +End With +End Function + +Function ParseJSONString(JSONString As String) As Variant +Dim Ctx As ParserContext +Ctx = NewParserContext(JSONString) +ParseSubString Ctx, ParseJSONString +SkipSpaces Ctx +'commented by cdhigh, ignore error +'If IsEndOfString(Ctx) = False Then Err.Raise JSONErrCode, "JSON Parser", "Extra data at " & GetPositionString(Ctx) +End Function + +Sub ParseJSONString2(JSONString As String, ReturnParsed As Variant) +Dim Ctx As ParserContext +Ctx = NewParserContext(JSONString) +ParseSubString Ctx, ReturnParsed +SkipSpaces Ctx +'commented by cdhigh, ignore error +'If IsEndOfString(Ctx) = False Then Err.Raise JSONErrCode, "JSON Parser", "Extra data at " & GetPositionString(Ctx) +End Sub + +Private Function Hex4(ByVal Value As Long) As String +Hex4 = Right$("000" & Hex$(Value), 4) +End Function + +Private Function EscapeString(ByVal SourceStr As String) As String +Dim I As Long, EI As Long, CurChar As String, CharCode As Long, ToAppend As String + +EI = Len(SourceStr) +For I = 1 To EI + CurChar = Mid$(SourceStr, I, 1) + CharCode = CLng(AscW(CurChar)) And &HFFFF& + Select Case CharCode + Case 0 + ToAppend = "\0" + Case 1 To 7, &HB, &HE To &H1F, &HD800& To &HDFFF& + ToAppend = "\u" & Hex4(CharCode) + Case 8 + ToAppend = "\b" + Case 9 + ToAppend = "\t" + Case &HA + ToAppend = "\n" + Case &HC + ToAppend = "\f" + Case &HD + ToAppend = "\r" + Case &H22 + ToAppend = "\""" + Case &H5C + ToAppend = "\\" + Case Else + ToAppend = CurChar + End Select + EscapeString = EscapeString & ToAppend +Next +End Function + +Function JSONToString(JSONData As Variant, Optional ByVal Indent As Long = 0, Optional ByVal IndentChar = " ", Optional ByVal CurIndentLevel As Long = 0) As String +If IsArray(JSONData) Then + If IsEmptyArray(JSONData) Then + JSONToString = "[]" + Exit Function + End If + Dim I As Long, U As Long + U = UBound(JSONData) + JSONToString = "[" + CurIndentLevel = CurIndentLevel + 1 + If Indent Then GoSub IndentNextLine + For I = 0 To U + JSONToString = JSONToString & JSONToString(JSONData(I), Indent, IndentChar, CurIndentLevel + 1) + If I <> U Then + JSONToString = JSONToString & "," + If Indent Then GoSub IndentNextLine + End If + Next + CurIndentLevel = CurIndentLevel - 1 + If Indent Then GoSub IndentNextLine + JSONToString = JSONToString & "]" +ElseIf IsObject(JSONData) Then + Dim JObj As Object, KeyName As Variant, IsNotFirst As Boolean + Set JObj = JSONData + If JObj.Count = 0 Then + JSONToString = "{}" + Exit Function + End If + JSONToString = "{" + If Indent Then GoSub IndentNextLine + For Each KeyName In JObj + If IsNotFirst Then + JSONToString = JSONToString & "," + If Indent Then GoSub IndentNextLine + End If + JSONToString = JSONToString & """" & KeyName & """: " & JSONToString(JObj(KeyName), Indent, IndentChar, CurIndentLevel + 1) + IsNotFirst = True + Next + CurIndentLevel = CurIndentLevel - 1 + If Indent Then GoSub IndentNextLine + JSONToString = JSONToString & "}" +Else + Select Case VarType(JSONData) + Case vbString + JSONToString = """" & EscapeString(JSONData) & """" + Case vbEmpty + JSONToString = "null" + Case Else + If IsNumeric(JSONData) Then + JSONToString = JSONData + If Left$(JSONToString, 1) = "." Then + JSONToString = "0" & JSONToString + Else + JSONToString = Replace(JSONToString, "-.", "-0.") + End If + JSONToString = Replace(LCase$(JSONToString), "e+", "e") + Else + Err.Raise JSONErrCode, "JSON Parser", "Unknown variant type `" & VarType(JSONData) & "`" + End If + End Select +End If +Exit Function +AddIndent: + JSONToString = JSONToString & String(Indent * CurIndentLevel, IndentChar) + Return + +AddNewLine: + JSONToString = JSONToString & vbCrLf + Return + +IndentNextLine: + GoSub AddNewLine + GoSub AddIndent + Return +End Function