#include "stdafx.h"
#include "common.h"
#include "RRGrid.h"
//内部消息定义
#define GM_LOAD_GRID WM_GRID_USER_INNER + 1
#define GM_SAVE_GRID WM_GRID_USER_INNER+2
#define GM_SET_EDIT_TEXT WM_GRID_USER_INNER+3
#define GM_GET_EDIT_TEXT WM_GRID_USER_INNER+4
#define GM_GET_TITLE_TEXT WM_GRID_USER_INNER+5
#define ROWS_MAX 32000//不包括第0行
#define COLS_MAX 256 //不包括第0列
#define CELL_TEXT_MAX 512
#define DATA_SYMBOL_LEN 12
#define LINE_BORDER_SIZE 6
#define CURSOR_ARROW 1
#define CURSOR_DRAG 2//改变列宽时光标状态
#define CURSOR_EDITING 3
//RR_GridCtrl_GetLogicColOnScreen 参数/返回值描述
#define RR_PARAM_MASk 0x0F
#define RR_PARAM_START_COLNO 0x00
#define RR_PARAM_END_COLNO 0x01
#define RR_RESULT_MASK 0xF0
#define RR_RESULT_HALF 0x00
#define RR_RESULT_INTACT 0x10
#define RR_GRID_FILE_HEAD "RRGrid"
#define RR_STRUCT_SIZE_MAX 1300
typedef struct _tagGrid
{
HWND hWnd;
HWND hChildEdit;
StringLink_T *ptTextLink;
UINT nGridId;
HFONT hbodyfont;//第0列和数据单元采用一样的字体
HFONT hheadfont;//标题字体
HFONT htitlefont;//第0行字体
HBRUSH hEditBackBrush;
//栅格线颜色
COLORREF crGridLine;
//标题/第0行/0列文本颜色
COLORREF crTextTitle;
//画刷颜色(未选择高亮时,选择行画刷颜色跟其他行一样)
COLORREF crBrushReadOnly;//只读时的颜色
COLORREF crBrushCommon;//一般状态颜色
//高亮:Grid有焦点时选择行画刷颜色
COLORREF crBrushLight;
//高亮: Grid无焦点时选择行画刷颜色
COLORREF crBrushGray;
//每个画刷颜色有一个文本颜色与之相配
COLORREF crTextReadOnly;
COLORREF crTextCommon;
COLORREF crTextLight;
COLORREF crTextGray;
char *pszTitle;
int titleheight;//标题高度
int headerrowheight;//第0行高度(没有第0行,该值为0)
int rowheight; //行高等高
int columnwidths[COLS_MAX+1];//列宽不等宽
int gridHeight;//客户区域高
int gridWidth;//客户区域宽
GridCell_T tEditCell;//当前正在编辑的逻辑单元
int rows;//行数(包括第0行)
int cols;//列数(包括第0列)
int homerow;
int homecol;//逻辑列号,指示横向滚动条当前位置所对应的左边第一列(不包括第0列,最小值为1)
int leftvisiblecol; //逻辑列号,指示当前显示的左边第一列(为0(最小值)时表示当前没有显示的数据单元)
int rightvisiblecol;
int topvisiblerow;//逻辑行号
int bottomvisiblerow;
int sel_row;
DWORD dwStyle;
BOOL bCellModified;//单元内容被修改标志
BOOL bRowModified;//行内容被修改标志
BOOL bGridTextModified;//Grid内容被修改标志
BOOL bGridFrameModified;
//内部使用的一些状态变量
int adjust_height;//bShowIntegralRow为TRUE时累计调整的高度
BOOL bColumnSizing;//列宽正在改变中
int resizeColumn;//改变列宽时使用
int columnInitSize;//改变列宽时使用
int columnInitx;//改变列宽时使用
int cursortype;
BOOL bGridHasFocus;//当前Grid获得焦点
BOOL bSizing; //正在响应WM_SIZE
BOOL bShowHScroll;//是否显示横向滚动条
BOOL bShowVScroll; //是否显示纵向滚动条
BOOL bEditing;//正在编辑中
//默认值
int init_rows;//行数(包括第0行)
int init_cols;//列数(包括第0列)
DWORD dwInitStyle;
} Grid_T;
typedef struct _tagGridSaveStruct
{
COLORREF crGridLine;
COLORREF crTextTitle;//Roger: 暂未提供接口修改
COLORREF crBrushReadOnly;//只读时的颜色
COLORREF crBrushCommon;//一般状态颜色
COLORREF crBrushLight;
COLORREF crBrushGray;
COLORREF crTextReadOnly;
COLORREF crTextCommon;
COLORREF crTextLight;
COLORREF crTextGray;
int titleheight;//标题高度//Roger: 标题高度由标题文本确定
int headerrowheight;//第0行高度(没有第0行,该值为0)
int rowheight; //行高等高
int columnwidths[COLS_MAX+1];//列宽不等宽
int rows;//行数(包括第0行)
int cols;//列数(包括第0列)
int homerow; //单单homerow/homecol改变,不置Grid修改标志
int homecol;//逻辑列号,指示横向滚动条当前位置所对应的左边第一列(不包括第0列,最小值为1)
int sel_row;
DWORD dwStyle;
}GridSaveStruct_T;
static BOOL RR_GridCtrl_Exit_Edit(HWND hWnd);
static BOOL RR_GridCtrl_Enter_Edit(HWND hWnd,GridCell_T*ptCell,int iSetSel);
static int RR_GridCtrl_GetNextNthColWithWidth(Grid_T * pGridData, int startcol, int direction);
static LRESULT RR_GridCtrlOnVScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static int RR_GridCtrl_ChgSelRow(HWND hWnd,int new_row);
static void RR_GridCtrl_CalcVisibleCellBoundaries(Grid_T * pGridData);
static BOOL RR_GridCtrl_Discard_Edit(HWND hWnd);
static BOOL RR_GridCtrl_Force_Exit_Edit(HWND hWnd);
typedef long (__stdcall *CELLEDIT_PROC_T)(HWND,UINT,WPARAM,LPARAM);
static CELLEDIT_PROC_T OriginalEditProc;
//
static BOOL RR_GridCtrl_CopyStruct(GridSaveStruct_T *pSaveStruct,Grid_T* pGridData,BOOL bFirstIsDest)
{
if(pGridData==NULL || pSaveStruct == NULL )
{
return FALSE;
}
if(bFirstIsDest)
{
memcpy(pSaveStruct->columnwidths,pGridData->columnwidths,sizeof(pGridData->columnwidths));
pSaveStruct->crGridLine = pGridData->crGridLine;
pSaveStruct->crTextTitle = pGridData->crTextTitle;
pSaveStruct->crBrushReadOnly = pGridData->crBrushReadOnly;
pSaveStruct->crBrushCommon = pGridData->crBrushCommon;
pSaveStruct->crBrushLight = pGridData->crBrushLight;
pSaveStruct->crBrushGray = pGridData->crBrushGray;
pSaveStruct->crTextReadOnly = pGridData->crTextReadOnly;
pSaveStruct->crTextCommon = pGridData->crTextCommon;
pSaveStruct->crTextLight = pGridData->crTextLight;
pSaveStruct->crTextGray = pGridData->crTextGray;
pSaveStruct->titleheight = pGridData->titleheight;
pSaveStruct->headerrowheight= pGridData->headerrowheight;
pSaveStruct->rowheight = pGridData->rowheight;
pSaveStruct->rows = pGridData->rows;
pSaveStruct->cols = pGridData->cols;
pSaveStruct->homerow=pGridData->homerow;
pSaveStruct->homecol = pGridData->homecol;
pSaveStruct->sel_row = pGridData->sel_row;
pSaveStruct->dwStyle = pGridData->dwStyle;
}
else
{
memcpy(pGridData->columnwidths,pSaveStruct->columnwidths,sizeof(pSaveStruct->columnwidths));
pGridData->crGridLine = pSaveStruct->crGridLine;
pGridData->crTextTitle = pSaveStruct->crTextTitle;
pGridData->crBrushReadOnly = pSaveStruct->crBrushReadOnly;
pGridData->crBrushCommon = pSaveStruct->crBrushCommon;
pGridData->crBrushLight = pSaveStruct->crBrushLight;
pGridData->crBrushGray = pSaveStruct->crBrushGray;
pGridData->crTextReadOnly = pSaveStruct->crTextReadOnly;
pGridData->crTextCommon = pSaveStruct->crTextCommon;
pGridData->crTextLight = pSaveStruct->crTextLight;
pGridData->crTextGray = pSaveStruct->crTextGray;
pGridData->titleheight = pSaveStruct->titleheight;
pGridData->headerrowheight= pSaveStruct->headerrowheight;
pGridData->rowheight = pSaveStruct->rowheight;
pGridData->rows = pSaveStruct->rows;
pGridData->cols = pSaveStruct->cols;
pGridData->homerow=pSaveStruct->homerow;
pGridData->homecol = pSaveStruct->homecol;
pGridData->sel_row = pSaveStruct->sel_row;
pGridData->dwStyle = pSaveStruct->dwStyle;
}
return TRUE;
}
static BOOL RR_GetReadOnlyStyle(HWND hWnd)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_READONLY)
{
return TRUE;
}
else
{
return FALSE;
}
}
static void RR_SetReadOnlyStyle(HWND hWnd ,BOOL bReadOnly)
{
Grid_T * pGridData;
DWORD dwSysStyle ;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
dwSysStyle = GetWindowLong(hWnd,GWL_STYLE);
if (bReadOnly)
{
//只读时不接受焦点
if(dwSysStyle & WS_TABSTOP)
{
dwSysStyle= dwSysStyle & (~WS_TABSTOP);
SetWindowLong(hWnd,GWL_STYLE ,dwSysStyle);
}
pGridData->dwStyle = pGridData->dwStyle | GS_READONLY;
}
else
{
if(!(dwSysStyle & WS_TABSTOP))
{
dwSysStyle= dwSysStyle | WS_TABSTOP;
SetWindowLong(hWnd,GWL_STYLE ,dwSysStyle);
}
pGridData->dwStyle = pGridData->dwStyle & ~GS_READONLY;
}
}
static BOOL RR_GetExtendLastColumnStyle(HWND hWnd)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_LASTCOL_NOEXTEND)
{
return FALSE;
}
else
{
return TRUE;
}
}
static BOOL RR_GetColumnAllowResizeStyle(HWND hWnd)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_COLUMN_NORESIZE)
{
return FALSE;
}
else
{
return TRUE;
}
}
static void RR_SetColumnAllowResizeStyle(HWND hWnd ,BOOL bAllow)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if (bAllow)
{
pGridData->dwStyle = pGridData->dwStyle & ~GS_COLUMN_NORESIZE;
}
else
{
pGridData->dwStyle = pGridData->dwStyle | GS_COLUMN_NORESIZE;
}
}
static BOOL RR_GetColHeadIsNumberStyle(HWND hWnd)
{
//第0行是否设成ABCDE之类的字母
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_COLHEAD_CUSTOM)
{
return FALSE;
}
else
{
return TRUE;
}
}
static BOOL RR_GetRowHeadIsNumberStyle(HWND hWnd)
{
//第0列是否设成12345之类的数字
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_ROWHEAD_CUSTOM)
{
return FALSE;
}
else
{
return TRUE;
}
}
static BOOL RR_GetShowIntegralRowStyle(HWND hWnd)
{
//是否调整Grid高度,以显示完整的行高
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_GRIDHIGH_NOADJUST)
{
return FALSE;
}
else
{
return TRUE;
}
}
static BOOL RR_GetHighLightStyle(HWND hWnd)
{
//选择行是否高亮显示
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_SELROW_INVISIBLE)
{
return FALSE;
}
else
{
return TRUE;
}
}
static void RR_SetHighLightStyle(HWND hWnd ,BOOL bHighLight)
{
//选择行是否高亮显示
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if (bHighLight)
{
pGridData->dwStyle = pGridData->dwStyle & ~GS_SELROW_INVISIBLE;
}
else
{
pGridData->dwStyle = pGridData->dwStyle | GS_SELROW_INVISIBLE;
}
}
static BOOL RR_GetInsertKeyStyle(HWND hWnd)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_CANCEL_INSKEY)
{
return FALSE;//不响应Insert键进行插入
}
else
{
return TRUE;
}
}
static BOOL RR_GetDeleteKeyStyle(HWND hWnd)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_CANCEL_DELKEY)
{
return FALSE;//不响应Delete键进行行删除
}
else
{
return TRUE;
}
}
static BOOL RR_GetEnterKeyStyle(HWND hWnd)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle & GS_CANCEL_ENTER_INSERT)
{
return FALSE;//回车键在最后行没有添加行功能
}
else
{
return TRUE;
}
}
//返回值:TRUE ,不再交给默认过程处理
static LRESULT RR_CellEditOnKeyDown(HWND hCellEdit, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lRet = 0;
HWND hGrid=GetParent(hCellEdit);
Grid_T * pGridData = NULL;
GridCell_T tMoveToCell;
pGridData = (Grid_T *)GetWindowLong(hGrid,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(!pGridData->bEditing)
{
return lRet;
}
switch(wParam)
{
case VK_ESCAPE:
RR_GridCtrl_Discard_Edit(hGrid);
lRet = TRUE;
break;
case VK_RETURN:
if(pGridData->tEditCell.row == pGridData->rows-1 &&
pGridData->tEditCell.col ==pGridData->cols-1 &&
RR_GetEnterKeyStyle(hGrid))
{
//插入新行,进入新行编辑
int row = pGridData->rows;
if(SendMessage(hGrid,GM_GRID_INSERT_ROW,row,0)==0)
{
tMoveToCell.row = row ;
tMoveToCell.col = pGridData->leftvisiblecol;
RR_GridCtrl_Enter_Edit(hGrid,&tMoveToCell,0);
}
lRet = TRUE;
break;
}
if(pGridData->tEditCell.col<pGridData->rightvisiblecol)
{
tMoveToCell.row = pGridData->tEditCell.row ;
tMoveToCell.col = RR_GridCtrl_GetNextNthColWithWidth(pGridData,pGridData->tEditCell.col,1);
}
else if(pGridData->tEditCell.row < pGridData->bottomvisiblerow)
{
tMoveToCell.row = pGridData->tEditCell.row +1;
tMoveToCell.col = pGridData->leftvisiblecol;
}
else
{
tMoveToCell.row = pGridData->topvisiblerow;
tMoveToCell.col = pGridData->leftvisiblecol;
}
RR_GridCtrl_Enter_Edit(hGrid,&tMoveToCell,0);
lRet = TRUE;
break;
case VK_TAB:
if(GetKeyState(VK_SHIFT) < 0)
{
//支持shift+TAB反方向移动
if(pGridData->tEditCell.col>pGridData->leftvisiblecol)
{
tMoveToCell.row = pGridData->tEditCell.row ;
tMoveToCell.col = RR_GridCtrl_GetNextNthColWithWidth(pGridData,pGridData->tEditCell.col,-1);
}
else if(pGridData->tEditCell.row > pGridData->topvisiblerow)
{
tMoveToCell.row = pGridData->tEditCell.row -1;
tMoveToCell.col = pGridData->rightvisiblecol;
}
else
{
tMoveToCell.row = pGridData->bottomvisiblerow;
tMoveToCell.col = pGridData->rightvisiblecol;
}
}
else
{
if(pGridData->tEditCell.col<pGridData->rightvisiblecol)
{
tMoveToCell.row = pGridData->tEditCell.row ;
tMoveToCell.col = RR_GridCtrl_GetNextNthColWithWidth(pGridData,pGridData->tEditCell.col,1);
}
else if(pGridData->tEditCell.row < pGridData->bottomvisiblerow)
{
tMoveToCell.row = pGridData->tEditCell.row +1;
tMoveToCell.col = pGridData->leftvisiblecol;
}
else
{
tMoveToCell.row = pGridData->topvisiblerow;
tMoveToCell.col = pGridData->leftvisiblecol;
}
}
RR_GridCtrl_Enter_Edit(hGrid,&tMoveToCell,0);
lRet = TRUE;
break;
case VK_LEFT:
{
int start=0;
int end=0;
SendMessage(hCellEdit,EM_GETSEL,(WPARAM)&start,(LPARAM)&end);
if(GetKeyState(VK_CONTROL) < 0 && (start >0 || end >0))
{
//VK_CONTROL键被按下(组合键)
SendMessage(hCellEdit,EM_SETSEL,0,0);
lRet = TRUE;
break;
}
if(start==0 && end ==0)//左移一单元编辑
{
tMoveToCell.col = RR_GridCtrl_GetNextNthColWithWidth(pGridData,pGridData->tEditCell.col,-1);
tMoveToCell.row = pGridData->tEditCell.row;
RR_GridCtrl_Enter_Edit(hGrid,&tMoveToCell,1);
lRet = TRUE;
}
}
break;
case VK_RIGHT:
{
int start=0;
int end=0;
int len=0;
len = SendMessage(hCellEdit,EM_LINELENGTH,0,0);
SendMessage(hCellEdit,EM_GETSEL,(WPARAM)&start,(LPARAM)&end);
if(GetKeyState(VK_CONTROL) < 0 && (end<len ||start<len))
{
//VK_CONTROL键被按下(组合键)
SendMessage(hCellEdit,EM_SETSEL,len+1,len+1);
lRet = TRUE;
break;
}
if(start == len && end == len)
{
tMoveToCell.col = RR_GridCtrl_GetNextNthColWithWidth(pGridData,pGridData->tEditCell.col,1);
tMoveToCell.row = pGridData->tEditCell.row;
RR_GridCtrl_Enter_Edit(hGrid,&tMoveToCell,1);
lRet = TRUE;
}
}
break;
case VK_UP:
tMoveToCell.col = pGridData->tEditCell.col;
tMoveToCell.row = pGridData->tEditCell.row-1;
RR_GridCtrl_Enter_Edit(hGrid,&tMoveToCell,1);
lRet = TRUE;
break;
case VK_DOWN:
tMoveToCell.col = pGridData->tEditCell.col;
tMoveToCell.row = pGridData->tEditCell.row+1;
RR_GridCtrl_Enter_Edit(hGrid,&tMoveToCell,1);
lRet = TRUE;
break;
default:
break;
}
return lRet;
}
static LRESULT ModifierCellEditProc(HWND hCellEdit,UINT message,WPARAM wParam,LPARAM lParam)
{
LRESULT lRet;
switch (message)
{
case WM_GETDLGCODE:
{
lRet = CallWindowProc(OriginalEditProc,hCellEdit,message,wParam,lParam);
// If lParam points to an MSG structure
if (lParam)
{
LPMSG lpmsg = (LPMSG)lParam;
if (lpmsg->message == WM_KEYDOWN)
{
switch(lpmsg->wParam)
{
case VK_ESCAPE:
case VK_RETURN:
case VK_TAB:
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
lRet |= DLGC_WANTMESSAGE;
break;
default:
break;
}
}
}
}
return lRet;
case WM_KEYDOWN:
lRet = RR_CellEditOnKeyDown(hCellEdit,message,wParam,lParam);
if(lRet)
{
return 0;//lRet 返回TRUE ,不再交给默认过程处理
}
break;
case WM_KILLFOCUS:
{
HWND hParent = GetParent(hCellEdit);
RR_GridCtrl_Force_Exit_Edit(hParent);
SendMessage(hParent,message,wParam,lParam);
}
break;
case WM_SETCURSOR:
SetCursor(LoadCursor(NULL,IDC_IBEAM));
return 0;
case WM_ERASEBKGND:
return 0;//直接return 编辑框将不会画鼠标指针
default:
break;
}
return CallWindowProc(OriginalEditProc,hCellEdit,message,wParam,lParam);
}
static int RR_GridCtrl_Notify(HWND hWnd,UINT code,LPARAM lParam)
{
Grid_T * pGridData = NULL;
GridNotify_T tNotify;
WPARAM wParam;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
//memset(tNotify,0,sizeof(GridNotify_T));
tNotify.hwndFrom = hWnd;
tNotify.idFrom = pGridData->nGridId;
tNotify.code = code;
tNotify.param = lParam;
tNotify.retVal =0;
wParam=MAKEWPARAM(tNotify.idFrom,tNotify.code);
SendMessage(GetParent(hWnd),GM_GRID_NOTIFY,wParam,(LPARAM)&tNotify);
//SendMessage(GetParent(hWnd),WM_COMMAND,wParam,lParam);
return tNotify.retVal;
}
BOOL RR_GridCtrl_OutOfRange(GridCell_T *cell)
{
if(cell->row > ROWS_MAX || cell->row <0 ||
cell->col > COLS_MAX || cell->col<0)
{
return TRUE;
}
else
{
return FALSE;
}
}
//返回与szSymbol匹配项的索引
static ListNode * RR_GridCtrl_SearchData(StringLink_T *ptStrLink,char szSymbol[])
{
StringLinkNode_T* pStrNode;
ListNode *p = NULL;
int len =0;
if(ptStrLink == NULL || szSymbol == NULL)
{
return NULL;
}
len = strlen(szSymbol);
List_ForEach(p,&(ptStrLink->head))
{
pStrNode = List_Entry(p,StringLinkNode_T,node);
if(strncmp(pStrNode->szString,szSymbol,len) ==0)
{
return p;
}
}
return NULL;
}
//bInsert :TRUE -- 插入行,排在row/col后面的单元行号加1
//FALSE -- 删除行,排在row/col后面的单元行号减1
static BOOL RR_GridCtrl_UpdateData(StringLink_T *ptStrLink,int row ,BOOL bInsert)
{
char szSymbol[DATA_SYMBOL_LEN+1];
char szRow[DATA_SYMBOL_LEN+1];
ListNode *p,*q;
StringLinkNode_T *pStrNode = NULL;
int len =0;
int line=0;
if(ptStrLink == NULL || row <1)
{
return FALSE;
}
sprintf(szSymbol,"%05d-%03d",row,0); //9
len = strlen(szSymbol);
List_ForEachSafe(p,q,&(ptStrLink->head))
{
pStrNode = List_Entry(p,StringLinkNode_T,node);
if(strncmp(pStrNode->szString,szSymbol,len) >=0)
{
line = atoi(pStrNode->szString);
RR_ASSERT(line>=row);
if(bInsert)
{
line++;
sprintf(szRow,"%05d",line);
strncpy(pStrNode->szString,szRow,5);
}
else
{
if(line == row)
{
//删除该行的数据单元
List_Del(&pStrNode->node);
ptStrLink->node_cnt --;
RR_Safe_Free(pStrNode->szString);
RR_Safe_Free(pStrNode);
}
else
{
line--;
sprintf(szRow,"%05d",line);
strncpy(pStrNode->szString,szRow,5);
}
}
}
}
return TRUE;
}
static int RR_GridCtrl_ChgSelRow(HWND hWnd,int new_row)
{
Grid_T * pGridData = NULL;
int old_row;
int ret;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
RR_ASSERT(new_row>0 && new_row <pGridData->rows);
old_row = pGridData->sel_row;
if(new_row == old_row)
{
return 0;
}
ret = RR_GridCtrl_Notify(hWnd,GN_ROW_CHANGED,MAKELPARAM(new_row,old_row));
if(ret== 0)
{
//选择行被改变
pGridData->sel_row = new_row;
pGridData->bRowModified = FALSE;
}
return ret;
}
static int RR_GridCtrl_GetLogicColOnScreen(Grid_T* pGridData,int reference_col,unsigned char description)
{
int gridWidth;
int i=0;
int col;
RR_ASSERT(pGridData!=NULL);
if(reference_col<0 || reference_col>=pGridData->cols)
{
RR_ASSERT(0);
return -1;
}
gridWidth = pGridData->gridWidth;
col = reference_col;
if((description&RR_PARAM_MASk) == RR_PARAM_START_COLNO)
{
//reference_col是开始列号
if(reference_col>0)
{
gridWidth-=pGridData->columnwidths[0];
}
for(i = reference_col;i<pGridData->cols;i++)
{
if(pGridData->columnwidths[i]>0)
{
if(gridWidth <= pGridData->columnwidths[i])
{
if((description & RR_RESULT_MASK) == RR_RESULT_HALF)
{
//可以部分显示
col = i;
}
else if(gridWidth == pGridData->columnwidths[i])
{
//完整显示单元
col =i;
}
break;
}
gridWidth-=pGridData->columnwidths[i];
col = i;
}
}
}
else
{
//reference_col是结束列号
//返回的一定是Grid能完全装下的列号
if(reference_col ==0 )
{
return 0;
}
gridWidth -= pGridData->columnwidths[0];
//返回值>0
for(i =reference_col;i>=1;i--)
{
if(pGridData->columnwidths[i]>0)
{
if(gridWidth < pGridData->columnwidths[i])
{
break;
}
else if (gridWidth ==pGridData->columnwidths[i])
{
col = i;
break;
}
gridWidth-=pGridData->columnwidths[i];
col = i;
}
}
}
return col;
}
//统计从startcol开始(含该列)到endcol(含)之间有宽度的列数
//pTotalWidth返回startcol 到endcol之间有宽度列宽度之和
//返回值:
static int RR_GridCtrl_GetColumnsWithWidth(Grid_T * pGridData, int startcol,int endcol,int* pTotalWidth)
{
int totalpixels=0;
int j;
int colswithwidth=0;
RR_ASSERT(pGridData!=NULL);
if(startcol<0 || startcol>=pGridData->cols ||
endcol<0 || endcol>=pGridData->cols||
startcol>endcol)
{
if(pTotalWidth!=NULL)
{
*pTotalWidth =0;
}
return 0;
}
//列宽不等宽
for(j=startcol;j<=endcol;j++)
{
if(pGridData->columnwidths[j]>0)
{
totalpixels += pGridData->columnwidths[j];
colswithwidth++;
}
}
if(pTotalWidth!=NULL)
{
*pTotalWidth = totalpixels;
}
return colswithwidth;
}
//得到下|direction|个有宽度的列的列号
//direction>0 往右数,direction <0往左数
//返回值<0表示往左(右)没有第|direction|个有宽度的列
//该函数可以返回第0列(调用时注意)
static int RR_GridCtrl_GetNextNthColWithWidth(Grid_T * pGridData, int startcol, int direction)
{
int n=0;
int col=startcol;
int abs_val=abs(direction);
RR_ASSERT(pGridData!=NULL);
if(startcol<0 || startcol>=pGridData->cols)
{
//输入参数不合法
return -1;
}
if(direction==0)
{
//RR_ASSERT(0);
return startcol;
}
else if(direction>0)
{
col++;
}
else
{
col--;
}
while(col>=0 && col<pGridData->cols)
{
if(pGridData->columnwidths[col]!= 0)
{
n++;
if(n==abs_val)
{
break;
}
}
if(direction>0)
{
col++;
}
else
{
col--;
}
}
if(n==abs_val)
{
RR_ASSERT(col>=0 && col<pGridData->cols);
return col;
}
else
{
return -2;
}