📄 tech.txt
字号:
// 指针所指向数据的格式见前面的描述。
// !!!只可读取而不可更改其中的内容。
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 + -