IUP中文环境下通过FreeBasic_x64做界面开发的实践

序言:

FreeBasic现在的版本是1.10,支持32位和64位开发,后端编译器使用 gcc-9.3.0,是一套跨平台的开发软件。勇芳Visual FreeBasic,WinFBE等Windows平台上界面开发,都使用的是FreeBasic编译器。IUP是开源免费的轻量界面程序包,也是支持跨平台和国际化语言的,与FreeBasic配合还是比较搭的。除些之外,FreeBasic还可以搭配Gtk和wxWidgets一起使用。

1. IUP的中文显示问题

IUP作为国际化跨平台使用的界面包,并不直接支持中文,这在网上可以查到关于类似的讨论,但它完美地支持UTF8,因此做些转换就可以使用了。重点1是将全局UTF8MODE在程序中设置成为Yes:

'Very Important for use Chinese Characters

IupSetAttribute(0, "UTF8MODE", "Yes")

重点2是发送中文或中英文混合字符串时先进行toUTF8转换,如btn1 = IupButton(toUTF8("Button1-按钮1"), "ACTION")

2. 开发工具和编译器配置选项

poseidonFB是一套跨平台的开发工具,开源免费红绿色,下载后解压即可使用。

在github上有该项目的发布

将FreeBasic编译器放在poseidonFB目录下或其它地方,在option菜单下将fbc32.exe和fbc64.exe填入相应的位置。

在具体项目的属性页,填写编译选项 ---> 图形界面、gcc后端、3及优化、加入TD.rc资源(编译输出的exe文件适应高DPI显示器缩放影响,否则字体变得模糊)

还是在属性而,将IUP 64位的界面库包的LIB包含进来,它的Include由FreeBasic程序自带了,不是.h文件,是与期对应的.bi文件。

3. 编写实践用程序

出个基本想法,让豆包帮助写个框架,然后修改。写一句下面的话:

"用freebasic和iup写程序框架,包括3外button,1个列表,1个combo,1个textbox和1个label"

豆包给出的回复看起来还是有模有样的。

vbscript 复制代码
#Include Once "iup.bi"

' 定义全局控件句柄,供回调函数访问
Dim Shared btn1 As Ihandle Ptr, btn2 As Ihandle Ptr, btn3 As Ihandle Ptr
Dim Shared list As Ihandle Ptr, combo As Ihandle Ptr, txt As Ihandle Ptr, lbl As Ihandle Ptr

' 按钮1回调:文本框显示"hello world",列表添加"hello everyone"
Function Btn1_CB(ByVal ih As Ihandle Ptr, ByVal data As Any Ptr) As Integer
    IupSetAttribute(txt, "VALUE", "hello world")  ' 文本框赋值
    IupListAdd(list, "hello everyone")            ' 列表添加项
    Return IUP_DEFAULT
End Function

' 按钮2回调:退出程序
Function Btn2_CB(ByVal ih As Ihandle Ptr, ByVal data As Any Ptr) As Integer
    Return IUP_CLOSE  ' 触发窗口关闭,终止消息循环
End Function

' 按钮3空回调(预留扩展)
Function Btn3_CB(ByVal ih As Ihandle Ptr, ByVal data As Any Ptr) As Integer
    Return IUP_DEFAULT
End Function

' 主程序入口
Sub Main()
    ' 初始化IUP库
    IupOpen(0, 0)
    
    ' 创建所有控件
    lbl = IupLabel("输入/显示区域:")              ' 标签
    txt = IupText("")                              ' 文本框
    combo = IupCombo("")                           ' 下拉框
    list = IupList("")                             ' 列表框
    btn1 = IupButton("显示&添加内容", @Btn1_CB)    ' 按钮1(&设置快捷键Alt+A)
    btn2 = IupButton("退出程序", @Btn2_CB)         ' 按钮2
    btn3 = IupButton("预留功能", @Btn3_CB)         ' 按钮3(预留)
    
    ' 配置控件属性
    IupSetAttribute(combo, "DROPDOWN", "YES")      ' 下拉框模式
    IupSetAttribute(combo, "VALUE", "请选择")      ' 下拉框默认提示
    IupSetAttribute(list, "MULTIPLE", "NO")        ' 列表单选
    IupSetAttribute(txt, "EXPAND", "HORIZONTAL")   ' 文本框水平拉伸
    IupSetAttribute(list, "EXPAND", "BOTH")        ' 列表双向拉伸(占满剩余空间)
    
    ' 构建布局(垂直容器嵌套水平容器,层次清晰)
    Dim top_row As Ihandle Ptr = IupHbox(lbl, txt, combo, 0)  ' 标签+文本框+下拉框 横向排列
    Dim btn_row As Ihandle Ptr = IupHbox(btn1, btn2, btn3, 0)  ' 三个按钮 横向排列
    Dim main_layout As Ihandle Ptr = IupVbox(
        top_row,
        IupLabel(""),  ' 空白分隔符,优化间距
        btn_row,
        IupLabel(""),  ' 空白分隔符
        list,
        0
    )
    
    ' 配置主布局样式
    IupSetAttribute(main_layout, "MARGIN", "15x15")  ' 内边距
    IupSetAttribute(main_layout, "GAP", "10")         ' 控件间距
    IupSetAttribute(main_layout, "EXPAND", "BOTH")    ' 主布局自适应窗口拉伸
    
    ' 创建主窗口并配置
    Dim main_win As Ihandle Ptr = IupDialog(main_layout)
    IupSetAttribute(main_win, "TITLE", "FB+IUP 功能框架")  ' 窗口标题
    IupSetAttribute(main_win, "SIZE", "650x450")           ' 初始窗口大小
    IupSetAttribute(main_win, "MINBOX", "YES")             ' 允许最小化
    IupSetAttribute(main_win, "MAXBOX", "YES")             ' 允许最大化
    
    ' 居中显示窗口并启动消息循环
    IupShowXY(main_win, IUP_CENTER, IUP_CENTER)
    IupMainLoop()
    
    ' 清理资源
    IupClose()
End Sub

' 启动程序
Main()

这里有一个大错误,iup没有combo控件,把它去除掉不要了,其余的保留,然后加上 windows.bi引用,再写上toUTF8,程序其它地方略做修改,最后的程序如下。

vbscript 复制代码
#Include Once "iup/iup.bi"
#Include Once "windows.bi"

' 定义全局控件句柄,供回调函数访问
Dim Shared btn1 As Ihandle Ptr, btn2 As Ihandle Ptr, btn3 As Ihandle Ptr
Dim Shared list As Ihandle Ptr, txt As Ihandle Ptr, lbl As Ihandle Ptr

Declare Function Btn1_CB(ByVal ih As Ihandle Ptr, ByVal idata As Any Ptr) As Integer
Declare Function Btn2_CB(ByVal ih As Ihandle Ptr, ByVal idata As Any Ptr) As Integer
Declare Function Btn3_CB(ByVal ih As Ihandle Ptr, ByVal idata As Any Ptr) As Integer
Declare Function toUTF8(ByVal swStringIN as WString ptr) As ZString ptr

' 按钮1回调:文本框显示"hello world",列表添加"hello everyone"
Function Btn1_CB(ByVal ih As Ihandle Ptr, ByVal idata As Any Ptr) As Integer
    IupSetAttribute(txt, "VALUE", "")  ' 文本框赋值
	IupSetAttribute(list, "2", toUTF8("列表数据第二项"))
	IupSetAttribute(list, "3", IupGetAttribute(list, "1"))
	Dim iCount as Integer
	Dim izsCount as ZString * 10
	izsCount = *IupGetAttribute(list, "COUNT")
	iCount = val(izsCount) + 1
	izsCount = Str(iCount)
	
	'It is ok to add an item
	'IupSetAttribute(list, izsCount, "Added " + izsCount)
	
	'It also works ok to append an item
	'IupSetAttribute(list, "APPENDITEM", "Add item to tail" + izsCount)

	'It also also works ok to use INSERTITEM followed by item no
	IupSetAttribute(list, "INSERTITEM1", *toUTF8("从上方插入数据" + izsCount))
    Return IUP_DEFAULT
End Function

' 按钮2回调:退出程序
Function Btn2_CB(ByVal ih As Ihandle Ptr, ByVal idata As Any Ptr) As Integer
    Return IUP_CLOSE  ' 触发窗口关闭,终止消息循环
End Function

' 按钮3空回调(预留扩展)
Function Btn3_CB(ByVal ih As Ihandle Ptr, ByVal idata As Any Ptr) As Integer
    Return IUP_DEFAULT
End Function

Function toUTF8(ByVal swStringIN as WString ptr) As ZString ptr
	Dim wideStr as wstring * 50 = *sWStringIN
	Static utf8str as zstring * 150
	Dim utf8Size as Integer
	utf8str = ""
	utf8Size = WideCharToMultiByte(CP_UTF8, 0, @wideStr, -1, NULL, 0, NULL, NULL)
	utf8Size = WideCharToMultiByte(CP_UTF8, 0, @wideStr, -1, @utf8str, utf8Size, NULL, NULL)
	return @utf8str
End function

' 主程序入口
Sub Main()
    ' 初始化IUP库
    IupOpen(0, 0)

	'Very Important for use Chinese Characters
    IupSetAttribute(0, "UTF8MODE", "Yes")
	
	lbl = IupLabel(toUTF8("输入/显示区域:"))
    ' 创建所有控件
    txt = IupText("")                              ' 文本框

    list = IupList("")                             ' 列表框
	IupSetAttribute(list, "1", toUTF8("第1项列表数据"))

	btn1 = IupButton(toUTF8("Button1-按钮1"), "ACTION")
	IupSetCallback(btn1 , "ACTION" , CAST(Icallback, @Btn1_CB))	
	
	btn2 = IupButton(toUTF8("Button2-按钮2"), "ACTION")
	IupSetCallback(btn2 , "ACTION" , CAST(Icallback, @Btn2_CB))	
	
	btn3 = IupButton(toUTF8("Button3-按钮3"), "ACTION")
	
    ' 配置控件属性
    IupSetAttribute(list, "EXPAND", "YES")        ' 列表双向拉伸(占满剩余空间)	
    IupSetAttribute(list, "MULTIPLE", "NO")        ' 列表单选
	
	IupSetAttribute(btn3, "EXPAND", "HORIZONTAL")
    IupSetAttribute(txt, "EXPAND", "HORIZONTAL")   ' 文本框水平拉伸

    
    ' 构建布局(垂直容器嵌套水平容器,层次清晰)
    Dim top_row As Ihandle Ptr = IupHbox(lbl, txt, 0)  ' 标签+文本框+下拉框 横向排列
    Dim btn_row As Ihandle Ptr = IupHbox(btn1, btn2, btn3, 0)  ' 三个按钮 横向排列
	Dim spacer2 as Ihandle Ptr = IupLabel("")  ' 空白分隔符,优化间距
	Dim main_layout As Ihandle Ptr = IupVbox( _
        top_row, _
        spacer2,  _ ' 空白分隔符,优化间距
        btn_row, _ 
        spacer2, _  ' 空白分隔符
        list, _
        0 _
    )
    
    ' 配置主布局样式
    IupSetAttribute(main_layout, "MARGIN", "15x15")  	' 内边距
    IupSetAttribute(main_layout, "GAP", "10")         	' 控件间距
    IupSetAttribute(main_layout, "EXPAND", "BOTH")    	' 主布局自适应窗口拉伸
	
	
    
    ' 创建主窗口并配置
    Dim main_win As Ihandle Ptr = IupDialog(main_layout)
    IupSetAttribute(main_win, "TITLE", toUTF8("FB+IUP 功能框架"))  ' 窗口标题
    IupSetAttribute(main_win, "SIZE", "400x200")           	' 初始窗口大小
    IupSetAttribute(main_win, "MINBOX", "YES")             	' 允许最小化
    IupSetAttribute(main_win, "MAXBOX", "YES")             	' 允许最大化
	
	'Add ICON to dialog window	
	IupSetAttribute(main_win, "ICON", "UCRT64.ico")
    
	'Add something to the list
	IupSetAttribute(list, "1", "Added something in")		'Add something to the list
	
    ' 居中显示窗口并启动消息循环
    IupShowXY(main_win, IUP_CENTER, IUP_CENTER)
    IupMainLoop()
    
    ' 清理资源
    IupClose()
End Sub

' 启动程序
Main()

点选64位编译

编译器输出编译成功

运行一下程序,看到中文显示正常,输入中英文混合也正常。

再细致考量一下,发现图标和资源文件全部打包进了EXE文件。至此,64位iup界面包搭上64位freeBasic可以跨平台使用了。