认识soui4js(第2篇):代码编辑及调试

发布时间 2023-06-06 11:37:34作者: 启程软件

开始

假定您使用向导在d:\jsdemo目录创建一个工程,您也已经安装好了vscode, 那么您应该可以看到下面的界面效果:

工程生成后,主要包含一个soui资源包及一个main.js

要运行这个程序,您需要给vscode安装一个插件:quickjs-debug

由于向导已经自动配置了一个launch.json, 

这里,你可在选择vscode菜单中的Run/Start Debugging或者Run/Run Without Debugging来启动soui4js-host.exe来加载这个测试工程。

然后你可以看到下面的效果:

在这个demo中只有一个test按钮,点击该按钮,会弹出一个msgbox。

如果您已经看到上面界面,恭喜,您已经可以开始soui4js的开发了。

切换到main.js的代码,展开OutLine, 我们可以看到整个main.js的代码结构:

主要有3个对象:

g_workDir,这是一个全局变量,标识当前程序的运行路径。

MainDialog, 这是一个继承自soui4.JsHostWnd主界面窗口。

main, 这是main.js的入口函数。

main函数功能:

 1 function main(inst,workDir,args)
 2 {
 3     soui4.log(workDir);
 4     g_workDir = workDir;
 5     let theApp = soui4.GetApp();
 6     let souiFac = soui4.CreateSouiFactory();
 7     //*
 8     let resProvider = souiFac.CreateResProvider(1);
 9     soui4.InitFileResProvider(resProvider,workDir + "\\uires");
10     //*/
11     /*
12     // show how to load resource from a zip file
13     let resProvider = soui4.CreateZipResProvider(theApp,workDir +"\\uires.zip","souizip");
14     if(resProvider === 0){
15         soui4.log("load res from uires.zip failed");
16         return -1;
17     }
18     //*/
19     let resMgr = theApp.GetResProviderMgr();
20     resMgr.AddResProvider(resProvider,"uidef:xml_init");
21     resProvider.Release();
22     let hwnd = soui4.GetActiveWindow();
23     let hostWnd = new MainDialog();
24     hostWnd.Create(hwnd,0,0,0,0);
25     hostWnd.SendMessage(0x110,0,0);//send init dialog message.
26     hostWnd.ShowWindow(soui4.SW_SHOWNORMAL); 
27     souiFac.Release();
28     let ret= theApp.Run(hostWnd.GetHwnd());
29     hostWnd=null;
30     soui4.log("js quit");
31     return ret;
32 }
33 
34 globalThis.main=main;

 

main函数代码基本上是固定的,没有特殊要求的情况下,可以不需要修改。

它的功能就是从资源包路径(或者zip包,见注释部分代码)创建一个soui资源包,然后交给theApp管理。

再从MainDialog创建一个窗口对象并显示。

再调用theApp.Run来运行程序的消息循环。

最后退出程序。

main函数后面需要有一行globalThis.main = main, 这样soui4js-host.exe才能通过全局对象找到这个函数并执行。

MainDialog方法介绍:

constructor(){
        super("layout:dlg_main");
        this.onEvt = this.onEvent;
    }

MainDialog的基类soui4.JsHostWnd的构造函数需要一个参数:布局文件的资源ID,因此在MainDialog的构造里需要把这个数据传递给基类。

此外,还在构造函数中指定了使用MainDialog的onEvent方法来处理窗口的事件。

1     onEvent(e){
2         if(e.GetID()==soui4.EVT_INIT){//event_init
3             this.init();
4         }else if(e.GetID()==soui4.EVT_EXIT){
5             this.uninit();
6         }
7         return false;
8     }

onEvent方法有一个参数e, 这个参数是soui的事件对象。通过e.GetID来识别是哪一种事件。

这里处理了两个事件:soui4.EVT_INIT, soui4.EVT_EXIT

这两个事件分别在界面元素创建完成及窗口退出前触发。

1     init(){
2         console.log("init");
3         soui4.SConnect(this.FindIChildByName("btn_test"),soui4.EVT_CMD,this,this.onBtnTest);
4     }

init方法只干了一件事:使用soui4.FindIChildByName("btn_test"), 找到布局文件里配置的name为btn_test的按钮,并且将它产生的soui4.EVT_CMD事件(点击事件)和this.onBtnTest方法相关联。

也就是说这个按钮按下后,执行this.onBtnTest。

1     uninit(){
2         //do uninit.
3         console.log("uninit");
4     }

uninit目前只打印了一行日志。

1     onBtnTest(e){
2         console.log("you click test button");
3         soui4.SMessageBox(this.GetHwnd(),"you click test button","test",soui4.MB_OK);
4     }

onBtnTest中,调用soui4.SMessageBox来显示一个msgbox。

代码调试:

写代码离不开调试,好在quickjs已经提供了调试支持,配合vscode的quickjs debugger插件就可以断点,调试。

我们可以在调试运行前或者运行过程中在代码行设置断点。

假定我们在onBtnTest里断点,点击test按钮,程序在断点中断。

从界面上可以看到程序的调用栈及当前的局部及全局变量的值。

需要注意的下,目前这个调试功能还不完美,仅仅是能用,部分操作可能会导致host崩溃。不过问题不大,已经足可能应对我们一般的代码调试需求。

到这里你应该已经基本了解了soui4js的开发流程了。