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

📄 list.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************
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 + -