⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tech.txt

📁 中文编程语言——易语言(可视化编程
💻 TXT
📖 第 1 页 / 共 5 页
字号:
                                          // 指针所指向数据的格式见前面的描述。
                                          // !!!只可读取而不可更改其中的内容。

            DWORD         m_dwSubCodeAdr; // SDT_SUB_PTR,为子程序代码地址指针。
            MUNIT         m_unit;         // 窗口单元、菜单数据类型的数据。

            void*         m_pCompoundData;// 复合数据类型数据指针,指针所指向数据的格式见前面的描述。
                                          // !!! 只可读取而不可更改其中的内容。

            void*         m_pAryData;     // 数组数据指针,指针所指向数据的格式见前面的描述。
                                          // 注意如果为文本或字节集数组,则成员数据指针可能为NULL。
                                          // !!! 只可读取而不可更改其中的内容。

            // 第二部分。
            // 为指向变量地址的指针,仅当参数具有AS_RECEIVE_VAR或AS_RECEIVE_VAR_ARRAY或
            // AS_RECEIVE_VAR_OR_ARRAY标志时才被使用。
            BYTE*   m_pByte;            // SDT_BYTE 数据类型变量的地址,下同。
            SHORT*  m_pShort;           // SDT_SHORT
            INT*    m_pInt;             // SDT_INT
            INT64*  m_pInt64;           // SDT_INT64
            FLOAT*  m_pFloat;           // SDT_FLOAT
            DOUBLE* m_pDouble;          // SDT_DOUBLE
            DATE*   m_pDate;            // SDT_DATE_TIME
            BOOL*   m_pBool;            // SDT_BOOL

            char**  m_ppText;           // SDT_TEXT,注意*m_ppText可能为NULL(代表空文本)。
                                        // 写入新值之前必须释放前值,例句:NotifySys (NRS_MFREE, (DWORD)*m_ppText)。
                                        // !!!不可直接更改*m_ppText所指向的内容,只能释放原指针后设置入NULL(空文本)
                                        // 或使用NRS_MALLOC通知分配的新内存地址指针(下同)。

            LPBYTE* m_ppBin;            // SDT_BIN,注意*m_ppBin可能为NULL(代表空字节集)。
                                        // 写入新值之前必须释放前值,例句:NotifySys (NRS_MFREE, (DWORD)*m_ppBin)。
                                        // !!!不可直接更改*m_ppBin所指向的内容,只能释放原指针后设置入NULL(空字节集)
                                        // 或新指针。

            DWORD*  m_pdwSubCodeAdr;    // SDT_SUB_PTR,子程序代码地址变量地址。
            PMUNIT  m_pUnit;            // 窗口单元、菜单数据类型变量地址。

            void**  m_ppCompoundData;   // 复合数据类型变量地址。
                                        // !!!注意写入新值之前必须使用NRS_MFREE通知逐一释放所有成员(即:SDT_TEXT、
                                        // SDT_BIN及复合数据类型成员)及原地址指针。
                                        // !!!不可直接更改*m_ppCompoundData所指向的内容,只能释放原指针后设置入新指针。

            void**  m_ppAryData;        // 数组数据变量地址,注意:
                                        // 1、写入新值之前必须释放原值,例句:NotifySys (NRS_FREE_ARY,
                                        //    m_dtDataType, (DWORD)*m_ppAryData),注意:此例句只适用于
                                        //    m_dtDataType为系统基本数据类型时的情况,如果为复合数据类型,
                                        //    必须根据其定义信息逐一释放。
                                        // 2、如果为文本或字节集数组,则其中成员的数据指针可能为NULL。
                                        // !!!不可直接更改*m_ppAryData所指向的内容,只能释放原指针后设置入新指针。
        };

        // 1、当用作传递参数数据时,如果该参数具有 AS_RECEIVE_VAR_OR_ARRAY 或
        //    AS_RECEIVE_ALL_TYPE_DATA 标志,且为数组数据,则包含标志 DT_IS_ARY ,
        //    这也是 DT_IS_ARY 标志的唯一使用场合。
        //    DT_IS_ARY 的定义为:
        //      #define    DT_IS_ARY   0x20000000
        // 2、当用作传递参数数据时,如果为空白数据,则为 _SDT_NULL 。
        DATA_TYPE m_dtDataType;
    };
    typedef MDATA_INF* PMDATA_INF;

    ///////////////////////////////////////////////

    下面给出一些具体的例子用来说明如何定义且实现全局命令,更多的例子请参见所提供的HtmlView支持库的源代码 。

    ///////////////////

        首先给出一些例子中被使用到的公共辅助函数的实现代码:

        // 使用指定文本数据建立易程序中使用的文本数据。
        char* CloneTextData (char* ps)
        {
            if (ps == NULL || *ps == '\0')
                return NULL;

            INT nTextLen = strlen (ps);
            char* pd = (char*)NotifySys (NRS_MALLOC, (DWORD)(nTextLen + 1), 0);
            memcpy (pd, ps, nTextLen);
            pd [nTextLen] = '\0';
            return pd;
        }

        // 使用指定文本数据建立易程序中使用的文本数据。
        //   nTextLen用作指定文本部分的长度(不包含结束零),
        // 如果为-1,则取ps的全部长度。
        char* CloneTextData (char* ps, INT nTextLen)
        {
            if (nTextLen <= 0)
                return NULL;

            char* pd = (char*)NotifySys (NRS_MALLOC, (DWORD)(nTextLen + 1), 0);
            memcpy (pd, ps, nTextLen);
            pd [nTextLen] = '\0';
            return pd;
        }

        // 使用指定数据建立易程序中使用的字节集数据。
        LPBYTE CloneBinData (LPBYTE pData, INT nDataSize)
        {
            if (nDataSize == 0)
                return NULL;

            LPBYTE pd = (LPBYTE)NotifySys (NRS_MALLOC, (DWORD)(sizeof (INT) * 2 + nDataSize), 0);
            *(LPINT)pd = 1;
            *(LPINT)(pd + sizeof (INT)) = nDataSize;
            memcpy (pd + sizeof (INT) * 2, pData, nDataSize);
            return pd;
        }

        // 报告运行时错误。
        void GReportError (char* szErrText)
        {
            NotifySys (NRS_RUNTIME_ERR, (DWORD)szErrText, 0);
        }

        void* MMalloc (INT nSize)
        {
            return (void*)NotifySys (NRS_MALLOC, (DWORD)nSize, 0);
        }

        void MFree (void* p)
        {
            NotifySys (NRS_MFREE, (DWORD)p, 0);
        }

        // 返回数组的数据部分首地址及成员数目。
        LPBYTE GetAryElementInf (void* pAryData, LPINT pnElementCount)
        {
            LPINT pnData = (LPINT)pAryData;
            INT nArys = *pnData++;  // 取得维数。
            // 计算成员数目。
            INT nElementCount = 1;
            while (nArys > 0)
            {
                nElementCount *= *pnData++;
                nArys--;
            }

            if (pnElementCount != NULL)
                *pnElementCount = nElementCount;
            return (LPBYTE)pnData;
        }

        #define DTT_IS_NULL_DATA_TYPE   0
        #define DTT_IS_SYS_DATA_TYPE    1
        #define DTT_IS_USER_DATA_TYPE   2
        #define DTT_IS_LIB_DATA_TYPE    3
        // 取回数据类型的类别。
        INT GetDataTypeType (DATA_TYPE dtDataType)
        {
            if (dtDataType == _SDT_NULL)
                return DTT_IS_NULL_DATA_TYPE;

            DWORD dw = dtDataType & 0xC0000000;
            return dw == DTM_SYS_DATA_TYPE_MASK ? DTT_IS_SYS_DATA_TYPE :
                    dw == DTM_USER_DATA_TYPE_MASK ? DTT_IS_USER_DATA_TYPE :
                    DTT_IS_LIB_DATA_TYPE;
        }

        // 绝对不会返回NULL或者窗口句柄无效的CWnd*指针。
        CWnd* GetWndPtr (PMDATA_INF pInf)
        {
            return (CWnd*)NotifySys (NRS_GET_AND_CHECK_UNIT_PTR,
                    pInf [0].m_unit.m_dwFormID, pInf [0].m_unit.m_dwUnitID);
        }

    ///////////////////


    1、使用到 CMD_INFO 中的 CT_ALLOW_APPEND_NEW_ARG 标志的命令例子:
    2、返回系统基本数据类型的命令例子:

        // 求余数

        static ARG_INFO s_ArgInfo[] =
        {
            {
            /*name*/       _T("被除数"),
            /*explain*/    NULL,
            /*bmp inx*/    0,
            /*bmp num*/    0,
            /*type*/       SDT_DOUBLE,
            /*default*/    0,
            /*state*/      NULL,
            }, {
            /*name*/       _T("除数"),
            /*explain*/    NULL,
            /*bmp inx*/    0,
            /*bmp num*/    0,
            /*type*/       SDT_DOUBLE,
            /*default*/    0,
            /*state*/      NULL,
            },
        };

        static CMD_INFO s_CmdInfo =
        {
        /*name*/          _T("求余数"),
        /*egname*/        _T("mod"),
        /*explain*/       _T("求出两个数值的商,并返回余数部分,运算符号为“%”或“Mod”"),
        /*category*/      2,
        /*state*/         CT_ALLOW_APPEND_NEW_ARG,
        /*ret*/           SDT_DOUBLE,
        /*reserved*/      0,
        /*level*/         LVL_SIMPLE,
        /*bmp inx*/       0,
        /*bmp num*/       0,
        /*ArgCount*/      2,
        /*arg lp*/        s_ArgInfo,
        },

        // 命令实现函数
        void fnMod (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
        {
            // 对于具有CT_ALLOW_APPEND_NEW_ARG标志的命令,需要读取nArgCount以获得实际参数数目。
            DOUBLE db = pArgInf [0].m_double;
            for (INT i = 1; i < nArgCount; i++)
            {
                pArgInf++;
                if (pArgInf->m_double == 0)
                    GReportError ("不能求余数于零");
                db = fmod (db, pArgInf->m_double);
            }

            // 设置返回的双精度小数数据。
            pRetData->m_double = db;
        }

    ///////////////////

    3、使用到 CMD_INFO 中的 CT_RETURN_ARRAY_DATA 标志的命令例子:
    4、具有定义有 AS_DEFAULT_VALUE_IS_EMPTY 标志参数的命令例子:

        // 分割文本

        static ARG_INFO s_ArgInfo[] =
        {
            {
            /*name*/       _T("待分割文本"),
            /*explain*/    _T("如果参数值是一个长度为零的文本,则返回一个空数组,即没有任何成员的数组"),
            /*bmp inx*/    0,
            /*bmp num*/    0,
            /*type*/       SDT_TEXT,
            /*default*/    0,
            /*state*/      NULL,
            }, {
            /*name*/       _T("用作分割的文本"),
            /*explain*/    _T("参数值用于标识子文本边界。如果被省略,"
                      "则默认使用半角逗号字符作为分隔符。如果是一个长度为零的文本,则返回的数组"
                      "仅包含一个成员,即完整的“待分割文本”"),
            /*bmp inx*/    0,
            /*bmp num*/    0,
            /*type*/       SDT_TEXT,
            /*default*/    0,
            /*state*/      AS_DEFAULT_VALUE_IS_EMPTY,
            }, {
            /*name*/       _T("要返回的子文本数目"),
            /*explain*/    _T("如果被省略,则默认返回所有的子文本"),
            /*bmp inx*/    0,
            /*bmp num*/    0,
            /*type*/       SDT_INT,
            /*default*/    0,
            /*state*/       AS_DEFAULT_VALUE_IS_EMPTY,
            }
        };

        static CMD_INFO s_CmdInfo =
        {
        /*name*/        _T("分割文本"),
        /*egname*/      _T("split"),
        /*explain*/     _T("将指定文本进行分割,返回分割后的一维文本数组"),
        /*category*/    9,
        /*state*/       CT_RETRUN_ARY_TYPE_DATA,
        /*ret*/         SDT_TEXT,
        /*reserved*/    0,
        /*level*/       LVL_SIMPLE,
        /*bmp inx*/     0,
        /*bmp num*/     0,
        /*ArgCount*/    3,
        /*arg lp*/      s_ArgInfo,
        };

        // 命令实现函数
        void fnSplit (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf)
        {
            LPTSTR szBeSplited = pArgInf [0].m_pText;
            // 如果某个具有 AS_DEFAULT_VALUE_IS_EMPTY 标志的参数用户程序中没有为其提供参数值,
            // 则其数据类型为 _SDT_NULL 。
            LPTSTR szMark = pArgInf [1].m_dtDataType == _SDT_NULL ? _T(",") : pArgInf [1].m_pText;
            INT nCount = pArgInf [2].m_dtDataType == _SDT_NULL ? -1 : max (0, pArgInf [2].m_int);

            INT nLen1 = strlen (szBeSplited);
            INT nLen2 = strlen (szMark);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -