[sixinice 原创翻译]从 VB6 到 B4A 的转化

Discussion in 'Chinese Forum' started by 52manhua, Sep 22, 2017.

  1. 52manhua

    52manhua Member Licensed User

    不定期发一些翻译类文字,希望和大家共同学习,如有不对,感谢指正.
    :)



    网站地址:http://sixinice.pw/drupal/node/65
    原地址:https://www.b4x.com/android/forum/threads/converting-vb6-to-b4a.9347/
      下面是一张包含 VB6 和 B4A 语法/函数转换表..

      如果你发现一些错误 或者想有其他补充, 可以回复,然后我在这个表中进行汇总 (在适当的时候进行更新).

      这个帖子也可以看成是一个基本的指导手册,当你把代码从 VB6 转换到 B4a 的时候会觉得有用(在一下的介绍中, VB6 的使用方法放左边 ,B4A 的用法在右 ).
    VB6 B4A
    === ===
    controls(控件 button ,textbox,label...等等) Views (button[按钮], edittext[编辑框], label[标签],等等.)

      在 vb6 的编码窗口, 左侧的控件栏中包含所有的可添加控件,中间是设计窗口,以及双击可以打开编码窗口,在右侧的属性框里,有所有这些控件的属性,还有工程的结构 ,设计窗口的显示模式等等(这里基本是自己写,vb6 的窗口布局,想要知道详细,打开去看). 在 B4a 中等价于设计器打开方式 : 菜单 -> Designer -> Tools -> Generate Members.(译者提示, 此项功能相当于 vb6 中将 控件丢到窗体后,再双击进入控件代码编写的操作. 注意,如果不使用 Generate Members,就需要手动在代码中实现对象引用和事件,与 vb6 不同的地方在于 b4a 的 Views 必须声明之后才可以使用.)一旦你在编码窗口中完整写出了子程序, 子程序名称就会出现处于右侧的 "Modules(模块)"中.
      在 B4a 里面, 你要按照 "Sub [viewName(子程序名称)]-〉中间有空格"的格式来生成一个子程序 , 按下回车后一般说一个子程序就生成了(译者注:回车后,程序自动生成 end sub ,如果没有自动生成,手动实现一下,注意看右边 Modules 的提示). 写子程序就是这样了.
    editBox = string(vb6) editBox.Text = string(b4a)
      在 vb6 里你可以直接用 textbox 的名称,获得的是字符串类型的文本,但是在 B4A 里面,这是不被允许的(必须加上 .Text).

    Dim/ReDim:

    Dim Array(n) Dim Array(n+1)

    n 是 VB6中最后一个序号,但是在 B4A中标示的是数组的数量. 举个例子, 定义一个 从 0 到 32 的 VB6 数组, 你会用 Dim A(32), 但是转换到 B4A 的时候, 你需要转化成 Dim A(33), 但是注意序号 33 并不存在 (如果引用 33 会出现 index out of range 错误).
    ReDim Preserve Use a List(使用 list 类型替代).
    ReDim Array() Dim Array(n+1) -- 清除一个数组, b4a只需要再定义(dim)一次就 OK 了.
    [Dim a Int: Dim b as Boolean](针对下面的例子,假设 a 是 int 类型, b 是Boolean布尔类型 )
    If Not b Then... If Not(b) Then...(NOT 的用法,在 B4a 中需要使用 (表达式) 来获取值*这是一个很常见的转换)
    If b Then... 一致
    If b = True Then 一致
    If a Then... If a > 0 Then...(b4a 中 a=0 不能直接引用为 false)
    B4A 并不像 VB6 一样把所有非零的值看成真(Boolean) .
    a = a + b (vb6) If b = True Then a = a - 1(b4a)
    同样,Boolean布尔值也不能使用 B4A 的数学运算符.
    Global Const x=1(vb6) B4A 没有全局常数的设定.
    在子程序定义全局变量, 你可以这样写 Dim x as Int: x = 1
    但是 x 不是一个常量 (它的值能被改变).

    循环, 判断, Select Case(不翻,都知道吧):
    Do [Until/While] 一致
    Loop [Until/While] Loop [Until/While 不允许.]
    For - Next 一致
    For i... - Next i 在 Next 后面不加在循环变量.
    Exit Do/For (vb6) Exit(b4a)
    If - Then - Else 一致, 除了 elseif(VB6) 和 else if (b4a)的区别; ditto EndIf
    --- Continue [直接跳转到 Next 执行]
    For i = 1 to 6 For i = 1 to 6
    If i <> 4 Then If i = 4 Then Continue
    ...code... ...code...
    End If ...
    Next Next
    Select Case [expr] Select [value](直接 select 值)

    颜色定义:
    L1.BackColor = (vb6) L1.Color = Colors.Red(b4a)
    vbRed (vb6)
    L1.ForeColor =(vb6) L1.TextColor = Colors.Black (b4a)
    vbBlack

    执行子程序:
    SubName x, y SubName(x, y)
    Sub SubName() Sub SubName() As Int/String/etc. -- b4a 中,全局变量不能作为子程序参数名
    假设 "player" 是一个全局变量,
    你在 b4a 中不能写作: Sub PlayCard(player). 你可以这样写:
    i=player: PlayCard(i)
    Function FName() Sub FName() As [var.type]
    As [var.type] 在 B4A 里面, 任何子程序都能作为函数使用,
    就像这样:
    Sub CheckX(x As Int) As Boolean
    ...optional code...
    If x = [desired value] Then Return True
    ...optional code...
    End Sub
    如果没有返回值, 会返回 0/false/"", 但是
    IDE 会给一个警告, 所以最好手动实现一下返回值.
    使用子程序并不一定需要返回值.
    所以 "If CheckX(x) = True..." 跟
    "CheckX(x)" 没有什么区别
    Exit Sub (vb6) Return (b4a)
    Exit Function (vb6) Return [value] (b4a)

    General:
    CInt Bit.ParseInt(string,[base]) 译者加的,原文没有
    DoEvents 一致, 不过 Erel 说明如下:
    "在循环中使用 DoEvents 会占用很多的资源,然后阻断系统正确响应消息",这个说明跟我想的一样
    在一个 do loop 中写入 DoEvents, WebView 不能载入
    即使载入后, 也不能正确地跳转链接. 同时 Agraham
    也指出: "在移动端使用循环会是一个很差的体验. 系统 CPU 会一直运行这段代码消耗更多的电力系统被迫一直处于忙碌状态,节能功能会因此而中止."
    Format() NumberFormat & NumberFormat2 [去看文档]
    InputBox($) InputList(Items as List, Title, CheckedItem as Int) as Int
    能显示多个选项 在每个选项前面设一个单选框. 返回选中的索引值.
    CheckedItem 设定默认选中的值.
    如果用户使用 InputMultiList(Items as List, Title) As List 这样的语句来选择多个选项 . 用户能勾选多个复选框,返回 list 中选中的复选框的索引值.

    MsgBox "text" MsgBox("text", "title")
    i=MsgBox() MsgBox2(Message, Title, Positive, Cancel, Negative, Icon) as Int

    显示分别带有(Positive, Cancel, Negative,字符可以自己设置)带有三个按钮
    (Positive, Cancel, Negative)
    图标是显示标题旁边,可以用下列语句进行设置:

    LoadBitmap(File.DirAssets, "[filename].gif")
    --- ToastMessageShow(text, b) [where b=True for long duration]
    以下是 Pfriemler 写的一个类似于 vb6 中 inpubox 功能的函数:
    Sub InputBox(Prompt As String, Title As String, Default As String, Hint As String) As String
    Dim Id As InputDialog
    Id.Hint = Hint
    Id.Input = Default
    ret = Id.Show(Prompt, Title, "OK", "","Abbrechen", Null)
    If ret = -1 Then Return Id.Input Else Return ""
    End Sub

    Rnd is < 1 Rnd(min, max) is integer >= min to < max
    Rnd(-#) RndSeed(#) - causes Rnd to generate the same random number series
    for the same # entered.
    Randomize 在 B4A 中不需要初始化随机种子.
    Round(n) 一致, 或者使用 Round2(n, x) 当 x=数字占位

    i = Val(string) If IsNumber(string) Then i = string Else i = 0 --
    尝试使用 i=string "造成异常" 如果字符串
    不是数字, 即时字符串是以数字开头的. 举例说明,
    t = "10:45"
    i = Val(t) sets i=10 在 B4A 中会出错.
    作为替代,
    i = t.SubString2(0, 2) = 10
    control.SetFocus view.RequestFocus
    n / 0 : error n / 0 = 2147483647 -- B4A 不会"造成异常" 因为
    除以 0, 但是会返回一个 2147483647 无所谓的数字 ?不管 "n" 到底是什么.
    x = Shell("...") 看 "Intent".
    没有完全的替代方法, 但是可以使用以下类似的方法 (by Erel):

    Dim pi As PhoneIntents
    StartActivity (pi.OpenBrowser("file:///sdcard/yourfile.html"))

    t = Timer t = DateTime.Now ' Ticks are number of milliseconds since 1-1-70

    TabIndex:
    在 VB6 中, TabIndex 用来设置按下 Tab 后的聚焦顺序. 根据 Erel 所说的, 在 B4A 中:
    "Android handles the sequence according to their position(Android 通过位置定义他们的顺序). 你可以写成这样:
    EditText.ForceDone = True 在所有你的 EditText 里. 捕获事件
    EditText_EnterPressed 在代码中设定 下一个聚焦的对象
    view (with EditText.RequestFocus)."

    设置标签的透明度:
    Properties - Back Style (vb6) Designer - Drawable - Alpha (设计器)

    Constants:
    "" Quote = Chr$(34)
    vbCr CRLF = Chr$(10)
    vbCrLf none

    字符串 "成员"(字符串处理的函数和语句):
    VB6 的字符串从位置 1 开始.
    B4A 的字符串从位置 0 开始.

    VB6 B4A
    Mid$("abcde", 1, 1) = "a" = letter array index 0 -- "a" = "abcde".CharAt(0)
    Mid$("abcde", 2, 1) = "b" = letter array index 1
    Mid$("abcde", 3, 1) = "c" = letter array index 2
    Mid$("abcde", 4, 1) = "d" = letter array index 3
    Mid$("abcde", 5, 1) = "e" = letter array index 4
    VB6 B4A
    === ===
    Mid$(text, n, 1) text.CharAt(n-1)
    Mid$(text, n) text.SubString(n-1)
    Mid$(text, n, x) [x=length wanted] text.SubString2(n-1, n+x-1) [n+x-1=end position]
    Mid$(text, n, x) = text2 text = text.SubString2(0, n-2) & _
    text2.SubString2(0, x-1) & _
    text.SubString(n-1 + z) where...
    z = Min(x, text2.length)
    Left$(text, n) [n=num.of chars.] text.SubString2(0, n)
    Right$(text, n) text.SubString(text.Length - n + 1)
    If a$ = b$... If a.CompareTo(b)...
    If Right$(text, n) = text2... If text.EndsWith(text2)...
    If Left$(text, n) = text2... If text.StartsWith(text2)...
    If Lcase$(text) = Lcase$(text2)... If text.EqualsIgnoreCase(text2)...

    这里有一些 NeoTechni 写的函数可以替换原先的 vb6 字符串函数(Left,Right,Mid,Split)
    字符串函数:

    Sub Left(Text As String, Length As Long)As String
    If length>text.Length Then length=text.Length
    Return text.SubString2(0, length)
    End Sub

    Sub Right(Text As String, Length As Long) As String
    If length>text.Length Then length=text.Length
    Return text.SubString(text.Length-length)
    End Sub

    Sub Mid(Text As String, Start As Int, Length As Int) As String
    Return text.SubString2(start-1,start+length-1)
    End Sub

    Sub Split(Text As String, Delimiter As String) As String()
    Return Regex.Split(delimter,text)
    End Sub

    x = Len(text) x = text.Length
    text = Replace(text, str, str2) text.Replace(str, str2)
    Lcase(text) text.ToLowerCase
    Ucase(text) text.ToUpperCase
    Trim(text) text.Trim
    (no LTrim or RTrim in B4A)
    Instr(text, string) text.IndexOf(string)
    Instr(int, text, string) text.IndexOf2(string, int)
    Returns -1 if not found.
    Returns char. index, not position.
    Starts search at "int".
    InStrRev(text, str, start, case) text.LastIndexOf(string)
    Searches from end of string, text.LastIndexOf(string, start)
    optionally from "start". Cannot specify case sensitivity.
    case = 0 = case-sensitive
    case = 0 = case-insensitive
    A boolean form of IndexOf is -
    If text.Contains(string) = True Then...
    If Lcase$(x) = Lcase$(y)... If x.EqualsIgnoreCase(y)...
    text = Left$(text, n) & s & text.Insert(n, s)
    Right$(Text, y)
    Asc(s) [where s = a character] same

    错误捕获:
    VB6:
    Sub SomeSub
    On [Local] Error GoTo ErrorTrap
    ...[一些代码]...
    On Error GoTo 0 [optional end to error trapping]
    ...optional additional code...
    Exit Sub [to avoid executing ErrorTrap code]
    ErrorTrap:
    ..[错误处理的代码]...
    Resume [optional: "Resume Next" or "Resume [line label]".
    End Sub

    B4A:
    Sub SomeSub
    Try
    ...[一些代码]...
    Catch [only executes if error above
    Log(LastException) [optional]
    ..[错误处理的代码]...
    End Try
    ...optional additional code...
    End Sub
    在 B4A中, 如果你在一大段的子程序中间发生了错误, 你不能做修正后继续执行接下来的代码--一切重新开始. Only the code
    in "Catch" gets executed, plus any code following "End Try".

    Try-Catch 以及 GoTo:
    Try-Catch 可以作为 GoTo [line label] 的简化版使用,只能正向,不能逆向执行或者跳转执行. GoSub 在 B4A 中不能使用.
    使用 Try -catch 时 ,在代码开始的地方放置 "Try" 在设置 [line label] 的地方放置 "Catch".
    与 "GoTo [line label]" 等价的代码, 相当于遇到异常后就跳转到 "Catch", 比如

    Try
    OpenInput("bad path", "bad filename")
    Catch

    End Try (文件打开的异常).

    "Immediate Window(即时窗口 vb6)" 和 "Logs" 调试窗的区别:

    VB6 中可以用 "Debug.Print ..."立即执行语句,打印变量值等等.
    在 B4A 开发环境中, 进入 debug 状态,可以从右边的 logs 调试窗口来显示变量值(在程序中使用 LOG(变量值) 来实现它).
    VB6 和 B4a 都支持步进式的调试方法. VB6 支持改变变量值,改变代码,跳转到某一行执行等功能,但是因为 B4A 和 app 运行的环境不同,所以并不是所有 VB6 的调试功能都支持.
     
    Last edited: Sep 22, 2017
Loading...