前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >minigui: 基于miniStudio1.2.1创建模式对话框(DialogBox)

minigui: 基于miniStudio1.2.1创建模式对话框(DialogBox)

作者头像
10km
发布2019-05-25 21:29:51
8350
发布2019-05-25 21:29:51
举报
文章被收录于专栏:10km的专栏10km的专栏

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433522

mGNCS(miniStudio新控件集)提供nscCreateModalDialogFromID函数用于从资源模板创建模式对话框,但是对于miniStudio生成的对话框模板,使用nscCreateModalDialogFromID函数创建模式对话框是无效的,下面是nscCreateModalDialogFromID的实例代码:

代码语言:javascript
复制
int ncsCreateModalDialogFromID (HPACKAGE package, Uint32 dlgId,
                    HWND owner, HICON hIcon, HMENU hMenu,
                    NCS_EVENT_HANDLER_INFO* handlers, NCS_EVENT_CONNECT_INFO* connects)
{
    int ret = 0;
    // ncsCreateMainWindowIndirectFromID根据模板中的class名字来创建对应的实例,
    // 而miniStudio生成的模板class属性是mainwnd,
    // 所以这里ncsCreateMainWindowIndirectFromID返回的对象是'mMainWnd',
    // 'mMainWnd'不是'mDialogBox'的子类,所以不能转为'mDialogBox',所以这里的返回值为NULL.
    mDialogBox * dialog = SAFE_CAST(mDialogBox,
            ncsCreateMainWindowIndirectFromID(package, dlgId, owner, hIcon, hMenu, handlers, connects, 0));
    // dialog 为 NULL,所以 这里不会执行doModal方法,就直接返回了,对话框的表现就像一个普通窗口一样,不是模式的。
    if (dialog) {       
        ret = _c(dialog)->doModal(dialog, TRUE);
        MainWindowThreadCleanup(dialog->hwnd);
    }

    return ret;
}

这应该算是mGNCS的一个bug。要解决这个问题,首先要让miniStuio生成的对话框模板有正确的class属性。

Class 属性

minigui提供的miniStudio (1.2.1)还没有做完善,所以在miniStudio中只能生成class类型为mainwnd的标准窗口,因为如下图没有办法在gui界面中修改Class属性

如果想生成 一个对话框类型(dialogbox)的模板,该怎么办呢?经过多次尝试,找到解决办法,就是直接修改资源模板的xml文件。如下图打开模板对应的xml文件,将窗口的class修改为DialogBox,这样创建的窗口实例的类型就为mDialogBox

再次用ministudio打开资源模板。会发现界面中Class属性神奇的消失了

请注意,这里OK,CANCEL按钮的ID不能随便定义,要用minigui预定义的IDOKIDCANCEL,否则对话框无法正确处理消息

修改 nscCreateModalDialogFromID

好了,现在我们的对话框资源模板的类型已经正确了。那么是不是可以直接用mGNCS(miniStudio新控件集)提供nscCreateModalDialogFromID函数创建对话框呢?

你可以试试,运行的时候肯定会抛出异常。为什么呢?

再来分析ncsCreateMainWindowIndirectFromID的源码,参见代码中本文作者添加的中文注释

代码语言:javascript
复制
mMainWnd *ncsCreateMainWindowIndirectFromID (HPACKAGE package, Uint32 wndId,
                    HWND owner, HICON hIcon, HMENU hMenu,
                    NCS_EVENT_HANDLER_INFO* handlers,
                    NCS_EVENT_CONNECT_INFO *connects,
                    DWORD user_data)
{
    int         uitype;
    Uint32      id;
    mMainWnd    *mainWnd;
    NCSRM_WINHEADER  *header;
    NCS_MNWND_TEMPLATE tmpl;
    create_notify_t create_notify;

    if (package == HPACKAGE_NULL)
        return NULL;

    uitype = get_ui_data(package, wndId, (void*)&header, &id);

    if (uitype == UIDATA_ERR) {
        printf ("Error=>ResManager: ID(0x%0x) isn't valid main window id. \n", wndId);
        return NULL;
    }

    if(connects)
    {
        INIT_CREATE_NOTIFY(&create_notify, cb_on_create_child);
        create_notify.connect_head = new_connect_node_array(connects);
    }

    construct_wnd_template (package, header, (NCS_WND_TEMPLATE*)&tmpl,
            handlers, (NCS_CREATE_NOTIFY_INFO*)(connects?&create_notify:NULL), TRUE);
    tmpl.user_data = user_data;

    tmpl.hIcon = hIcon;
    tmpl.hMenu = hMenu;
    // Class 为mainwnd则调用ncsCreateMainWindowIndirect创建主窗口(MainWindow) 
    // 否则 调用ncsCreateWindowIndirect创建普通窗口
    if(ncsIsChildClass(tmpl.class_name, NCSCTRL_MAINWND))
        mainWnd = (mMainWnd*)ncsCreateMainWindowIndirect (&tmpl, owner);
    else
        mainWnd = (mMainWnd*)ncsCreateWindowIndirect((NCS_WND_TEMPLATE*)&tmpl, owner);

    deconstruct_wnd_template(&tmpl);

    //insert children
    if(connects)
    {
        if(mainWnd)
            connect_events(create_notify.connect_head, connects);
        free_connect_nodes(create_notify.connect_head);
    }

    del_list(package, id);

    if (mainWnd == NULL) {
        printf ("RESMANAGER>Error: According to ID(0x%0x), create main window or dialog failure. \n", wndId);
        return NULL;
    }

    return mainWnd;
}

从上面的代码分析可以看出,当模板的Class属性为mainwnd时创建的窗口类型是MainWindow,而其他类型时返回的是普通窗口实例。问题就出在这里。

再回头看ncsCreateModalDialogFromID的代码

代码语言:javascript
复制
    if (dialog) {       
        ret = _c(dialog)->doModal(dialog, TRUE);        
        MainWindowThreadCleanup(dialog->hwnd);
    }

对话框关闭后调用MainWindowThreadCleanup从函数名就可以看出,这个函数是针对MainWindow的,对于一个普通窗口对象是不能执行MainWindowThreadCleanup的。程序的运行异常就来自于这里。

mGNCS(miniStudio新控件集)中提供的调用例程都是调用ncsCreateMainWindowIndirect来创建窗口实例,所以能正常执行。

如下图是mGNCS手册中的例程片段

所以显然不能用ncsCreateModalDialogFromID来创建我们手工修改过模板Class属性的对话框了。但既然知道了原因,我们就可以参照ncsCreateModalDialogFromID的代码自己写一个myCreateModalDialogFromID函数。

代码语言:javascript
复制
// 根据模板ID(dlgId)创建模式对话框
// 点击IDOK按钮,返回1,否则返回0 
int myCreateModalDialogFromID(HPACKAGE package, Uint32 dlgId,
                    HWND owner, HICON hIcon, HMENU hMenu,
                    NCS_EVENT_HANDLER_INFO* handlers, NCS_EVENT_CONNECT_INFO* connects)
{
    int ret = 0;
    mDialogBox * dialog = SAFE_CAST(mDialogBox,
            ncsCreateMainWindowIndirectFromID(package, dlgId, owner, hIcon, hMenu, handlers, connects, 0));

    if (dialog) {
        mWidget* wok = ncsGetChildObj(dialog->hwnd,IDOK);
        mWidget* wcancel = ncsGetChildObj(dialog->hwnd,IDCANCEL);
        // 检查窗口对象中是否有IDOK,IDCANCEL按钮,如果没有输出警告
        if(!wok && !wcancel){
            perror("WARNING:not define OK or CANCEL button\n");
        }
        // 检查IDOK,IDCANCEL是否为按钮对象,如果不是则输出警告
        if(wok && ! INSTANCEOF(wok,mButton)){
            perror("WARNING:IDOK is not a button\n");
        }
        if(wcancel && ! INSTANCEOF(wcancel,mButton)){
            perror("WARNING:IDCANCEL is not a button\n");
        }
        ret = _c(dialog)->doModal(dialog, TRUE);
        // 这里判断是否为MainWindow,如果是MainWindow才执行MainWindowThreadCleanup
        if(IsMainWindow(dialog->hwnd)){
            MainWindowThreadCleanup(dialog->hwnd);
        }
    }
    return ret;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年07月06日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Class 属性
  • 修改 nscCreateModalDialogFromID
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档