📄 list.c
字号:
/******************************************************
Copyright(c) 版权所有,1998-2003微逻辑。保留所有权利。
******************************************************/
/*****************************************************
文件说明:list class
版本号:1.0.0
开发时期:2003-04-07
作者:李林
修改记录:
2005-01-26, add code, DoRESETCONTENT 没有刷新滚动条
2004-12-21, 改变 DoLBUTTONUP & DoLBUTTONDOWN , 去掉 SetCapture功能
因为有可能在 发LB_CLICK 后AP进入其它画面,然后又被 SetCapture
2004-10-27, DoSETCURSEL 2004-10-27, modify, 优化
2004-08-27, 将 _LISTDATA 的 count 成员有 short 改为 WORD
2004-03-06, LN DoSetRedraw 之前并没有做任何事情
2003-08-29 LN, not sent LBN_SELCHANGE when use LB_SETCURSEL
2003-06-23, DoSETCARETINDEX 增加对Caret的隐藏
******************************************************/
#include <eframe.h>
#include <estring.h>
#include <eassert.h>
#include <ealloc.h>
//#include <gwmesrv.h>
#define ITEMEXT 10
#define ITEM_HEIGHT 16
#define ITEM_WIDTH 8
#define AUTO_UP 0xfffe
#define AUTO_DOWN 0xfffd
#define AUTO_HOLD 0xffc
//#define _MAPPOINTER
// 定义列表框项目结构
typedef struct __LISTITEM
{
LPSTR lpszItem; //列表框项目数据
DWORD dwItemData; //列表框项目用户数据
WORD typeData; //列表框项目用户数据类型
WORD state; //当前列表项目状态
}_LISTITEM, FAR * _LPLISTITEM;
// 定义列表框结构
typedef struct __LISTDATA
{
_LPLISTITEM lpItems; //列表框项目指针
DWORD dwStyle; //列表框风格
WORD count; //列表框当前项目数
BYTE bFree; //是否由列表框释放内容(无用)
BYTE bDown; //是否在画面有处理 WM_LBUTTONDOWN 消息
short limit; //列表框可容纳的最大项目数目
short caret; //列表框当前标注项目
short curSel; //列表框当前被选择项目(用于单项选择风格)use when single-selection
short topIndex; //列表框当前显示窗口的最顶项目
short colWidth; //列表框列宽
short rowHeight; //列表框行宽
short colNum; //列表框列数
short bCombBoxList; //是否是组合框列表风格
HWND hCombBox; //假如是组合框列表,该项有效,表示组合框窗口
COLORREF cl_Text; //正常文本的前景与背景色
COLORREF cl_TextBk; //
COLORREF cl_Selection; //选择文本的前景与背景色
COLORREF cl_SelectionBk; //
COLORREF cl_Disable; //无效文本的前景与背景色
COLORREF cl_DisableBk; //
HANDLE hFont;
}_LISTDATA, FAR * _LPLISTDATA;
// insert before index
static _LPLISTITEM InsertItem( _LPLISTDATA, int * index );
static BOOL SetItemData( _LPLISTDATA, int index, DWORD dwData );
static BOOL SetItemTypeData( _LPLISTDATA, int index, WORD dwTypeData );
static BOOL RemoveItem( _LPLISTDATA, int index );
static BOOL ResetLimit( _LPLISTDATA, int newLimit );
static int SetItemState( _LPLISTDATA, int index, WORD state, BOOL bEnable );
static BOOL FreeItem( LPSTR lpstr );
static _LPLISTITEM At( _LPLISTDATA, int index );
static int Count( _LPLISTDATA );
//static BOOL Pack( _LPLISTDATA );
static void RedrawItem( _LPLISTDATA lpData,
HWND hWnd,
DWORD dwStyle,
HDC hdc,
int iFrom,
int iTo,
BOOL bEraseBottom
);
static LRESULT DoADDSTRING( HWND hWnd, LPCSTR lpcstr );
static LRESULT DoINSERTSTRING( HWND hWnd, int index, LPCSTR lpcstr );
static LRESULT DoSETSEL( HWND hWnd, BOOL fSelect, int index );
static LRESULT DoSETCURSEL( HWND hWnd, int index, BOOL bNotify );
static LRESULT DoSETTOPINDEX( HWND hWnd, int index );
static LRESULT DoSELITEMRANGE( HWND hWnd, BOOL fSelect, int first, int last );
static LRESULT DoSETCARETINDEX( HWND hWnd, int index, BOOL fScroll );
static short GetItemRect( _LPLISTDATA, int index, LPRECT lpRect, DWORD style );
static int GetRows( _LPLISTDATA, DWORD dwStyle, LPCRECT lpClienRect );
static int GetCols( _LPLISTDATA, LPCRECT lpClienRect );
static int AtRow( _LPLISTDATA, DWORD dwStyle, int y );
static int AtCol( _LPLISTDATA, DWORD dwStyle, int x );
static void DrawItemContents ( HWND hWnd, _LPLISTDATA lpListData, DWORD dwStyle, HDC hdc, int index, LPCRECT lpRect, BOOL bHasCaret, UINT uiAction );
static void DrawCaret( HDC hdc, LPCRECT lpRect );
static void SendNotify( HWND hWnd, const short code );
static BOOL SetScrollBar( HWND hWnd, int pos, int *lpNewPos );
static int ScrollRow( HWND hWnd, int code );
static int ScrollCol( HWND hWnd, int code );
static void CALLBACK TimerProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime );
static LRESULT WINAPI ListBoxWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
static LRESULT WINAPI CombBoxListBoxWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
// 列表框类名
static const char strClassListBox[] = "LISTBOX";
// **************************************************
// 声明:ATOM RegisterListBoxClass(HINSTANCE hInst)
// 参数:
// IN hInst - 实例句柄
// 返回值:
// 假如成功,返回非0值;失败,返回0
// 功能描述:
// 注册列表框类
// 引用:
// 被sysclass.c 调用
// ************************************************
// register my define class
ATOM RegisterListBoxClass(HINSTANCE hInst)
{
WNDCLASS wc;
wc.hInstance=hInst;
wc.lpszClassName= strClassListBox;
// the proc is class function
wc.lpfnWndProc = ListBoxWndProc;
wc.style=CS_DBLCLKS;
wc.hIcon= 0;
// at pen window, no cursor
wc.hCursor= LoadCursor(NULL,IDC_ARROW);
// to auto erase background, must set a valid brush
// if 0, you must erase background yourself
wc.hbrBackground = NULL;
wc.lpszMenuName=NULL;
wc.cbClsExtra=0;
// !!! it's important to save state of button, align to long
//私有数据
wc.cbWndExtra= sizeof( void * );
return RegisterClass(&wc);
}
// 组合列表框类名
static const char strClassComboListBox[] = "COMBOLISTBOX";
// register my define class
// **************************************************
// 声明:ATOM RegisterComboListBoxClass(HINSTANCE hInst)
// 参数:
// IN hInst - 实例句柄
// 返回值:
// 假如成功,返回非0值;失败,返回0
// 功能描述:
// 注册组合列表框类
// 引用:
// 被sysclass.c 调用
// ************************************************
ATOM RegisterComboListBoxClass(HINSTANCE hInst)
{
WNDCLASS wc;
wc.hInstance=hInst;
wc.lpszClassName= strClassComboListBox;
// the proc is class function
wc.lpfnWndProc = CombBoxListBoxWndProc;
wc.style=CS_DBLCLKS;
wc.hIcon= 0;
// at pen window, no cursor
wc.hCursor= LoadCursor(NULL,IDC_ARROW);
// to auto erase background, must set a valid brush
// if 0, you must erase background yourself
wc.hbrBackground = NULL;
wc.lpszMenuName=NULL;
wc.cbClsExtra=0;
// !!! it's important to align to long
////私有数据
wc.cbWndExtra=sizeof( void * );
return RegisterClass(&wc);
}
// **************************************************
// 声明:static HDC GetListDC( HWND hWnd, PAINTSTRUCT * lpps, HFONT hFont )
// 参数:
// IN hWnd - 窗口句柄
// IN lpps - PAINTSTRUCT 结构指针
// IN hFont - 字体句柄
// 返回值:
// 假如成功,返回DC 句柄
// 功能描述:
// 得到DC(如果 lpps 为NULL,用GetDC,否则用BeginPaint)
// 引用:
//
// ************************************************
static HDC GetListDC( HWND hWnd, PAINTSTRUCT * lpps, _LPLISTDATA lpListData )
{
HDC hdc;
if( lpps )
{
hdc = BeginPaint( hWnd, lpps );
}
else
hdc = GetDC( hWnd );
if( lpListData->hFont )
SelectObject( hdc, lpListData->hFont );
return hdc;
}
// **************************************************
// 声明:static VOID ReleaseListDC( HWND hWnd, PAINTSTRUCT * lpps, _LPLISTDATA lpListData )
// 参数:
// IN hWnd - 窗口句柄
// IN hdc - DC句柄
// IN lpps - PAINTSTRUCT 结构指针
// 返回值:
// 无
// 功能描述:
// 释放DC
// 引用:
//
// ************************************************
static VOID ReleaseListDC( HWND hWnd, HDC hdc, PAINTSTRUCT * lpps )
{
if( lpps )
{
EndPaint( hWnd, lpps );
}
else
ReleaseDC( hWnd, hdc );
}
// **************************************************
// 声明:static _LPLISTITEM InsertItem( _LPLISTDATA lpListData, int * index )
// 参数:
// IN/OUT lpListData - 列表框对象指针
// IN/OUT index - 将列表框项目插入位置,假如为-1,表示将列表框项目插到最后并返回实际的位置
// 返回值:
// 假如成功,返回新的项目指针; 否则,返回0
// 功能描述:
// 在当前列表框位置新增一个列表项目的内存空间
// 引用:
//
// ************************************************
static _LPLISTITEM InsertItem( _LPLISTDATA lpListData, int * index )
{
if( lpListData->count == lpListData->limit )
{ // 没有更多的列表项目的内存空间,需要新增列表项目
// 每次新增固定数目的项目空间以备以后使用
if( ResetLimit( lpListData, (lpListData->limit + ITEMEXT) ) == FALSE )
return 0; //分配失败
}
if( *index == -1 )
{ //新项目在末尾
*index = lpListData->count;
}
else
{ //新项目在列表框中间,需要移动已经存在的项目
//[oooooooooo new oooooooold]
memmove( lpListData->lpItems + *index + 1,
lpListData->lpItems + *index,
(lpListData->count - *index) * sizeof( _LISTITEM ) );
}
//初始化新的
memset( lpListData->lpItems + *index, 0, sizeof(_LISTITEM) );
lpListData->count++; //更新实际项目数
//返回新项目
return lpListData->lpItems + *index;
}
// **************************************************
// 声明:static BOOL RemoveItem( _LPLISTDATA lpListData, int index )
// 参数:
// IN/OUT lpListData - 列表框对象指针
// IN index - 列表项目的索引号
// 返回值:
// 假如成功,返回TRUE; 否则,返回FALSe
// 功能描述:
// 移出列表项目,但并不减少整个列表项目的内存空间
// 引用:
//
// ************************************************
static BOOL RemoveItem( _LPLISTDATA lpListData, int index )
{
_ASSERT( (DWORD)index < lpListData->count );
//if( index >= 0 && index < lpListData->count )
if( (DWORD)index < lpListData->count )
{ // 索引号合法
lpListData->count--;
// 通过移动内存的方法移出该项目
// [ IIIIIIII (remove item) IIIIIIIIIII ]
memmove( lpListData->lpItems + index,
lpListData->lpItems + index + 1,
(lpListData->count - index) * sizeof( _LISTITEM ) );
return TRUE;
}
return FALSE;
}
// **************************************************
// 声明:static int DeleteItem( HWND hWnd, DWORD dwStyle, _LPLISTDATA lpListData, int index )
// 参数:
// IN hWnd - 列表窗口句柄
// IN dwStyle - 列表窗口风格
// IN/OUT lpListData - 列表框对象指针
// IN index - 列表项目索引号
// 返回值:
// 假如成功,返回返回当前列表框实际的列表项目数; 否则,返回LB_ERR
// 功能描述:
// 删除列表项目内容,并移出项目结构
// 返回当前列表框实际的列表项目数
// 引用:
//
// ************************************************
static int DeleteItem( HWND hWnd, DWORD dwStyle, _LPLISTDATA lpListData, int index )
{
_LPLISTITEM lpItem;
lpItem = At( lpListData, index );
if( dwStyle & LBS_HASSTRINGS )
{ //列表项目为字符串风格项目内容,释放该项目内容
FreeItem( lpItem->lpszItem );
}
else if( dwStyle & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE) )
{ //列表项目为用户自绘风格,必须让用户去释放项目数据
DELETEITEMSTRUCT ds;
ds.itemData = lpItem->dwItemData;
if( ds.itemData )
{ //准备发送的数据
ds.CtlType = ODT_LISTBOX;
ds.CtlID = (WORD)GetWindowLong( hWnd, GWL_ID );
ds.itemID = index;
ds.hwndItem = hWnd;
// 向父窗口发送数据
SendMessage( GetParent( hWnd ), WM_DELETEITEM, ds.CtlID, (LPARAM)&ds );
}
}
else
return LB_ERR; //错误
//移出项目结构
RemoveItem( lpListData, index );
return lpListData->count;
}
// **************************************************
// 声明:static int SetItemData( _LPLISTDATA lpListData, int index, DWORD dwData )
// 参数:
// IN/OUT lpListData - 列表框对象指针
// IN index - 列表项目索引号
// IN dwData - 需要设置的数据
// 返回值:
// 假如成功,返回0; 否则,返回LB_ERR
// 功能描述:
// 设置项目用户数据
// 引用:
//
// ************************************************
static BOOL SetItemData( _LPLISTDATA lpListData, int index, DWORD dwData )
{
_ASSERT( index >=0 && index < lpListData->count );
(lpListData->lpItems + index)->dwItemData = dwData;
return 0;
}
// **************************************************
// 声明:static BOOL ResetLimit( _LPLISTDATA lpListData, int newLimit )
// 参数:
// IN/OUT lpListData - 列表框对象指针
// IN newLimit - 新的项目内存空间
// 返回值:
// 假如成功,返回TRUE; 否则,返回FALSE
// 功能描述:
// 重新分配项目内存空间
// 引用:
//
// ************************************************
static BOOL ResetLimit( _LPLISTDATA lpListData, int newLimit )
{
_LPLISTITEM lpItem;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -