在C语言中二级指针是个很有用的东东。有时候在一些性能方面需做平衡且需要灵活性的时候,2级指针就非常有用。
例如在设计UI列表框的时候,我们如果要显示列表框的文本,WINDOWS编程,如果是用一般的GDI函数绘制文本比较慢。微软DX提供了一些方便使用的绘制文本函数,当然这些绘制文本函数不能解决裁剪问题。例如列表框中由于文字过多出现滚动条的时候,那么列表框只能显示其中部分文字,这时候只能自己想办法解决问题了,目前考虑到比较好的方案就是用2级指针。当然想追求速度可以用数组,例如可以为列表框每行文字数量设置一个固定值,然后简单用静态数组为列表框每行文本分配内存最快解决问题,而且高效。但是实在无法忍受其对内存所造成的浪费,当系统有很多列表框而列表框文字又参差不齐的时候更是不能忍受。这时候用2级指针感觉更好。
我在用DX做UI的时候,为了效率,我把整个菜单系统能显示的文本部分全部保存在一个静态字符数组区域。而在这个区域又可划分很多不同的“字符串块”,例如UI的某个文本框所指向的字符为一个字符串块,某个列表框显示的文本为一个字符串块。接下来在给列表框设置数据结构的时候分配一个2级指针,2级指针的好处就是灵活方便且不会造成内存浪费,可以为列表框显示的每行文本提供一个1级指针用于指向列表框每行显示的第1个字的开头位置地址,这样做的好处,就是当移动滚动条的时候直接用移动指针的方法处理文字绘图裁剪问题,而且2级指针的好处不用为每行要绘制的文本分配多余的内存,在遇见列表框每行文字特别参差不齐的时候,其体现得更好。
例如在定义列表框数据的时候可以:
struct LIST_BOX
{
WCHAR *pTextStartPointer; // 文本框指向其文本框对应字符串块的最起始地址
WCHAR **ppListBoxText; // 可用于保存文本框每行文字第1个字符的地址
WCHAR *pPTTextShowLine_1; // 文本框显示第一行第1个文字的地址
unsigned long LineNumber; // 列表框的总行数
unsigned long SelectReturnValue; // 列表框选择项的返回值
unsigned long MouseInBoxPos; // 鼠标所在列表框位置选项的索引
等等和列表框相关数据
…………
…………
…………
};
LIST_BOX *gpListBoxUnion; // 声明列表框元素数据的集合
// 初始化2级指针函数:
int InitListBoxPMemey( unsigned int ListBoxIndex, unsigned long LineNum )
{
// 为某个列表框根据列表框字符的行数(即选项数量)分配2级指针内存
( WCHAR ** )( gpListBoxUnion[ListBoxIndex].ppListBoxText ) = ( WCHAR ** )malloc( sizeof( WCHAR** ) * LineNum );
…………
}
接下来在设置列表框字符串数据函数的时候可以:
int SetListBoxText( unsigned int ListBoxIndex, unsigned long LineNum, const WCHAR *pChar, unsigned long TextCharNum )
{
…………
// 根据2级指针把预设置的文本字符赋给到之前提到的静态数组的字符区域中
for( i = 0; i < TextCharNum; i++ )
{
*( *( gpListBoxUnion[ListBoxIndex].ppListBoxText + LineNum ) + i ) = pChar[i];
}
*( *( gpListBoxUnion[ListBoxIndex].ppListBoxText + LineNum ) + TextCharNum + 1 ) = '/n'; // 换行处理
// 获取下行文本字符开头地址以及获得整列表框字符串块的总长度
if( LineNum < gpListBoxUnion[ListBoxIndex].LineNumber - 1 )
{
*( gpListBoxUnion[ListBoxIndex].ppListBoxText + LineNum + 1 ) = *( gpListBoxUnion[ListBoxIndex].ppListBoxText + LineNum ) + TextCharNum + 2;
}
else
{
gpListBoxUnion[ListBoxIndex].TextLen = *( gpListBoxUnion[ListBoxIndex].ppListBoxText + LineNum ) - gpListBoxUnion[ListBoxIndex].pTextStartPointer + TextCharNum;
}
…………
return 1;
}
当然还有很多问题,例如必须为每个列表框的*pTextStartPointer; *pPTTextShowLine_1等指针变量赋予一个合法的初始值。用DX渲染文字。等等还有很多细节问题在这里就省略了