#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;
}
}
//得到逻辑单元的矩形区域 (支持第0行第0列的单元)
static BOOL RR_GridCtrl_GetCellRect(HWND hWnd,int row, int col,RECT *pCellRect)
{
Grid_T * pGridData;
RECT rect;
RECT rtGrid;
int offset =0;
int j=0;
if(pCellRect==NULL)
{
RR_ASSERT(0);
return FALSE;
}
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(row<0 || row>=pGridData->rows ||
col<0 || col>=pGridData->cols)
{
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
if(col !=0)
{
if(pGridData->leftvisiblecol<1 || pGridData->rightvisiblecol<1)
{
//(当前没有显示的数据单元)
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
if(col < pGridData->leftvisiblecol || col > pGridData->rightvisiblecol)
{
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
offset=pGridData->columnwidths[0];
//计算从leftvisiblecol开始到col列的宽度偏移
for(j=pGridData->leftvisiblecol ;j<col;j++)
{
offset +=pGridData->columnwidths[j];
}
}
rect.left = offset ;
rect.right = offset +pGridData->columnwidths[col];
if(RR_GetExtendLastColumnStyle(hWnd) &&
RR_GridCtrl_GetNextNthColWithWidth(pGridData,col,1)<0)
{
//最后一列有宽度的列扩展到Grid右边界
rect.right = pGridData->gridWidth;
}
offset =pGridData->titleheight;//重置offset
if(row==0)
{
rect.top = offset;
rect.bottom = offset+pGridData->headerrowheight;
}
else
{
if(pGridData->topvisiblerow<1 || pGridData->bottomvisiblerow<1)
{
//(当前没有显示的数据单元)
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
if(row < pGridData->topvisiblerow || row > pGridData->bottomvisiblerow)
{
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
offset += pGridData->headerrowheight;
for(j=pGridData->topvisiblerow;j<row;j++)
{
offset += pGridData->rowheight;
}
rect.top = offset;
rect.bottom = offset+pGridData->rowheight;
}
SetRect(&rtGrid,0,0,pGridData->gridWidth,pGridData->gridHeight);
if(!IntersectRect(pCellRect,&rect,&rtGrid))
{
//两个矩形没有交集
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
if(IsRectEmpty(pCellRect))
{
return FALSE;
}
return TRUE;
}
//得到逻辑行的矩形区域,支持第0行
static BOOL RR_GridCtrl_GetRowRect(HWND hWnd,int row, RECT *pCellRect, BOOL bAdd0Col)
{
Grid_T * pGridData;
int offset =0;
int j=0;
RECT rtRow;
RECT rtGrid;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
RR_ASSERT(pCellRect!=NULL);
if(row<0 || row >=pGridData->rows)
{
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
if(bAdd0Col)
{
rtRow.left = 0;
}
else
{
rtRow.left = pGridData->columnwidths[0];
}
rtRow.right = pGridData->gridWidth;
offset = pGridData->titleheight;
if(row == 0)
{
rtRow.top = offset;
rtRow.bottom = pGridData->titleheight+ pGridData->headerrowheight;
}
else
{
if(pGridData->topvisiblerow<1 || pGridData->bottomvisiblerow<1)
{
//(当前没有显示的数据单元)
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
if(row < pGridData->topvisiblerow || row > pGridData->bottomvisiblerow)
{
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
offset += pGridData->headerrowheight;
for(j=pGridData->topvisiblerow;j<row;j++)
{
offset += pGridData->rowheight;
}
rtRow.top = offset;
rtRow.bottom = offset+pGridData->rowheight;
}
SetRect(&rtGrid,0,0,pGridData->gridWidth,pGridData->gridHeight);
if(!IntersectRect(pCellRect,&rtRow,&rtGrid))
{
//两个矩形没有交集
SetRect(pCellRect,0,0,0,0);
return FALSE;
}
RR_ASSERT(!IsRectEmpty(pCellRect));
return TRUE;
}
//得到鼠标事件光标所在的行(逻辑行号)
int RR_GridCtrl_GetRowOfMouse(Grid_T * pGridData,int y)
{
int row;
int top=0;
RR_ASSERT(pGridData!=NULL);
if(y<0 || y>pGridData->gridHeight)
{
return -1;
}
if(pGridData->titleheight>0 && y< pGridData->titleheight )
{
return -1;
}
top = pGridData->titleheight;
if(pGridData->headerrowheight >0 && (y>=top) &&
(y<(pGridData->headerrowheight + top)))
{
return 0;
}
if(pGridData->topvisiblerow<=0)
{
return -1;
}
top+=pGridData->headerrowheight ;
y-=top;
row = y/pGridData->rowheight;
row+=pGridData->topvisiblerow;
if(row>pGridData->bottomvisiblerow)
{
return -1;
}
return row;
}
//得到鼠标事件光标所在的列(逻辑列号)
//x 是相对于Grid 窗口的坐标
int RR_GridCtrl_GetColOfMouse(Grid_T * pGridData,int x)
{
int col=0;
int left=0;
int right=0;
RR_ASSERT(pGridData!=NULL);
if(x<0 || x>pGridData->gridWidth)
{
//x坐标在Grid窗口之外
return -1;
}
if(pGridData->columnwidths[0]>0)
{
//第0列有宽度
int border;
border = pGridData->columnwidths[0];
if(RR_GetExtendLastColumnStyle(pGridData->hWnd) &&
RR_GridCtrl_GetNextNthColWithWidth(pGridData,0,1)<0)
{
//第0列是最后一列且被扩展
border = pGridData->gridWidth;
}
if(x<border)
{
return 0;
}
}
if(pGridData->leftvisiblecol<=0)
{
return -1;
}
left = pGridData->columnwidths[0];
col=pGridData->leftvisiblecol;
while(col<pGridData->rightvisiblecol)
{
if(x>=left && x<left+pGridData->columnwidths[col])
{
return col;
}
left+=pGridData->columnwidths[col];
col++;
}
RR_ASSERT(col == pGridData->rightvisiblecol);
if(RR_GetExtendLastColumnStyle(pGridData->hWnd)&&
RR_GridCtrl_GetNextNthColWithWidth(pGridData,col,1)<0 )
{
right = pGridData->gridWidth;
}
else
{
right = left+pGridData->columnwidths[col];
if(right>pGridData->gridWidth)
{
right = pGridData->gridWidth;
}
}
if(x>=left && x<right)
{
return col;
}
else
{
return -1;
}
}
//调整homecol,以使reference_col能显示在屏幕上(如果有宽度)
static void RR_GridCtrl_AdjustHomeCol(HWND hWnd,int reference_col)
{
Grid_T * pGridData;
int home_col=1;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
RR_ASSERT(pGridData->homecol>=0 && pGridData->homecol<pGridData->cols);
if(reference_col<=0 || reference_col>=pGridData->cols)
{
return ;
}
if(reference_col<pGridData->leftvisiblecol)
{
//拖出左边界外的列
home_col = reference_col;
}
else
{
home_col = pGridData->homecol;
}
if(pGridData->columnwidths[home_col]<=0)
{
int col;
col =RR_GridCtrl_GetNextNthColWithWidth(pGridData,home_col,1);
if(col>0)
{
home_col = col;
}
else
{
home_col =RR_GridCtrl_GetNextNthColWithWidth(pGridData,home_col,-1);
if(home_col<1)
{
home_col =1;
}
}
}
if(home_col!=pGridData->homecol)
{
RR_ASSERT(home_col>0 && home_col<pGridData->cols);
pGridData->homecol = home_col;
}
}
//根据滚动条当前位置设置home_col
//而RR_GridCtrl_AdjustHomeCol是先设置home_col 再由home_col去 调整滚动条位置
static void RR_GridCtrl_SetHomeCol(HWND hWnd,int pos)
{
int home_col =0;
int col =0;
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
col =RR_GridCtrl_GetNextNthColWithWidth(pGridData,0,pos);
if(col>0)
{
home_col = col;
}
else
{
col = RR_GridCtrl_GetColumnsWithWidth(pGridData,1,pGridData->cols-1,NULL);
if(col>1)
{
home_col =RR_GridCtrl_GetNextNthColWithWidth(pGridData,0,col);
if(home_col<1)
{
RR_ASSERT(0);
home_col =1;
}
}
else
{
home_col =1;
}
}
if(home_col!=pGridData->homecol)
{
RR_ASSERT(home_col>0 && home_col<pGridData->cols);
pGridData->homecol = home_col;
}
}
static void RR_GridCtrl_InitStruct(Grid_T * pGridData)
{
int i =0;
RR_ASSERT(pGridData!=NULL);
//初始化字体
pGridData->htitlefont = CreateFont(20,0,0, 0,FW_HEAVY,FALSE,FALSE,FALSE,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,VARIABLE_PITCH|FF_MODERN ,NULL);
pGridData->hheadfont = CreateFont(18,0,0, 0,FW_HEAVY,FALSE,FALSE,FALSE,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,VARIABLE_PITCH|FF_MODERN ,NULL);
pGridData->hbodyfont = CreateFont(16,0,0, 0,100,FALSE,FALSE,FALSE,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,VARIABLE_PITCH|FF_MODERN ,NULL);
//初始化颜色值
//pGridData->crTextTitle = RGB(0,0,0);
//栅格线颜色
pGridData->crGridLine =RGB(220,220,220);
//画刷颜色
pGridData->crBrushReadOnly =RGB(252,252,248);//RGB(252,248,251); //RGB(247,253,253);
pGridData->crBrushCommon = RGB(255,255,255);
pGridData->crBrushLight =RGB(0,80,226);//RGB(0,80,226);RGB(49,106,197);
pGridData->crBrushGray = RGB(124,153,226);
pGridData->crTextReadOnly = RGB(166,166,166);
//pGridData->crTextCommon= RGB(0,0,0);
pGridData->crTextLight =RGB(255,255,255);
pGridData->crTextGray = RGB(216,228,248);
pGridData->hEditBackBrush = CreateSolidBrush(pGridData->crBrushCommon);
pGridData->homerow = 1;
pGridData->homecol = 1;
pGridData->sel_row = 1;
pGridData->tEditCell.row =-1;
pGridData->tEditCell.col =-1;
pGridData->cursortype = CURSOR_ARROW;
pGridData->headerrowheight = 18+LINE_BORDER_SIZE;
pGridData->rowheight = 16+LINE_BORDER_SIZE;
pGridData->columnwidths[0] = 50;
for(i=1;i<pGridData->cols;i++)
{
pGridData->columnwidths[i]=50;
}
pGridData->ptTextLink = (StringLink_T*)RR_MALLOC(sizeof(StringLink_T));
RR_InitStringLink(pGridData->ptTextLink);
}
static void RR_GridCtrl_ResumeDefaultStruct(Grid_T * pGridData)
{
int i=0;
if(pGridData == NULL)
{
RR_ASSERT(0);
}
pGridData->rows = pGridData->init_rows;
pGridData->cols = pGridData->init_cols;
pGridData->dwStyle = pGridData->dwStyle;
pGridData->homerow =1;
pGridData->homecol = 1;
pGridData->sel_row =1;
if(pGridData->dwStyle & GS_NO_COLHEAD)
{
pGridData->headerrowheight =0;
}
else
{
pGridData->headerrowheight = 18+LINE_BORDER_SIZE;
}
pGridData->rowheight = 16+LINE_BORDER_SIZE;
memset(pGridData->columnwidths,0,sizeof(pGridData->columnwidths));
if(!(pGridData->dwStyle & GS_NO_ROWHEAD))
{
pGridData->columnwidths[0] = 50;
}
for(i=1;i<pGridData->cols;i++)
{
pGridData->columnwidths[i]=50;
}
//栅格线颜色
pGridData->crGridLine =RGB(220,220,220);
//画刷颜色
pGridData->crBrushReadOnly =RGB(252,252,248);//RGB(252,248,251); //RGB(247,253,253);
pGridData->crBrushCommon = RGB(255,255,255);
pGridData->crBrushLight =RGB(0,80,226);//RGB(0,80,226);RGB(49,106,197);
pGridData->crBrushGray = RGB(124,153,226);
pGridData->crTextReadOnly = RGB(166,166,166);
//pGridData->crTextCommon= RGB(0,0,0);
pGridData->crTextLight =RGB(255,255,255);
pGridData->crTextGray = RGB(216,228,248);
if(pGridData->hEditBackBrush!=NULL)
{
DeleteObject(pGridData->hEditBackBrush);
}
pGridData->hEditBackBrush = CreateSolidBrush(pGridData->crBrushCommon);
}
static void RR_GridCtrl_FreeStruct(Grid_T * pGridData)
{
if(pGridData->htitlefont!=NULL)
{
DeleteObject(pGridData->htitlefont);
}
if(pGridData->hheadfont!=NULL)
{
DeleteObject(pGridData->hheadfont);
}
if(pGridData->hbodyfont!=NULL)
{
DeleteObject(pGridData->hbodyfont);
}
if(pGridData->hEditBackBrush!=NULL)
{
DeleteObject(pGridData->hEditBackBrush);
}
RRFreeStringLink(pGridData->ptTextLink);
RR_Safe_Free(pGridData->ptTextLink);
RR_Safe_Free(pGridData->pszTitle);
RR_Safe_Free(pGridData);
}
//设置标题条的显示位置
static void RR_GridCtrl_SetTitleBarArea(HWND hWnd)
{
HDC dc;
HFONT hOldFont;
SIZE size;
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->pszTitle == NULL ||pGridData->pszTitle[0] == 0)
{
pGridData->titleheight=0;
return;
}
dc=GetDC(hWnd);
//dc = CreateDC("DISPLAY", NULL, NULL, NULL );
hOldFont=(HFONT)SelectObject(dc,pGridData->htitlefont);
GetTextExtentPoint32(dc,pGridData->pszTitle,strlen(pGridData->pszTitle),&size);
SelectObject(dc,hOldFont);
pGridData->titleheight = (int)(size.cy * RR_Get_Sector_Count(pGridData->pszTitle,'/n')+LINE_BORDER_SIZE);
ReleaseDC(hWnd,dc);
//DeleteDC( dc );
}
static void RR_GridCtrl_ShowHscroll(HWND hWnd)
{
Grid_T * pGridData;
int totalpixels=0;
int colswithwidth=0;//有宽度的列数(除第0列外)
int max=0;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL && pGridData->cols>0);
colswithwidth = RR_GridCtrl_GetColumnsWithWidth(pGridData,1,pGridData->cols-1,&totalpixels);
if(pGridData->columnwidths[0]>0 )
{
totalpixels += pGridData->columnwidths[0];
}
if(totalpixels > pGridData->gridWidth)
{
if(!pGridData->bShowHScroll )
{
//show hscrollbar
ShowScrollBar(hWnd,SB_HORZ,TRUE);
}
RR_ASSERT(colswithwidth<pGridData->cols);
SetScrollRange(hWnd,SB_HORZ,1,colswithwidth,TRUE);
max = colswithwidth;
colswithwidth = RR_GridCtrl_GetColumnsWithWidth(pGridData,1,pGridData->homecol,NULL);
if(colswithwidth<1)
{
colswithwidth =1;
}
else if (colswithwidth>max)
{
RR_GridCtrl_SetHomeCol(hWnd,colswithwidth);
colswithwidth =max;
}
SetScrollPos(hWnd,SB_HORZ,colswithwidth,TRUE);
pGridData->bShowHScroll = TRUE;
}
else
{
pGridData->homecol =RR_GridCtrl_GetNextNthColWithWidth(pGridData,0,1);
if(pGridData->homecol<1)
{
pGridData->homecol =1;
}
if(pGridData->bShowHScroll)
{
//hide hscrollbar
ShowScrollBar(hWnd,SB_HORZ,FALSE);
}
SetScrollRange(hWnd,SB_HORZ,0,0,TRUE);
pGridData->bShowHScroll = FALSE;
}
}
void RR_GridCtrl_ShowVscroll(HWND hWnd)
{
Grid_T * pGridData;
int totalpixels;
int max=0;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
totalpixels = pGridData->titleheight+pGridData->headerrowheight+((pGridData->rowheight) * (pGridData->rows-1)); //-1 :除去第0行计数
if(totalpixels> pGridData->gridHeight)
{
int rows_onscreen;//屏幕上能显示的行数(不包括第0行)
int pos ;
if(!pGridData->bShowVScroll)
{
//显示纵向滚动条
ShowScrollBar(hWnd,SB_VERT,TRUE);
}
totalpixels = pGridData->gridHeight - (pGridData->headerrowheight+pGridData->titleheight);
rows_onscreen = totalpixels / (pGridData->rowheight);
max = (pGridData->rows-1-rows_onscreen)+1;
SetScrollRange(hWnd,SB_VERT,1,max,TRUE);
if(pGridData->homerow<1)
{
RR_ASSERT(0);
pos =1;
}
else if (pGridData->homerow<=max)
{
pos = pGridData->homerow;
}
else
{
pGridData->homerow = max; //调整homerow
pos = max;
}
SetScrollPos(hWnd,SB_VERT,pos,TRUE);
pGridData->bShowVScroll = TRUE;
}
else
{
pGridData->homerow =1;
if(pGridData->bShowVScroll)
{
//隐藏纵向滚动条
ShowScrollBar(hWnd,SB_VERT,FALSE);
}
SetScrollRange(hWnd,SB_VERT,0,0,TRUE);
pGridData->bShowVScroll = FALSE;
}
}
void RR_GridCtrl_Refresh(HWND hWnd,BOOL bUpdate)
{
RECT rect;
Grid_T * pGridData;
//窗口是隐藏状态,无需刷新
if(!(GetWindowLong(hWnd,GWL_STYLE)& WS_VISIBLE))
{
if(bUpdate)
{
UpdateWindow(hWnd);
}
return;
}
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
SetRect(&rect,0,0,pGridData->gridWidth,pGridData->gridHeight);
InvalidateRect(hWnd,&rect,FALSE);
if(bUpdate)
{
UpdateWindow(hWnd);
}
}
static void RR_GridCtrl_Resize(HWND hWnd)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
SendMessage(hWnd,WM_SIZE,SIZE_MAXIMIZED,MAKELPARAM(pGridData->gridWidth,pGridData->gridHeight));
}
static void RR_GridCtrl_SetFocus(HWND hWnd, BOOL bUpdate)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(RR_GetReadOnlyStyle(hWnd))
{
if(bUpdate)
{
RR_GridCtrl_Refresh(hWnd,FALSE);
}
return;
}
if(GetFocus()!=hWnd)
{
SetFocus(hWnd);
}
if(bUpdate)
{
RR_GridCtrl_Refresh(hWnd,FALSE);
}
}
static void RR_GridCtrl_CalcVisibleCellBoundaries(Grid_T * pGridData)
{
int j;
int height=0;
RR_ASSERT(pGridData!=NULL);
//calc columns visible
if(pGridData->homecol<=0||pGridData->homecol >= pGridData->cols ||
pGridData->columnwidths[0]>=pGridData->gridWidth)
{
pGridData->rightvisiblecol = pGridData->leftvisiblecol = 0;
}
else
{
if(pGridData->columnwidths[pGridData->homecol] >0)
{
pGridData->leftvisiblecol = pGridData->homecol;
}
else
{
pGridData->leftvisiblecol = RR_GridCtrl_GetNextNthColWithWidth(pGridData,pGridData->homecol,1);
if(pGridData->leftvisiblecol <0)
{
pGridData->leftvisiblecol =0;
}
}
pGridData->rightvisiblecol = RR_GridCtrl_GetLogicColOnScreen(pGridData,pGridData->homecol,RR_PARAM_START_COLNO|RR_RESULT_HALF);
if(pGridData->rightvisiblecol <0)
{
RR_ASSERT(0);
pGridData->rightvisiblecol = pGridData->leftvisiblecol ;
}
if(pGridData->columnwidths[pGridData->rightvisiblecol] <=0)
{
pGridData->rightvisiblecol = RR_GridCtrl_GetNextNthColWithWidth(pGridData,pGridData->rightvisiblecol,-1);
if(pGridData->rightvisiblecol <0)
{
pGridData->rightvisiblecol =pGridData->leftvisiblecol;
}
}
}
//calc rows visible;
height = pGridData->titleheight+pGridData->headerrowheight;
if(pGridData->homerow<=0 ||pGridData->homerow>=pGridData->rows ||
height>=pGridData->gridHeight )
{
pGridData->bottomvisiblerow=pGridData->topvisiblerow = 0;
}
else
{
j=pGridData->homerow;
pGridData->topvisiblerow = pGridData->homerow;
j+=(pGridData->gridHeight-height)/pGridData->rowheight -1;
if(j>=pGridData->rows)
{
j=pGridData->rows-1;
}
pGridData->bottomvisiblerow = (j>pGridData->topvisiblerow)?j:pGridData->topvisiblerow;
}
}
static void RR_GridCtrl_DisplayTitle(HWND hWnd,HDC hdc)
{
Grid_T * pGridData = NULL;
RECT rect;
HFONT hOldFont;
COLORREF crOldColor;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->pszTitle[0]==0)
{
return;
}
SetRect(&rect,0,0,pGridData->gridWidth+1,pGridData->gridHeight+1);
rect.bottom = pGridData->titleheight;
SetBkMode(hdc,TRANSPARENT);
hOldFont=(HFONT)SelectObject(hdc,pGridData->htitlefont);
crOldColor = SetTextColor(hdc,pGridData->crTextTitle);
//画矩形边框(EDGE_ETCHED: 突起内缘,凹下的外缘)
DrawEdge(hdc,&rect,EDGE_ETCHED,BF_MIDDLE|BF_RECT|BF_ADJUST);
DrawTextEx(hdc,pGridData->pszTitle,-1,&rect,/*DT_WORD_ELLIPSIS|*/DT_END_ELLIPSIS|DT_CENTER|DT_WORDBREAK|DT_NOPREFIX,NULL);
SelectObject(hdc,hOldFont);
SetTextColor(hdc,crOldColor);
}
//画空白区域矩形
static void RR_GridCtrl_DrawBlank(HDC hdc,RECT *pRect)
{
HBRUSH holdbrush;
HPEN holdpen;
RR_ASSERT(pRect!=NULL);
holdbrush=(HBRUSH)SelectObject(hdc,GetStockObject(LTGRAY_BRUSH));
holdpen=(HPEN)SelectObject(hdc,GetStockObject(NULL_PEN));
Rectangle(hdc,pRect->left,pRect->top,pRect->right,pRect->bottom);
SelectObject(hdc,holdbrush);
SelectObject(hdc,holdpen);
}
//返回值标识当前
static void RR_GridCtrl_DrawCell(HWND hWnd,HDC hdc,GridCell_T *pGridCell,const RECT *pCellRect)
{
Grid_T*pGridData;
COLORREF crBrushColor;
COLORREF crText;
HBRUSH hbrush=NULL;
HPEN hpen;
HPEN holdpen;
HBRUSH holdbrush;
RECT rtCell;
char szText[CELL_TEXT_MAX+1]={0};
RR_ASSERT(pGridCell!=NULL && pCellRect!=NULL);
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
CopyRect(&rtCell,pCellRect);
if(RR_GetReadOnlyStyle(hWnd))
{
crBrushColor = pGridData->crBrushReadOnly;
crText = pGridData->crTextReadOnly;
}
else
{
crBrushColor = pGridData->crBrushCommon;
crText = pGridData->crTextCommon;
}
if(!pGridData->bEditing && pGridCell->row >0 &&
pGridCell->row == pGridData->sel_row)
{
//是选择行
if(RR_GetHighLightStyle(hWnd))
{
if(pGridData->bGridHasFocus )
{
crBrushColor =pGridData->crBrushLight;
crText = pGridData->crTextLight;
}
else
{
crBrushColor =pGridData->crBrushGray;
crText = pGridData->crTextGray;
}
}
}
hbrush = CreateSolidBrush(crBrushColor);
hpen=CreatePen(PS_SOLID,1,pGridData->crGridLine);
holdbrush=(HBRUSH)SelectObject(hdc,hbrush);
holdpen=(HPEN)SelectObject(hdc,hpen);
Rectangle(hdc,rtCell.left,rtCell.top,rtCell.right,rtCell.bottom);
SelectObject(hdc,holdbrush);
SelectObject(hdc,holdpen);
DeleteObject(hbrush);
DeleteObject(hpen);
SetTextColor(hdc,crText);
rtCell.right -= 2;
rtCell.left += 2;
if(!pGridData->bEditing ||
!RR_GridCtrl_CmpCell(&pGridData->tEditCell,pGridCell))
{
RR_GridCtrl_GetCellText(hWnd, pGridCell->row,pGridCell->col,szText, sizeof(szText));
}
//文本在单元格里显示不下用省略号
DrawTextEx(hdc,szText,-1,&rtCell,DT_END_ELLIPSIS|DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX,NULL);
}
//显示第0列
static void RR_GridCtrl_Display0Column(HWND hWnd,HDC hdc)
{
Grid_T*pGridData;
COLORREF crOldColor;
RECT rectGrid;
RECT rtCell;
RECT rtTmp;
HFONT hOldFont;
char szText[CELL_TEXT_MAX+1]={0};
int row=0;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
SetRect(&rectGrid,0,0,pGridData->gridWidth,pGridData->gridHeight);
if(pGridData->cols<=0||pGridData->columnwidths[0]<=0 ||
pGridData->gridWidth<=0 || pGridData->gridHeight<=0)
{
return;
}
SetBkMode(hdc,TRANSPARENT);
crOldColor = SetTextColor(hdc,pGridData->crTextTitle);
//显示第0行(header row)
hOldFont = (HFONT)SelectObject(hdc,pGridData->hheadfont);
SetRect(&rtCell,0,pGridData->titleheight,pGridData->columnwidths[0],pGridData->titleheight+pGridData->headerrowheight);
if(RR_GridCtrl_GetNextNthColWithWidth(pGridData,0,1)<0)
{
//是最右边一列
if(RR_GetExtendLastColumnStyle(hWnd))
{
//extend this column
if(rtCell.right<rectGrid.right)
{
rtCell.right = rectGrid.right;
}
}
else
{
if(rtCell.right<rectGrid.right)
{
//repaint right side of grid
SetRect(&rtTmp,rtCell.right,pGridData->titleheight,rectGrid.right+1,rectGrid.bottom+1);
RR_GridCtrl_DrawBlank(hdc,&rtTmp);
}
}
}
if(rtCell.top<rtCell.bottom)
{
CopyRect(&rtTmp,&rtCell);
DrawEdge(hdc,&rtTmp,EDGE_ETCHED,BF_MIDDLE|BF_RECT|BF_ADJUST);
}
row=pGridData->topvisiblerow;
if(row>0 && row<pGridData->rows &&
(pGridData->bottomvisiblerow < pGridData->rows))
{
SelectObject(hdc,pGridData->hbodyfont);
while(row<=pGridData->bottomvisiblerow)
{
rtCell.top = rtCell.bottom;
rtCell.bottom = rtCell.top + pGridData->rowheight;
CopyRect(&rtTmp,&rtCell);
DrawEdge(hdc,&rtTmp,EDGE_ETCHED,BF_MIDDLE|BF_RECT|BF_ADJUST);
if(RR_GetRowHeadIsNumberStyle(hWnd))
{
sprintf(szText,"%d",row);
RR_ASSERT(strlen(szText)<sizeof(szText));
DrawTextEx(hdc,szText,-1,&rtTmp,DT_END_ELLIPSIS|DT_RIGHT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX,NULL);
}
else
{
RR_GridCtrl_GetCellText(hWnd, row,0,szText, sizeof(szText));
DrawTextEx(hdc,szText,-1,&rtTmp,DT_END_ELLIPSIS|DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX,NULL);
}
row++;
}
}
SetRect(&rtTmp,rtCell.left,rtCell.bottom,rtCell.right+1,rectGrid.bottom+1);
RR_GridCtrl_DrawBlank(hdc,&rtTmp);
SelectObject(hdc,hOldFont);
SetTextColor(hdc,crOldColor);
}
//显示除第0列外的列
static void RR_GridCtrl_DisplayColumn(HWND hWnd,HDC hdc,int col,int offset)
{
Grid_T*pGridData;
HFONT hOldFont;
RECT rtCell;
RECT rtTmp;
RECT rectGrid;
int row=0;
char szText[CELL_TEXT_MAX+1]={0};
COLORREF crOldColor;
GridCell_T GridCell;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
SetRect(&rectGrid,0,0,pGridData->gridWidth,pGridData->gridHeight);
if(col<=0||col >=pGridData->cols || offset>=pGridData->gridWidth ||
pGridData->columnwidths[col]<=0)
{
return;
}
SetBkMode(hdc,TRANSPARENT);
crOldColor = SetTextColor(hdc,pGridData->crTextTitle);
//显示第0行( header row)
hOldFont = (HFONT)SelectObject(hdc,pGridData->hheadfont);
SetRect(&rtCell,offset,pGridData->titleheight,offset+pGridData->columnwidths[col],pGridData->titleheight +pGridData->headerrowheight);
if(RR_GridCtrl_GetNextNthColWithWidth(pGridData,col,1)<0)
{
//当前列是最右边一列
if(RR_GetExtendLastColumnStyle(hWnd))
{
//extend this column
if(rtCell.right<rectGrid.right)
{
rtCell.right = rectGrid.right;
}
}
else
{
if(rtCell.right<rectGrid.right)
{
//repaint right side of grid
SetRect(&rtTmp,rtCell.right,pGridData->titleheight,rectGrid.right+1,rectGrid.bottom+1);
RR_GridCtrl_DrawBlank(hdc,&rtTmp);
}
}
}
szText[0] =0;
if(RR_GetColHeadIsNumberStyle(hWnd))
{
int high,low;
high = ((col-1)/26);
low = col % 26;
if(high == 0)
{
high = 32;
}
else
{
high+=64;
}
if(low==0)
{
low = 90;
}
else
{
low += 64;
}
if(((high>64 && high<91)||high ==32) && low>64 && low<91)
{
sprintf(szText,"%c%c",high,low);
RR_ASSERT(strlen(szText)<sizeof(szText));
}
}
else
{
RR_GridCtrl_GetCellText(hWnd, 0,col,szText, sizeof(szText));
}
if(rtCell.top<rtCell.bottom)
{
CopyRect(&rtTmp,&rtCell);
DrawEdge(hdc,&rtTmp,EDGE_ETCHED,BF_MIDDLE|BF_RECT|BF_ADJUST);
DrawTextEx(hdc,szText,-1,&rtTmp,DT_END_ELLIPSIS|DT_CENTER|DT_VCENTER|DT_WORDBREAK|DT_SINGLELINE|DT_NOPREFIX,NULL);
}
//显示第0行外的行
row=pGridData->topvisiblerow;
if(row>0 && row<pGridData->rows &&
(pGridData->bottomvisiblerow < pGridData->rows))
{
SelectObject(hdc,pGridData->hbodyfont);
while(row<=pGridData->bottomvisiblerow)
{
rtCell.top = rtCell.bottom;
rtCell.bottom = rtCell.top + pGridData->rowheight;
RR_GridCtrl_SetCell(&GridCell,row,col);
RR_GridCtrl_DrawCell(hWnd,hdc,&GridCell,&rtCell);
row++;
}
}
SetRect(&rtTmp,rtCell.left,rtCell.bottom,rtCell.right+1,rectGrid.bottom+1);
RR_GridCtrl_DrawBlank(hdc,&rtTmp);
SelectObject(hdc,hOldFont);
SetTextColor(hdc,crOldColor);
}
static void RR_GridCtrl_DisplayCellEditBox(HWND hWnd)
{
Grid_T*pGridData;
RECT rtCell;
RECT rtEdit;
char szText[CELL_TEXT_MAX+1];
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(!RR_GridCtrl_GetCellRect(hWnd,pGridData->tEditCell.row,pGridData->tEditCell.col,&rtCell))
{
SetRect(&rtCell,0,0,0,0);
}
InflateRect(&rtCell, -1, -1);
if(IsRectEmpty(&rtCell))
{
ShowWindow(pGridData->hChildEdit,SW_HIDE);
return ;
}
GetWindowRect(pGridData->hChildEdit,&rtEdit);
RR_ScreenRectToClient(hWnd,&rtEdit);
if(EqualRect(&rtCell,&rtEdit))
{
return;
}
//不相等,需要调整
MoveWindow(pGridData->hChildEdit,rtCell.left,rtCell.top,
RR_RECT_WIDTH(rtCell),RR_RECT_HEIGHT(rtCell),FALSE);
GetWindowText(pGridData->hChildEdit,szText,sizeof(szText));
if(szText[0]!=0)
{
int start=0;
int end=0;
//编辑框在列宽变化过程中文本自动适应
SendMessage(pGridData->hChildEdit,EM_GETSEL,(WPARAM)&start,(LPARAM)&end);
SetWindowText(pGridData->hChildEdit,szText);
SendMessage(pGridData->hChildEdit,EM_SETSEL,start,end);
}
ShowWindow(pGridData->hChildEdit,SW_SHOW);
}
static BOOL RR_GridCtrl_Discard_Edit(HWND hWnd)
{
Grid_T*pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(!pGridData->bEditing)
{
//当前不是编辑状态
return TRUE;
}
pGridData->tEditCell.row = -1;
pGridData->tEditCell.col =-1;
pGridData->bEditing = FALSE;
if((GetWindowLong(pGridData->hChildEdit,GWL_STYLE)& WS_VISIBLE))
{
ShowWindow(pGridData->hChildEdit,SW_HIDE);
//隐藏会让编辑框失去焦点,在失去焦点会调用RR_GridCtrl_Exit_Edit
}
SetWindowText(pGridData->hChildEdit,"");
SendMessage(pGridData->hChildEdit,EM_SETMODIFY,FALSE,0);
return TRUE;
}
static BOOL RR_GridCtrl_Exit_Edit(HWND hWnd)
{
Grid_T*pGridData;
char szText[CELL_TEXT_MAX+1]={0};
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(!pGridData->bEditing)
{
//当前不是编辑状态
return TRUE;
}
RR_ASSERT(pGridData->tEditCell.row >0 && pGridData->tEditCell.col>0);
if(RR_GridCtrl_Notify(hWnd,GN_EXIT_CELL_EDITBOX, MAKELPARAM(pGridData->tEditCell.row,pGridData->tEditCell.col )))
{
//父窗口通知响应不让退出编辑
return FALSE;
}
pGridData->bCellModified = SendMessage(pGridData->hChildEdit,EM_GETMODIFY,0,0);
if(pGridData->bCellModified)
{
if(!pGridData->bRowModified)
{
pGridData->bRowModified = TRUE;
}
if (!pGridData->bGridTextModified)
{
pGridData->bGridTextModified = TRUE;
}
}
pGridData->bEditing = FALSE;
//RR_GridCtrl_SetCellText不能放在只读标识获取之前
//RR_GridCtrl_SetCellText不能放在pGridData->bEditing置FALSE之前
GetWindowText(pGridData->hChildEdit,szText,sizeof(szText));
RR_GridCtrl_SetCellText(hWnd,pGridData->tEditCell.row,pGridData->tEditCell.col,szText);
if((GetWindowLong(pGridData->hChildEdit,GWL_STYLE)& WS_VISIBLE))
{
ShowWindow(pGridData->hChildEdit,SW_HIDE);
//隐藏会让编辑框失去焦点,在失去
//焦点会再次调用RR_GridCtrl_Exit_Edit
}
SetWindowText(pGridData->hChildEdit,"");
SendMessage(pGridData->hChildEdit,EM_SETMODIFY,FALSE,0);
if(pGridData->tEditCell.row!=-1 && pGridData->tEditCell.col!=-1)
{
RR_GridCtrl_Notify(hWnd,GN_AFTER_EXIT_CELL_EDITBOX, MAKELPARAM(pGridData->tEditCell.row,pGridData->tEditCell.col ));
}
pGridData->tEditCell.row = -1;
pGridData->tEditCell.col =-1;
return TRUE;
}
//强制性退出编辑,如果父窗口响应不让退出编辑,
//则将本次编辑的数据丢失
static BOOL RR_GridCtrl_Force_Exit_Edit(HWND hWnd)
{
BOOL bRet = TRUE;
Grid_T*pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(!pGridData->bEditing)
{
//当前不是编辑状态
return TRUE;
}
if(!RR_GridCtrl_Exit_Edit(hWnd))
{
RR_GridCtrl_Discard_Edit(hWnd);
bRet = FALSE;
}
return bRet;
}
//iSetSel 进入编辑框时设置光标位置 0 -- 光标在文本末
// 1-- 选中所有文本
static BOOL RR_GridCtrl_Enter_Edit(HWND hWnd,GridCell_T*ptCell,int iSetSel)
{
Grid_T*pGridData;
RECT rectCell;
char szText[CELL_TEXT_MAX+1];
int len=0;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(ptCell==NULL || ptCell->row<1 ||ptCell->row > pGridData->rows-1||
ptCell->col<1 || ptCell->col > pGridData->cols-1 ||RR_GetReadOnlyStyle(hWnd))
{
return FALSE;
}
if(!RR_GridCtrl_GetCellRect(hWnd,ptCell->row,ptCell->col,&rectCell))
{
return FALSE;
}
InflateRect(&rectCell, -1, -1);
if(IsRectEmpty(&rectCell))
{
return FALSE;
}
if(pGridData->bEditing)
{
//正在编辑
RR_ASSERT(pGridData->tEditCell.row >0 && pGridData->tEditCell.col >0);
//确认原来确实有有效的编辑单元
if(pGridData->tEditCell.row==ptCell->row &&
pGridData->tEditCell.col ==ptCell->col)
{
//已在编辑
return TRUE;
}
else
{
//退出原来的编辑单元
if(!RR_GridCtrl_Exit_Edit(hWnd))
{
//父窗口退出编辑通知响应不让退出
return FALSE;
}
}
}
if(RR_GridCtrl_ChgSelRow(hWnd,ptCell->row))
{
//选择行不让改变
return FALSE;
}
RR_GridCtrl_GetCellText(hWnd,ptCell->row,ptCell->col,szText,sizeof(szText));
SetWindowText(pGridData->hChildEdit,szText);
SendMessage(pGridData->hChildEdit,EM_SETMODIFY,FALSE,0);
pGridData->bCellModified = FALSE;
pGridData->bEditing = TRUE;
pGridData->tEditCell.row = ptCell->row;
pGridData->tEditCell.col = ptCell->col;
//SendMessage(pGridData->hChildEdit, WM_SETFONT, (WPARAM) pGridData->hbodyfont, FALSE);
MoveWindow(pGridData->hChildEdit,rectCell.left,rectCell.top,
RR_RECT_WIDTH(rectCell),RR_RECT_HEIGHT(rectCell),FALSE);
ShowWindow(pGridData->hChildEdit,SW_SHOW);
SetFocus(pGridData->hChildEdit);
len = strlen(szText);
if(iSetSel == 0) //光标在文本末
{
SendMessage(pGridData->hChildEdit,EM_SETSEL,len+1,len+1);
}
else if (iSetSel == 1)//所有文本被选中
{
SendMessage(pGridData->hChildEdit,EM_SETSEL,0,len+1);
}
RR_GridCtrl_Notify(hWnd,GN_ENTRY_CELL_EDITBOX,MAKELPARAM(ptCell->row,ptCell->col));
return TRUE;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
static LRESULT RR_GridCtrlOnSetText(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
char *pszTitle = (char*)lParam;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
RR_Safe_Free(pGridData->pszTitle);
if(pszTitle!=NULL)
{
pGridData->pszTitle = (char*)RR_MALLOC(strlen(pszTitle)+1);
strcpy(pGridData->pszTitle,pszTitle);
}
else
{
pGridData->pszTitle = (char*)RR_MALLOC(1);
}
RR_GridCtrl_SetTitleBarArea(hWnd);
RR_GridCtrl_Resize(hWnd);
return 0;
}
static LRESULT RR_GridCtrlOnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
LPCREATESTRUCT lpcs;
lpcs = (LPCREATESTRUCT)lParam;
RR_ASSERT(lpcs->lpCreateParams!=NULL);
pGridData = (Grid_T * )lpcs->lpCreateParams;
pGridData->hWnd =hWnd;
SetWindowLong(hWnd,GWL_USERDATA,(LONG)pGridData);
pGridData->hChildEdit =CreateWindowEx(0/*WS_EX_TRANSPARENT*/,"EDIT","",
WS_CHILD|ES_AUTOHSCROLL|ES_LEFT/*|WS_BORDER*/,0,0,0,0,hWnd,NULL,lpcs->hInstance,NULL);
RR_ASSERT(pGridData->hChildEdit!=NULL);
OriginalEditProc=(CELLEDIT_PROC_T)GetWindowLong(pGridData->hChildEdit ,GWL_WNDPROC);
SetWindowLong(pGridData->hChildEdit,GWL_WNDPROC,(long)ModifierCellEditProc);
SendMessage(pGridData->hChildEdit,EM_LIMITTEXT,CELL_TEXT_MAX,0);
SendMessage(pGridData->hChildEdit, WM_SETFONT, (WPARAM) pGridData->hbodyfont, FALSE);
RR_GridCtrl_SetTitleBarArea(hWnd);
return 0;
}
static LRESULT RR_GridCtrlOnSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
int gridWidth = LOWORD(lParam);
int gridHeight = HIWORD(lParam);
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(gridWidth == 0 || gridHeight==0)
{
return 0;
}
pGridData->gridWidth = gridWidth;
pGridData->gridHeight = gridHeight;
if(pGridData->bSizing)
{
return 0;
}
pGridData->bSizing= TRUE;
RR_GridCtrl_ShowHscroll(hWnd);
RR_GridCtrl_ShowVscroll(hWnd);
gridWidth = pGridData->gridWidth;
gridHeight = pGridData->gridHeight;
//微调Grid大小,让其刚刚好放下完整的行
if(RR_GetShowIntegralRowStyle(hWnd) && (pGridData->bShowVScroll))
{
int height = gridHeight;
//int width=gridWidth;
//int nrows;
int remainder=0;
height-=pGridData->titleheight + pGridData->headerrowheight;
if(height <= pGridData->rowheight)
{
return 0;
}
//nrows=(int)((height)/pGridData->rowheight);//可以放下多少行
//remainder=(height)-(nrows * pGridData->rowheight);
remainder = height%(pGridData->rowheight);
//if(remainder>0)
{
int adjust_height=0;
int rect_bottom =0;
RECT rect;
GetWindowRect(hWnd,&rect);
RR_ScreenRectToClient(GetParent(hWnd), &rect);
rect_bottom = rect.bottom;
height = remainder+pGridData->adjust_height;
adjust_height = height %(pGridData->rowheight);
if(height - adjust_height>0)
{
RR_ASSERT((height - adjust_height )> adjust_height &&
(height - adjust_height )> remainder);
rect.bottom+=(height - adjust_height)-remainder;
pGridData->adjust_height= adjust_height;
}
else
{
RR_ASSERT(height - adjust_height ==0);
rect.bottom-= remainder;
pGridData->adjust_height+=remainder;
}
if(rect_bottom!=rect.bottom)
{
MoveWindow(hWnd,rect.left,rect.top,RR_RECT_WIDTH(rect),RR_RECT_HEIGHT(rect),TRUE);
RR_GridCtrl_ShowVscroll(hWnd);
}
}
}
pGridData->bSizing= FALSE;
RR_GridCtrl_Refresh(hWnd,FALSE);
return 0;
}
static LRESULT RR_GridCtrlOnPaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
Grid_T * pGridData = NULL;
int col;
int offset=0;
//避免闪烁
HBITMAP hBitmap;
HDC hdcMem;
HGDIOBJ hOldSel ;
RECT rtGrid;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
#ifdef _DEBUG
{
RECT rtGrid;
GetClientRect(hWnd,&rtGrid);
RR_ASSERT(rtGrid.right == pGridData->gridWidth &&
rtGrid.bottom == pGridData->gridHeight);
RR_ASSERT(pGridData->homecol>0 && pGridData->homerow>0);
}
#endif
RR_GridCtrl_CalcVisibleCellBoundaries(pGridData);
RR_ASSERT(pGridData->leftvisiblecol>=0 && pGridData->rightvisiblecol >= pGridData->leftvisiblecol
&&pGridData->rightvisiblecol <pGridData->cols);
hdc = BeginPaint(hWnd, &ps);
//hdc = GetDC(hWnd);
//避免闪烁
hBitmap = CreateCompatibleBitmap(hdc,pGridData->gridWidth,pGridData->gridHeight);
hdcMem = CreateCompatibleDC(hdc);
hOldSel = SelectObject(hdcMem,hBitmap);
SetRect(&rtGrid,0,0,pGridData->gridWidth,pGridData->gridHeight);
FillRect( hdcMem, &rtGrid, (HBRUSH)GetStockObject(GRAY_BRUSH));//用背景色刷一下
//display title
RR_GridCtrl_DisplayTitle(hWnd,hdcMem/*hdc*/);
//display column 0;
if(pGridData->columnwidths[0]>0)
{
RR_GridCtrl_Display0Column(hWnd,hdcMem/*hdc*/);
offset = pGridData->columnwidths[0];
}
col=pGridData->leftvisiblecol;
if(col>0)
{
for(;col<=pGridData->rightvisiblecol;col++)
{
if(pGridData->columnwidths[col]>0 && offset< pGridData->gridWidth)
{
RR_GridCtrl_DisplayColumn(hWnd,hdcMem/*hdc*/,col,offset);
offset+=pGridData->columnwidths[col];
}
}
}
//避免闪烁
BitBlt(hdc,0,0,pGridData->gridWidth,pGridData->gridHeight,hdcMem,0,0,SRCCOPY);
SelectObject(hdcMem,hOldSel);
DeleteObject(hBitmap);
DeleteDC(hdcMem);
EndPaint(hWnd, &ps);
//ValidateRect(hWnd,&rtGrid);
//ReleaseDC(hWnd,hdc);
if(pGridData->bEditing)
{
RR_GridCtrl_DisplayCellEditBox(hWnd);
}
return 0;
}
static int RR_GridCtrl_GetResizeCol(Grid_T * pGridData,int x,int y,int *pRefCol)
{
int row ;
int cur_col=-1;
int left_col=-1;
int right_col=-1;
int resize_col =-1;
RR_ASSERT(pGridData!=NULL);
if(pRefCol!=NULL)
{
*pRefCol = -1;
}
row = RR_GridCtrl_GetRowOfMouse(pGridData,y);
if (row!=0)
{
return -1;
}
cur_col = RR_GridCtrl_GetColOfMouse(pGridData,x);
if(cur_col<0)
{
return -1;
}
else
{
if(pRefCol!=NULL)
{
*pRefCol = cur_col;
}
}
left_col = RR_GridCtrl_GetColOfMouse(pGridData,x-6);
right_col = RR_GridCtrl_GetColOfMouse(pGridData,x+6);
if(left_col!=cur_col)
{
//鼠标在列的左部分
if(right_col!=cur_col)
{
//同时也在右部分
if(RR_GridCtrl_GetNextNthColWithWidth(pGridData,cur_col,1)<0 )
{
//最后一列可见的列(拖下一个)
if(cur_col<pGridData->cols-1 )
{
resize_col = cur_col+1;
}
else
{
resize_col = pGridData->cols-1;
}
return resize_col;
}
}
//鼠标在左部分拖上一个
if(left_col<0)
{
if(pGridData->columnwidths[0]>0)
{
left_col =0;
}
else
{
left_col =1;
}
}
resize_col = cur_col-1;
if(resize_col<left_col)
{
resize_col = left_col;
}
return resize_col;
}
if(right_col!=cur_col)
{
//鼠标在右部分
if(RR_GridCtrl_GetNextNthColWithWidth(pGridData,cur_col,1)<0 )
{
//最后一列可见的列(拖下一个)
if(cur_col<pGridData->cols-1 )
{
resize_col = cur_col+1;
}
else
{
resize_col = pGridData->cols-1;
}
return resize_col;
}
//在右部分拖自己
return cur_col;
}
return resize_col;
}
static LRESULT RR_GridCtrlOnLButtonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
int row;
int x=LOWORD(lParam);
int y = HIWORD(lParam);
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
row = RR_GridCtrl_GetRowOfMouse(pGridData,y);
if (row == 0 && RR_GetColumnAllowResizeStyle(hWnd)&&
pGridData->cursortype == CURSOR_DRAG)
{
int resize_col;
resize_col = RR_GridCtrl_GetResizeCol(pGridData,x,y,NULL);
if(resize_col>=0)
{
SetCapture(hWnd);
if(!pGridData->bColumnSizing)
{
pGridData->bColumnSizing = TRUE;
pGridData->columnInitx=x;
}
pGridData->resizeColumn =resize_col;
pGridData->columnInitSize = pGridData->columnwidths[resize_col];
}
}
else
{
GridCell_T tCell;
tCell.row = row;
tCell.col = RR_GridCtrl_GetColOfMouse(pGridData,x);
if(!RR_GridCtrl_Notify(hWnd,GN_CLICK_CELL, MAKELPARAM(tCell.row,tCell.col )))
{
if(pGridData->bEditing)
{
if(tCell.row >0 && tCell.col >0)
{
if(tCell.row != pGridData->tEditCell.row ||
tCell.col != pGridData->tEditCell.col)
{
//切换到另外的单元编辑
RR_GridCtrl_Enter_Edit(hWnd,&tCell,0);
}
}
else
{
RR_GridCtrl_Exit_Edit(hWnd);
}
}
else
{
//不在编辑中
if(row>0 && row< pGridData->rows )
{
RR_GridCtrl_ChgSelRow(hWnd,row);
}
}
}
}
if(!pGridData->bEditing)
{
//不在编辑中
RR_GridCtrl_SetFocus(hWnd,TRUE);
}
return 0;
}
static LRESULT RR_GridCtrlOnMouseMove(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
int x=LOWORD(lParam);
int y=HIWORD(lParam);
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->bColumnSizing)
{
int add_width; //增减宽度
int new_width;
RECT rect;
if(x<0 || x>pGridData->gridWidth+1 ||
y<0 || y>pGridData->gridHeight+1)
{
return 0;
}
add_width=x-pGridData->columnInitx;
new_width=pGridData->columnInitSize + add_width;
if(new_width<0)
{
new_width=0;
}
else if(new_width>=pGridData->gridWidth)
{
new_width = pGridData->gridWidth-1;
}
if(pGridData->columnwidths[pGridData->resizeColumn] ==new_width)
{
//宽度没有发生变化
return 0;
}
pGridData->columnwidths[pGridData->resizeColumn] = new_width;
if(pGridData->resizeColumn>0)
{
RR_GridCtrl_AdjustHomeCol(hWnd,pGridData->resizeColumn);
}
RR_GridCtrl_ShowHscroll(hWnd);
SetRect(&rect,0,pGridData->titleheight,
pGridData->gridWidth,pGridData->gridHeight);
InvalidateRect(hWnd,&rect,FALSE);
}
else
{
int resize_col;
resize_col = RR_GridCtrl_GetResizeCol(pGridData,x,y,NULL);
if( resize_col>=0 && RR_GetColumnAllowResizeStyle(hWnd))
{
pGridData->cursortype = CURSOR_DRAG;
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
}
else if(pGridData->bEditing)
{
pGridData->cursortype = CURSOR_ARROW;//CURSOR_EDITING;
SetCursor(LoadCursor(NULL,IDC_ARROW ));
}
else
{
pGridData->cursortype = CURSOR_ARROW;
SetCursor(LoadCursor(NULL,IDC_ARROW ));
}
}
return 0;
}
static LRESULT RR_GridCtrlOnLButtonUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->bColumnSizing)
{
pGridData->bColumnSizing = FALSE;
SetCursor(LoadCursor(NULL, IDC_ARROW));
pGridData->cursortype = CURSOR_ARROW;
if(pGridData->columnwidths[pGridData->resizeColumn] !=pGridData->columnInitSize)
{
pGridData->bGridFrameModified= TRUE;
}
}
ReleaseCapture();
return 0;
}
//双击事件之前会有一次Down事件,一次up事件
static LRESULT RR_GridCtrlOnLButtonDblclk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
GridCell_T tCell;
int x=LOWORD(lParam);
int y=HIWORD(lParam);
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
tCell.row= RR_GridCtrl_GetRowOfMouse(pGridData,y);
tCell.col = RR_GridCtrl_GetColOfMouse(pGridData,x);
if(!RR_GridCtrl_Notify(hWnd,GN_DCLICK_CELL,MAKELPARAM(tCell.row,tCell.col )))
{
if(tCell.row >0 && tCell.col >0 && !pGridData->bEditing)
{
RR_GridCtrl_Enter_Edit(hWnd,&tCell,0);
}
else if (pGridData->bEditing)
{
RR_GridCtrl_Exit_Edit(hWnd);
}
}
return 0;
}
static LRESULT RR_GridCtrlOnSetCursor(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//注:鼠标在滚动条上也会收到WM_SETCURSOR消息,
//造成滚动条上会显示双向箭头鼠标光标
/*Grid_T * pGridData = NULL;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
switch(pGridData->cursortype)
{
case CURSOR_DRAG:
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
break;
case CURSOR_ARROW:
SetCursor(LoadCursor(NULL,IDC_ARROW ));
break;
case CURSOR_EDITING:
SetCursor(LoadCursor(NULL,IDC_IBEAM));
break;
default:
break;
}*/
return 0;
}
static LRESULT RR_GridCtrlOnDestroy(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
RR_GridCtrl_FreeStruct(pGridData);
return 0;
}
static LRESULT RR_GridCtrlOnHScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData;
RECT rect;
int old_pos=0;
int cur_pos=0;
int min=0;
int max=0;
int interval=0;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
RR_GridCtrl_SetFocus(hWnd,FALSE);
switch(LOWORD(wParam))
{
case SB_PAGERIGHT:
{
interval = RR_GridCtrl_GetColumnsWithWidth(pGridData,pGridData->leftvisiblecol,pGridData->rightvisiblecol,NULL);
if(interval<2)
{
interval =1;
}
else
{
interval --;
}
old_pos=GetScrollPos(hWnd,SB_HORZ);
cur_pos = old_pos+interval;
GetScrollRange(hWnd,SB_HORZ,&min,&max);
if(cur_pos>max)
{
cur_pos = max;
}
if(cur_pos>old_pos)
{
SetScrollPos(hWnd,SB_HORZ,cur_pos,TRUE);
RR_GridCtrl_SetHomeCol(hWnd,cur_pos);
SetRect(&rect,pGridData->columnwidths[0],pGridData->titleheight,
pGridData->gridWidth,pGridData->gridHeight);
InvalidateRect(hWnd,&rect,FALSE);
}
}
break;
case SB_PAGELEFT:
{
interval = RR_GridCtrl_GetColumnsWithWidth(pGridData,pGridData->leftvisiblecol,pGridData->rightvisiblecol,NULL);
if(interval<2)
{
interval =1;
}
else
{
interval --;
}
old_pos=GetScrollPos(hWnd,SB_HORZ);
cur_pos = old_pos-interval;
GetScrollRange(hWnd,SB_HORZ,&min,&max);
if(cur_pos<min)
{
cur_pos = min;
}
if(cur_pos<old_pos)
{
SetScrollPos(hWnd,SB_HORZ,cur_pos,TRUE);
RR_GridCtrl_SetHomeCol(hWnd,cur_pos);
SetRect(&rect,pGridData->columnwidths[0],pGridData->titleheight,
pGridData->gridWidth,pGridData->gridHeight);
InvalidateRect(hWnd,&rect,FALSE);
}
}
break;
case SB_LINERIGHT:
{
old_pos=GetScrollPos(hWnd,SB_HORZ);
cur_pos = old_pos+1;
GetScrollRange(hWnd,SB_HORZ,&min,&max);
if(cur_pos>max)
{
cur_pos = max;
}
if(cur_pos>old_pos)
{
SetScrollPos(hWnd,SB_HORZ,cur_pos,TRUE);
RR_GridCtrl_SetHomeCol(hWnd,cur_pos);
SetRect(&rect,pGridData->columnwidths[0],pGridData->titleheight,
pGridData->gridWidth,pGridData->gridHeight);
InvalidateRect(hWnd,&rect,FALSE);
}
}
break;
case SB_LINELEFT:
{
old_pos=GetScrollPos(hWnd,SB_HORZ);
cur_pos = old_pos-1;
GetScrollRange(hWnd,SB_HORZ,&min,&max);
if(cur_pos<min)
{
cur_pos = min;
}
if(cur_pos<old_pos)
{
SetScrollPos(hWnd,SB_HORZ,cur_pos,TRUE);
RR_GridCtrl_SetHomeCol(hWnd,cur_pos);
SetRect(&rect,pGridData->columnwidths[0],pGridData->titleheight,
pGridData->gridWidth,pGridData->gridHeight);
InvalidateRect(hWnd,&rect,FALSE);
}
}
break;
case SB_THUMBTRACK:
{
cur_pos=HIWORD(wParam);
SetScrollPos(hWnd,SB_HORZ,cur_pos,TRUE);
RR_GridCtrl_SetHomeCol(hWnd,cur_pos);
SetRect(&rect,pGridData->columnwidths[0],pGridData->titleheight,
pGridData->gridWidth,pGridData->gridHeight);
InvalidateRect(hWnd,&rect,FALSE);
}
break;
default:
break;
}
return 0;
}
static LRESULT RR_GridCtrlOnVScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData;
RECT rect;
int min=0,max=0;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
RR_GridCtrl_SetFocus(hWnd,FALSE);
switch(LOWORD(wParam))
{
case SB_THUMBTRACK://拖动滚动条
pGridData->homerow = HIWORD(wParam);
SetScrollPos(hWnd,SB_VERT,HIWORD(wParam),TRUE);
SetRect(&rect,0,pGridData->titleheight+pGridData->headerrowheight,
pGridData->gridWidth,pGridData->gridHeight);
InvalidateRect(hWnd,&rect,FALSE);
break;
case SB_PAGEDOWN://Roger: home行需要重设
{
int rows_page;
int pos;
SetRect(&rect,0,pGridData->titleheight+pGridData->headerrowheight,
pGridData->gridWidth,pGridData->gridHeight);
GetScrollRange(hWnd,SB_VERT,&min,&max);
pos = GetScrollPos(hWnd,SB_VERT);
rows_page = RR_RECT_HEIGHT(rect)/pGridData->rowheight;
pos+=rows_page;
if(pos>max)
{
pos = max;
}
pGridData->homerow = pos;
SetScrollPos(hWnd,SB_VERT,pos,TRUE);
InvalidateRect(hWnd,&rect,FALSE);
}
break;
case SB_PAGEUP:
{
int rows_page;
int pos;
SetRect(&rect,0,pGridData->titleheight+pGridData->headerrowheight,
pGridData->gridWidth,pGridData->gridHeight);
GetScrollRange(hWnd,SB_VERT,&min,&max);
rows_page = RR_RECT_HEIGHT(rect)/pGridData->rowheight;
pos = GetScrollPos(hWnd,SB_VERT);
pos-=rows_page;
if(pos<min)
{
pos = min;
}
pGridData->homerow =pos;
SetScrollPos(hWnd,SB_VERT,pos,TRUE);
InvalidateRect(hWnd,&rect,FALSE);
}
break;
case SB_LINEDOWN:
{
int pos;
SetRect(&rect,0,pGridData->titleheight+pGridData->headerrowheight,
pGridData->gridWidth,pGridData->gridHeight);
GetScrollRange(hWnd,SB_VERT,&min,&max);
pos=GetScrollPos(hWnd,SB_VERT);
pos++;
if(pos > max)
{
pos=max;
}
pGridData->homerow = pos;
SetScrollPos(hWnd,SB_VERT,pos,TRUE);
InvalidateRect(hWnd,&rect,FALSE);
}
break;
case SB_LINEUP:
{
int pos;
SetRect(&rect,0,pGridData->titleheight+pGridData->headerrowheight,
pGridData->gridWidth,pGridData->gridHeight);
GetScrollRange(hWnd,SB_VERT,&min,&max);
pos=GetScrollPos(hWnd,SB_VERT);
pos--;
if(pos < min)
{
pos=min;
}
pGridData->homerow = pos;
SetScrollPos(hWnd,SB_VERT,pos,TRUE);
InvalidateRect(hWnd,&rect,FALSE);
}
break;
default:
break;
}
return 0;
}
static LRESULT RR_GridCtrlOnKeyDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
int rows_page=0;
int row_diff=0;
int row=0;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
switch(wParam)
{
case VK_NEXT://PAGE DOWN key
{
if(pGridData->rows <2 || pGridData->sel_row >= pGridData->rows-1 ||
!pGridData->bShowVScroll)
{
break;
}
row = pGridData->sel_row;
row_diff = row - pGridData->homerow;
rows_page = pGridData->bottomvisiblerow - pGridData->topvisiblerow+1;
if(row_diff>=0 && row_diff<rows_page )
{
//当前选择行是可见的,
//选择行滚动条一起翻页
RR_GridCtrlOnVScroll(hWnd,WM_VSCROLL,SB_PAGEDOWN,0);
//注意:此时不能基于topvisiblerow加,topvisiblerow要到WM_PAINT响应时才更新
row = pGridData->homerow+row_diff;
}
else
{
//不可见,改变选择行,使其可见,滚动条不动
if(row_diff<0)
{
row= pGridData->topvisiblerow;
}
}
if(row<1)
{
row=1;
}
else if(row > pGridData->rows-1)
{
row=pGridData->rows-1;
}
RR_GridCtrl_ChgSelRow(hWnd,row);
RR_GridCtrl_Refresh(hWnd,FALSE);
}
break;
case VK_PRIOR://PAGE UP key
{
if(pGridData->rows <2 || pGridData->sel_row <2||
!pGridData->bShowVScroll)
{
break;
}
row = pGridData->sel_row;
row_diff = row- pGridData->homerow;
rows_page = pGridData->bottomvisiblerow - pGridData->topvisiblerow+1;
if(row_diff>=0 && row_diff<rows_page )
{
//当前选择行是可见的,
//选择行滚动条一起翻页
RR_GridCtrlOnVScroll(hWnd,WM_VSCROLL,SB_PAGEUP,0);
//注意:此时不能基于topvisiblerow加,topvisiblerow要到WM_PAINT响应时才更新
row = pGridData->homerow+row_diff;
}
else
{
//不可见,改变选择行,使其可见,滚动条不动
if(row_diff>=rows_page)
{
row= pGridData->bottomvisiblerow;
}
}
if(row<1)
{
row=1;
}
else if(row > pGridData->rows-1)
{
row =pGridData->rows-1;
}
RR_GridCtrl_ChgSelRow(hWnd,row );
RR_GridCtrl_Refresh(hWnd,FALSE);
}
break;
case VK_DOWN:
{
if(pGridData->rows <2 || pGridData->sel_row >= pGridData->rows-1 )
{
break;
}
row = pGridData->sel_row;
row ++;
if(row > pGridData->rows-1)
{
row =pGridData->rows-1;
}
if(row > pGridData->bottomvisiblerow && pGridData->bShowVScroll)
{
RR_GridCtrlOnVScroll(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
}
RR_GridCtrl_ChgSelRow(hWnd,row );
RR_GridCtrl_Refresh(hWnd,FALSE);
}
break;
case VK_UP:
{
if(pGridData->rows <2 || pGridData->sel_row <2)
{
break;
}
row = pGridData->sel_row;
row --;
if(row <1)
{
row =1;
}
if(row <pGridData->topvisiblerow && pGridData->bShowVScroll)
{
RR_GridCtrlOnVScroll(hWnd,WM_VSCROLL,SB_LINEUP,0);
}
RR_GridCtrl_ChgSelRow(hWnd,row );
RR_GridCtrl_Refresh(hWnd,FALSE);
break;
}
case VK_LEFT:
{
if(pGridData->bShowHScroll)
{
RR_GridCtrlOnHScroll(hWnd,WM_HSCROLL,SB_PAGELEFT,0);
}
break;
}
case VK_RIGHT:
{
if(pGridData->bShowHScroll)
{
RR_GridCtrlOnHScroll(hWnd,WM_HSCROLL,SB_PAGERIGHT,0);
}
break;
}
case VK_HOME :
if(pGridData->rows <2 || pGridData->sel_row <2)
{
break;
}
if(pGridData->bShowVScroll)
{
int min;
int max;
GetScrollRange(hWnd,SB_VERT,&min,&max);
SetScrollPos(hWnd,SB_VERT,min,TRUE);
pGridData->homerow = min;
}
RR_GridCtrl_ChgSelRow(hWnd,1);
RR_GridCtrl_Refresh(hWnd,FALSE);
break;
case VK_END:
if(pGridData->rows <2 || pGridData->sel_row >= pGridData->rows-1 )
{
break;
}
if(pGridData->bShowVScroll)
{
int min;
int max;
GetScrollRange(hWnd,SB_VERT,&min,&max);
SetScrollPos(hWnd,SB_VERT,max,TRUE);
pGridData->homerow = max;
}
RR_GridCtrl_ChgSelRow(hWnd,pGridData->rows-1);
RR_GridCtrl_Refresh(hWnd,FALSE);
break;
case VK_ESCAPE:
case VK_TAB:
//把焦点移到下一TABSTOP控件
SetFocus(GetNextDlgTabItem(GetParent(hWnd),hWnd,FALSE));
break;
case VK_INSERT :
if(pGridData->sel_row >0 && RR_GetInsertKeyStyle(hWnd))
{
SendMessage(hWnd,GM_GRID_INSERT_ROW,pGridData->sel_row,0);
}
break;
case VK_DELETE:
if(pGridData->sel_row >0 && RR_GetDeleteKeyStyle(hWnd))
{
SendMessage(hWnd,GM_GRID_DELETE_ROW,pGridData->sel_row,0);
}
break;
case VK_RETURN:
//如果是在最后行,添加一新行
if(pGridData->rows>=2 && pGridData->sel_row < pGridData->rows-1 )
{
//移动到下一行
row = pGridData->sel_row;
row ++;
if(row > pGridData->rows-1)
{
row =pGridData->rows-1;
}
if(row > pGridData->bottomvisiblerow && pGridData->bShowVScroll)
{
RR_GridCtrlOnVScroll(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
}
RR_GridCtrl_ChgSelRow(hWnd,row );
RR_GridCtrl_Refresh(hWnd,FALSE);
}
else if(RR_GetEnterKeyStyle(hWnd))
{
//增加一新行
RR_ASSERT(pGridData->rows>0);
SendMessage(hWnd,GM_GRID_INSERT_ROW,pGridData->rows,0);
}
break;
default:
break;
}
return 0;
}
static LRESULT RR_GridCtrlOnGetDlgCode(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT ReturnValue = DLGC_DEFPUSHBUTTON;
LPMSG lpmsg = (LPMSG)lParam;
if (lpmsg!=NULL)
{
if (lpmsg->message == WM_KEYDOWN)
{
switch(lpmsg->wParam)
{
case VK_RETURN:
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
case VK_ESCAPE:
ReturnValue = DLGC_WANTMESSAGE;
break;
default:
break;
}
}
}
return ReturnValue;
}
static LRESULT RR_GridCtrlOnLoadGrid(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
GridSaveStruct_T *ptSaveStruct = (GridSaveStruct_T *)wParam;
StringLink_T *pLink = (StringLink_T *)lParam;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->bEditing)
{
RR_GridCtrl_Force_Exit_Edit(hWnd);
}
if(pLink!=NULL)
{
RRFreeStringLink(pGridData->ptTextLink);
RR_Safe_Free(pGridData->ptTextLink);
pGridData->ptTextLink = pLink;
}
if(ptSaveStruct != NULL)
{
RR_GridCtrl_CopyStruct(ptSaveStruct,pGridData,FALSE);
if(pGridData->hEditBackBrush!=NULL)
{
DeleteObject(pGridData->hEditBackBrush);
}
pGridData->hEditBackBrush = CreateSolidBrush(pGridData->crBrushCommon);
//注:字体暂未实现保存/装载
}
else
{
RR_GridCtrl_ResumeDefaultStruct(pGridData);
}
pGridData->bCellModified = FALSE;
pGridData->bRowModified = FALSE;
pGridData->bGridTextModified = FALSE;
pGridData->bGridFrameModified = FALSE;
RR_GridCtrl_Resize(hWnd);
return 0;
}
static LRESULT RR_GridCtrlOnSaveGrid(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT ReturnValue = 0;
Grid_T * pGridData = NULL;
char *pszFile = (char *)wParam;
char szTmpFile[MAX_PATH];
char *pDot;
HANDLE hFile;
BYTE buf[RR_STRUCT_SIZE_MAX];
GridSaveStruct_T tSaveStruct;
DWORD size=0;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL && pszFile!=NULL);
RR_ASSERT(sizeof(tSaveStruct)<RR_STRUCT_SIZE_MAX);
if(pGridData->bEditing)
{
RR_GridCtrl_Force_Exit_Edit(hWnd);
}
//先保证到临时文件,保存成功后再覆盖原文件
pDot = strrchr(pszFile,'.');
if(pDot==NULL)
{
return -1;//参数错误
}
strncpy(szTmpFile,pszFile,pDot-pszFile);
strcpy(szTmpFile+(pDot-pszFile),".tmp");
memset(buf,0,sizeof(buf));
memset(&tSaveStruct,0,sizeof(tSaveStruct));
strcpy((char*)buf,RR_GRID_FILE_HEAD);
RR_GridCtrl_CopyStruct(&tSaveStruct,pGridData,TRUE);
memcpy(buf+strlen(RR_GRID_FILE_HEAD)+1,&tSaveStruct,sizeof(tSaveStruct));
//如果不存在,创建文件,如果存在,重写文件
hFile = CreateFile(szTmpFile,GENERIC_WRITE,
FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
return -2;//创建临时文件失败
}
if(!WriteFile(hFile,buf,RR_STRUCT_SIZE_MAX,&size,NULL) ||
size != RR_STRUCT_SIZE_MAX)
{
CloseHandle(hFile);
return -3;//写临时文件失败
}
CloseHandle(hFile);
if(pGridData->ptTextLink->node_cnt==0)
{
if(!CopyFile(szTmpFile,pszFile,FALSE))
{
RR_OUTPUT_LAST_ERR(hWnd);
ReturnValue =-4;//拷贝失败
}
else
{
pGridData->bCellModified = FALSE;
pGridData->bRowModified = FALSE;
pGridData->bGridTextModified = FALSE;
pGridData->bGridFrameModified = FALSE;
}
return ReturnValue;
}
if(!RR_Save_StringLink_To_File(szTmpFile,-1,pGridData->ptTextLink))
{
return -3;//写临时文件失败
}
if(ReturnValue == 0)
{
if(!CopyFile(szTmpFile,pszFile,FALSE))
{
RR_OUTPUT_LAST_ERR(hWnd);
ReturnValue =-4;//拷贝失败
}
else
{
pGridData->bCellModified = FALSE;
pGridData->bRowModified = FALSE;
pGridData->bGridTextModified = FALSE;
pGridData->bGridFrameModified = FALSE;
}
}
return ReturnValue;
}
static LRESULT RR_GridCtrlOnInsertRow(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
int row= (int)wParam;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(row<=0|| row >pGridData->rows || row >ROWS_MAX)
{
return -1;
}
//插入新行前通知父窗口
lParam = MAKELPARAM(row,pGridData->rows-1);//新行号和原来的行数(不包括第0行)
if(RR_GridCtrl_Notify(hWnd,GN_INSERT_ROW,lParam))
{
//消息返回值为非0:中断插入
return 1;
}
if(pGridData->bEditing && !RR_GridCtrl_Exit_Edit(hWnd))
{
//父窗口退出编辑通知响应不让退出
return 2;
}
pGridData->rows++;
if(row!=pGridData->rows)
{
//如果不是在最后插入,存储数据的ListBox需要更新
RR_GridCtrl_UpdateData(pGridData->ptTextLink,row,TRUE);
}
RR_GridCtrl_Resize(hWnd);
if(pGridData->bShowVScroll)
{
if(row <pGridData->topvisiblerow && pGridData->bShowVScroll)
{
RR_GridCtrlOnVScroll(hWnd,WM_VSCROLL,SB_LINEUP,0);
}
else if(row > pGridData->bottomvisiblerow)
{
RR_GridCtrlOnVScroll(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
}
}
pGridData->bGridTextModified = TRUE;
pGridData->bGridFrameModified = TRUE;
RR_GridCtrl_CalcVisibleCellBoundaries(pGridData);
RR_GridCtrl_ChgSelRow(hWnd,row );
//RR_GridCtrl_Refresh(hWnd,FALSE);
return 0;
}
static LRESULT RR_GridCtrlOnDeleteRow(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
int row= (int)wParam;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(row<=0|| row >pGridData->rows-1 )
{
return -1;
}
//删除行之前通知父窗口
lParam = MAKELPARAM(row,pGridData->rows-1);//删除行号和未删除前总行数(不包括第0行)
if(RR_GridCtrl_Notify(hWnd,GN_DELETE_ROW,lParam))
{
//消息返回值为非0:中断插入
return 1;
}
if(pGridData->bEditing)
{
if(row == pGridData->tEditCell.row)
{
RR_GridCtrl_Discard_Edit(hWnd);
}
else
{
if(!RR_GridCtrl_Exit_Edit(hWnd))
{
//父窗口退出编辑通知响应不让退出
return 2;
}
}
}
RR_GridCtrl_UpdateData(pGridData->ptTextLink,row,FALSE);
if(pGridData->rows <=2 )
{
//始终保持Grid有2X2个单元(含0行/0列)
RR_GridCtrl_Refresh(hWnd,FALSE);
return 0;
}
pGridData->rows--;
pGridData->bGridTextModified = TRUE;
pGridData->bGridFrameModified = TRUE;
if(pGridData->sel_row >=pGridData->rows)
{
RR_GridCtrl_ChgSelRow(hWnd,pGridData->rows-1);
}
RR_GridCtrl_Resize(hWnd);
return 0;
}
static LRESULT RR_GridCtrlOnGetCellTextLen(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
GridCell_T* pCell = (GridCell_T*)wParam;
Grid_T * pGridData = NULL;
char szSymbol[DATA_SYMBOL_LEN+1];
int len=0;
int editing_len = 0;
ListNode * pNode=NULL;
StringLinkNode_T *pStrNode = NULL;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData == NULL || pCell==NULL)
{
return -1;
}
if(RR_GridCtrl_OutOfRange(pCell))
{
return -2;
}
sprintf(szSymbol,"%05d-%03d",pCell->row,pCell->col); //9
pNode= RR_GridCtrl_SearchData(pGridData->ptTextLink,szSymbol);
if(pNode!=NULL)
{
pStrNode = List_Entry(pNode,StringLinkNode_T,node);
len = strlen(pStrNode->szString);
len -=DATA_SYMBOL_LEN;
}
if(pGridData->bEditing && RR_GridCtrl_CmpCell(&(pGridData->tEditCell),pCell))
{
editing_len = SendMessage(pGridData->hChildEdit,EM_LINELENGTH,0,0);
}
len = editing_len>len?editing_len:len;
len+=10; //健壮性
return len;
}
static LRESULT RR_GridCtrlOnGetCellText(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
GridCell_T* pCell = (GridCell_T*)wParam;
char *pszText = (char *)lParam;
Grid_T * pGridData = NULL;
char szSymbol[DATA_SYMBOL_LEN+1];
ListNode * pNode=NULL;
StringLinkNode_T *pStrNode = NULL;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData == NULL || pCell==NULL || pszText == NULL)
{
if(pszText!=NULL)
{
pszText[0] = 0;//调用者保证此处不越界
}
return -1;
}
if(RR_GridCtrl_OutOfRange(pCell))
{
pszText[0] = 0;//调用者保证此处不越界
return -2;
}
sprintf(szSymbol,"%05d-%03d",pCell->row,pCell->col); //9
pNode= RR_GridCtrl_SearchData(pGridData->ptTextLink,szSymbol);
if(pNode !=NULL)
{
int len;
pStrNode = List_Entry(pNode,StringLinkNode_T,node);
len = strlen(pStrNode->szString);
len -=DATA_SYMBOL_LEN;
strcpy(pszText,pStrNode->szString+DATA_SYMBOL_LEN);//调用者保证此处不越界
}
else
{
pszText[0] = 0;//调用者保证此处不越界
}
return 0;
}
static LRESULT RR_GridCtrlOnSetCellText(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
GridCell_T* pCell = (GridCell_T*)wParam;
char *pszText=(char*)lParam;
char *pszBuf = NULL;
char szSymbol[DATA_SYMBOL_LEN+1];
int i=0;
ListNode * pNode=NULL;
StringLinkNode_T *pStrNode = NULL;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData == NULL ||pCell == NULL || pszText == NULL)
{
return -1;//参数错误
}
if(RR_GridCtrl_OutOfRange(pCell))
{
return -2;
}
if(pGridData->bEditing&& RR_GridCtrl_CmpCell(&(pGridData->tEditCell),pCell))
{
RR_GridCtrl_Discard_Edit(hWnd);
}
sprintf(szSymbol,"%05d-%03d",pCell->row,pCell->col);//9
pNode = RR_GridCtrl_SearchData(pGridData->ptTextLink,szSymbol);
RR_ASSERT(DATA_SYMBOL_LEN>=9);
for (i =9;i<DATA_SYMBOL_LEN;i++)
{
szSymbol[i] = ' ';//预留
}
if(strlen(pszText) >CELL_TEXT_MAX )
{
pszBuf = (char*)RR_MALLOC(DATA_SYMBOL_LEN+CELL_TEXT_MAX+1);
strncpy(pszBuf,szSymbol,DATA_SYMBOL_LEN);
strncpy(pszBuf+DATA_SYMBOL_LEN,pszText,CELL_TEXT_MAX);
}
else
{
if(pszText[0]!=0)
{
pszBuf = (char*)RR_MALLOC(DATA_SYMBOL_LEN+strlen(pszText)+1);
strncpy(pszBuf,szSymbol,DATA_SYMBOL_LEN);
strcpy(pszBuf+DATA_SYMBOL_LEN,pszText);
}
}
if(pNode!=NULL)
{
pStrNode = List_Entry(pNode,StringLinkNode_T,node);
if(pszBuf !=NULL)
{
RR_Safe_Free(pStrNode->szString);
pStrNode->szString= pszBuf;
}
else
{
List_Del(&pStrNode->node);
pGridData->ptTextLink->node_cnt --;
RR_Safe_Free(pStrNode->szString);
RR_Safe_Free(pStrNode);
}
}
else
{
if(pszBuf!=NULL)
{
RR_SqrtInsertStringToLink(pGridData->ptTextLink,pszBuf);
}
}
pGridData->bGridTextModified = TRUE;
RR_GridCtrl_Refresh(hWnd,FALSE);
return 0;
}
static LRESULT RR_GridCtrlOnSetStyle(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
DWORD dwSysStyle;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(pGridData->dwStyle == (DWORD)wParam)
{
return 0;
}
pGridData->dwStyle = (DWORD)wParam;
dwSysStyle = GetWindowLong(hWnd,GWL_STYLE);
if(pGridData->dwStyle & GS_READONLY)
{
//只读
//只读时不接受焦点
if(dwSysStyle & WS_TABSTOP)
{
dwSysStyle= dwSysStyle & (~WS_TABSTOP);
SetWindowLong(hWnd,GWL_STYLE ,dwSysStyle);
}
}
else
{
//可骗辑
if(!(dwSysStyle & WS_TABSTOP))
{
dwSysStyle= dwSysStyle | WS_TABSTOP;
SetWindowLong(hWnd,GWL_STYLE ,dwSysStyle);
}
}
RR_GridCtrl_Resize(hWnd);
return 0;
}
static LRESULT RR_GridCtrlOnSetGridCellCount(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Grid_T * pGridData = NULL;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
RR_ASSERT(pGridData!=NULL);
if(wParam< 0 || wParam> ROWS_MAX ||
lParam <0 || lParam >COLS_MAX)
{
return -1;
}
if((int)wParam+1 == pGridData->rows &&
(int)lParam+1 == pGridData->cols)
{
return 0;
}
if(pGridData->bEditing)
{
RR_GridCtrl_Discard_Edit(hWnd);
}
RRFreeStringLink(pGridData->ptTextLink);
pGridData->bGridTextModified = TRUE;
pGridData->rows = (int)wParam+1;
if(pGridData->rows<2)
{
pGridData->rows =2;
}
pGridData->cols = (int)lParam+1;
if(pGridData->cols<2)
{
pGridData->cols =2;
}
pGridData->sel_row =1;
pGridData->bGridFrameModified = TRUE;
RR_GridCtrl_Resize(hWnd);
return 0;
}
LRESULT CALLBACK RR_GridCtrlProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT ReturnValue=0;
Grid_T * pGridData = NULL;
pGridData = (Grid_T *)GetWindowLong(hWnd,GWL_USERDATA);
switch (message)
{
case WM_CREATE:
ReturnValue=RR_GridCtrlOnCreate(hWnd,message,wParam,lParam);
break;
case WM_SETTEXT: //设置标题文本
ReturnValue=RR_GridCtrlOnSetText(hWnd,message,wParam,lParam);
break;
case WM_SIZE:
ReturnValue=RR_GridCtrlOnSize(hWnd,message,wParam,lParam);
break;
case WM_PAINT:
ReturnValue=RR_GridCtrlOnPaint(hWnd,message,wParam,lParam);
break;
case WM_LBUTTONDOWN:
ReturnValue=RR_GridCtrlOnLButtonDown(hWnd,message,wParam,lParam);
break;
case WM_MOUSEMOVE:
ReturnValue=RR_GridCtrlOnMouseMove(hWnd,message,wParam,lParam);
break;
case WM_LBUTTONUP:
ReturnValue=RR_GridCtrlOnLButtonUp(hWnd,message,wParam,lParam);
break;
case WM_LBUTTONDBLCLK:
ReturnValue=RR_GridCtrlOnLButtonDblclk(hWnd,message,wParam,lParam);
break;
/*case WM_SETCURSOR:
ReturnValue=RR_GridCtrlOnSetCursor(hWnd,message,wParam,lParam);
break;*/
case WM_ERASEBKGND:
break;//自画
case WM_KEYDOWN:
ReturnValue=RR_GridCtrlOnKeyDown(hWnd,message,wParam,lParam);
break;
case WM_SETFOCUS:
{
RR_ASSERT(pGridData!=NULL);
pGridData->bGridHasFocus = TRUE;
if((HWND)wParam != pGridData->hChildEdit)
{
//焦点不是由单元编辑框失去
//给父窗口发一个通知
RR_GridCtrl_Notify(hWnd,GN_GET_FOCUS,(LPARAM)wParam);
RR_GridCtrl_Refresh(hWnd,FALSE);
}
}
break;
case WM_KILLFOCUS:
RR_ASSERT(pGridData!=NULL);
if((HWND)wParam != pGridData->hChildEdit)
{
//焦点不是由单元编辑窗口获得
pGridData->bGridHasFocus = FALSE;
RR_GridCtrl_Notify(hWnd,GN_LOST_FOCUS,(LPARAM)wParam);
}
RR_GridCtrl_Refresh(hWnd,FALSE);
break;
case WM_DESTROY:
ReturnValue=RR_GridCtrlOnDestroy(hWnd,message,wParam,lParam);
break;
case WM_HSCROLL:
ReturnValue=RR_GridCtrlOnHScroll(hWnd,message,wParam,lParam);
break;
case WM_VSCROLL:
ReturnValue=RR_GridCtrlOnVScroll(hWnd,message,wParam,lParam);
break;
case WM_GETDLGCODE:
ReturnValue=RR_GridCtrlOnGetDlgCode(hWnd,message,wParam,lParam);
break;
case WM_CTLCOLOREDIT:
if(pGridData!=NULL)
{
SetTextColor((HDC)wParam,pGridData->crTextCommon);
SetBkMode((HDC)wParam,TRANSPARENT);
ReturnValue = (LRESULT)pGridData->hEditBackBrush;
}
else
{
ReturnValue = DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_ENABLE:
if(wParam)
{
//enable 窗口
RR_SetReadOnlyStyle(hWnd,FALSE);
}
else
{
//disable 窗口
if(pGridData->bEditing)
{
RR_GridCtrl_Discard_Edit(hWnd);
}
RR_SetReadOnlyStyle(hWnd,TRUE);
}
RR_GridCtrl_Refresh(hWnd,FALSE);
break;
case GM_LOAD_GRID:
ReturnValue=RR_GridCtrlOnLoadGrid(hWnd,message,wParam,lParam);
break;
case GM_SAVE_GRID:
ReturnValue=RR_GridCtrlOnSaveGrid(hWnd,message,wParam,lParam);
break;
case GM_GRID_INSERT_ROW:
ReturnValue=RR_GridCtrlOnInsertRow(hWnd,message,wParam,lParam);
break;
case GM_GRID_DELETE_ROW:
ReturnValue=RR_GridCtrlOnDeleteRow(hWnd,message,wParam,lParam);
break;
case GM_GRID_SET_READONLY:
RR_ASSERT(pGridData!=NULL);
if(wParam)
{
if(pGridData->bEditing)
{
RR_GridCtrl_Discard_Edit(hWnd);
}
RR_SetReadOnlyStyle(hWnd,TRUE);
}
else
{
RR_SetReadOnlyStyle(hWnd,FALSE);
}
RR_GridCtrl_Refresh(hWnd,FALSE);
break;
case GM_GET_CELL_TEXT_LEN:
ReturnValue = RR_GridCtrlOnGetCellTextLen(hWnd,message,wParam,lParam);
break;
case GM_GET_CELL_TEXT:
ReturnValue = RR_GridCtrlOnGetCellText(hWnd,message,wParam,lParam);
break;
case GM_SET_CELL_TEXT:
ReturnValue =RR_GridCtrlOnSetCellText(hWnd,message,wParam,lParam);
break;
case GM_SET_EDIT_TEXT://wParam -- GridCell_T* ;lParam-- text
if(pGridData->bEditing && RR_GridCtrl_CmpCell(&(pGridData->tEditCell),(GridCell_T*)wParam)
&& lParam!=0)
{
SetWindowText(pGridData->hChildEdit,(char *)lParam);
}
else
{
ReturnValue = -1;
}
break;
case GM_GET_EDIT_TEXT:
if(pGridData->bEditing && RR_GridCtrl_CmpCell(&(pGridData->tEditCell),(GridCell_T*)wParam)
&& lParam!=0)
{
char szBuf[CELL_TEXT_MAX+1];
GetWindowText(pGridData->hChildEdit,szBuf,CELL_TEXT_MAX);
strcpy((char*)lParam,szBuf);//调用者保证此处不越界
}
else
{
ReturnValue = -1;
}
break;
case GM_GRID_SET_CELL_COUNT:
ReturnValue =RR_GridCtrlOnSetGridCellCount(hWnd,message,wParam,lParam);
break;
case GM_GRID_CLEAR_TEXT:
RR_ASSERT(pGridData!=NULL);
if(pGridData->bEditing)
{
RR_GridCtrl_Discard_Edit(hWnd);
}
RRFreeStringLink(pGridData->ptTextLink);
RR_GridCtrl_Refresh(hWnd, FALSE);
break;
case GM_GRID_GET_ROWS:
RR_ASSERT(pGridData!=NULL);
ReturnValue = pGridData->rows-1;
break;
case GM_GRID_GET_COLS:
RR_ASSERT(pGridData!=NULL);
ReturnValue = pGridData->cols-1;
break;
case GM_GET_COL_WIDTH:
RR_ASSERT(pGridData!=NULL);
if((int)wParam>=0 && (int)wParam <pGridData->cols)
{
ReturnValue = pGridData->columnwidths[wParam];
}
else
{
ReturnValue = -1;
}
break;
case GM_GET_ROW_HEIGHT:
RR_ASSERT(pGridData!=NULL);
ReturnValue = pGridData->rowheight;
break;
case GM_GET_HEADERROW_HEIGHT:
RR_ASSERT(pGridData!=NULL);
ReturnValue = pGridData->headerrowheight;
break;
case GM_GET_SELECT_ROW:
RR_ASSERT(pGridData!=NULL);
ReturnValue = pGridData->sel_row;
break;
case GM_SET_HEADER_ROW_HEIGHT:
RR_ASSERT(pGridData!=NULL);
if(pGridData->headerrowheight == (int)wParam)
{
break;
}
if(wParam >= 0)
{
pGridData->headerrowheight = (int)wParam;
}
else
{
pGridData->headerrowheight =0;
}
pGridData->bGridFrameModified = TRUE;
RR_GridCtrl_Resize(hWnd);
break;
case GM_SET_ROW_HEIGHT:
{
RR_ASSERT(pGridData!=NULL);
if(pGridData->rowheight == (int)wParam)
{
break;
}
if(wParam <1)
{
wParam=1;
}
pGridData->rowheight = wParam;
pGridData->bGridFrameModified = TRUE;
RR_GridCtrl_Resize(hWnd);
}
break;
case GM_SET_COL_WIDTH:
if((wParam >= 0) && (wParam <= COLS_MAX) && (lParam >= 0))
{
RR_ASSERT(pGridData!=NULL);
if(pGridData->columnwidths[wParam] != (int)lParam)
{
pGridData->columnwidths[wParam] = lParam;
pGridData->bGridFrameModified = TRUE;
RR_GridCtrl_Resize(hWnd);
}
}
else
{
ReturnValue =-1;
}
break;
case GM_SET_GRID_LINE_COLOR:
RR_ASSERT(pGridData!=NULL);
if(pGridData->crGridLine != (COLORREF)wParam)
{
pGridData->crGridLine = (COLORREF)wParam;
pGridData->bGridFrameModified = TRUE;
RR_GridCtrl_Refresh(hWnd,FALSE);
}
break;
case GM_SET_NOFOCUS_SELLINE_COLOR:
RR_ASSERT(pGridData!=NULL);
RR_SetHighLightStyle(hWnd,TRUE);
if(pGridData->crTextGray != (COLORREF)wParam ||
pGridData->crBrushGray != (COLORREF)lParam)
{
pGridData->crTextGray = (COLORREF)wParam;
pGridData->crBrushGray = (COLORREF)lParam;
pGridData->bGridFrameModified = TRUE;
RR_GridCtrl_Refresh(hWnd,FALSE);
}
break;
case GM_SET_FOCUS_SELLINE_COLOR:
RR_ASSERT(pGridData!=NULL);
RR_SetHighLightStyle(hWnd,TRUE);
if(pGridData->crTextLight!= (COLORREF)wParam ||
pGridData->crBrushLight != (COLORREF)lParam)
{
pGridData->crTextLight= (COLORREF)wParam;
pGridData->crBrushLight = (COLORREF)lParam;
pGridData->bGridFrameModified = TRUE;
RR_GridCtrl_Refresh(hWnd,FALSE);
}
break;
case GM_SET_READONLY_COLOR:
RR_ASSERT(pGridData!=NULL);
if(pGridData->crTextReadOnly!= (COLORREF)wParam ||
pGridData->crBrushReadOnly != (COLORREF)lParam)
{
pGridData->crTextReadOnly= (COLORREF)wParam;
pGridData->crBrushReadOnly = (COLORREF)lParam;
pGridData->bGridFrameModified = TRUE;
if(RR_GetReadOnlyStyle(hWnd))
{
RR_GridCtrl_Refresh(hWnd,FALSE);
}
}
break;
case GM_SET_GRID_COLOR:
RR_ASSERT(pGridData!=NULL);
if(pGridData->crTextCommon!= (COLORREF)wParam)
{
pGridData->crTextCommon= (COLORREF)wParam;
pGridData->bGridFrameModified = TRUE;
}
if(pGridData->crBrushCommon!= (COLORREF)lParam)
{
pGridData->crBrushCommon= (COLORREF)lParam;
pGridData->bGridFrameModified = TRUE;
if(pGridData->hEditBackBrush!=NULL)
{
DeleteObject(pGridData->hEditBackBrush);
}
pGridData->hEditBackBrush = CreateSolidBrush(pGridData->crBrushCommon);
}
RR_GridCtrl_Refresh(hWnd,FALSE);
break;
case GM_SET_TITLE_FONT:
RR_ASSERT(pGridData!=NULL);
if(wParam!=0)
{
if(pGridData->htitlefont!=NULL)
{
DeleteObject(pGridData->htitlefont);
}
pGridData->htitlefont = CreateFontIndirect((LOGFONT *)wParam);
}
break;
case GM_SET_HEADING_FONT:
RR_ASSERT(pGridData!=NULL);
if(wParam!=0)
{
if(pGridData->hheadfont!=NULL)
{
DeleteObject(pGridData->hheadfont);
}
pGridData->hheadfont = CreateFontIndirect((LOGFONT *)wParam);
}
break;
case GM_SET_BODY_FONT:
RR_ASSERT(pGridData!=NULL);
if(wParam!=0)
{
if(pGridData->hbodyfont!=NULL)
{
DeleteObject(pGridData->hbodyfont);
}
pGridData->hbodyfont = CreateFontIndirect((LOGFONT *)wParam);
}
break;
case GM_GRID_ALLOW_COL_RESIZE:
RR_ASSERT(pGridData!=NULL);
RR_SetColumnAllowResizeStyle(hWnd,(BOOL)wParam);
break;
case GM_GET_EDIT_STATUS:
{
GridCell_T * pCell = (GridCell_T *)lParam;
RR_ASSERT(pGridData!=NULL);
if(pGridData->bEditing)
{
ReturnValue =1;
if(pCell!=NULL)
{
pCell->row = pGridData->tEditCell.row;
pCell->col = pGridData->tEditCell.col;
}
}
}
break;
case GM_GRID_GET_STYLE:
RR_ASSERT(pGridData!=NULL);
ReturnValue = pGridData->dwStyle;
break;
case GM_GRID_SET_STYLE:
RR_GridCtrlOnSetStyle(hWnd,message,wParam,lParam);
break;
case GM_GET_GRID_MODIFY:
RR_ASSERT(pGridData!=NULL);
ReturnValue =pGridData->bGridTextModified || pGridData->bGridFrameModified;
if(pGridData->bEditing)
{
ReturnValue = ReturnValue||pGridData->bCellModified ;
}
break;
case GM_SET_GRID_MODIFY:
RR_ASSERT(pGridData!=NULL);
pGridData->bGridTextModified = (BOOL) lParam;
break;
case GM_GET_ROW_MODIFY:
RR_ASSERT(pGridData!=NULL);
if(pGridData->sel_row == (int)wParam)
{
ReturnValue = pGridData->bRowModified;
if(pGridData->bEditing && pGridData->tEditCell.row== (int)wParam)
{
ReturnValue = ReturnValue||pGridData->bCellModified;
}
}
break;
case GM_SET_ROW_MODIFY:
RR_ASSERT(pGridData!=NULL);
if(pGridData->sel_row ==(int)wParam )
{
pGridData->bRowModified = (BOOL) lParam;
}
else
{
ReturnValue =-1;
}
break;
case GM_GET_CELL_MODIFY:
RR_ASSERT(pGridData!=NULL);
if(pGridData->bEditing && RR_GridCtrl_CmpCell(&pGridData->tEditCell,(GridCell_T*)wParam))
{
ReturnValue = pGridData->bCellModified;
}
break;
case GM_SET_CELL_MODIFY:
RR_ASSERT(pGridData!=NULL);
if(pGridData->bEditing && RR_GridCtrl_CmpCell(&pGridData->tEditCell,(GridCell_T*)wParam))
{
pGridData->bCellModified = (BOOL) lParam;
}
else
{
ReturnValue =-1;
}
break;
case GM_GRID_ENTRY_EDITBOX:
{
GridCell_T * pCell = (GridCell_T *)wParam;
RR_ASSERT(pGridData!=NULL);
if(pGridData->bEditing )
{
if(!RR_GridCtrl_CmpCell(&pGridData->tEditCell,pCell))
{
RR_GridCtrl_Discard_Edit(hWnd);
}
else
{
break;
}
}
if(!RR_GridCtrl_Enter_Edit(hWnd,pCell,(int)lParam))
{
ReturnValue= -1;
}
}
break;
case GM_GRID_EXIT_EDITBOX:
if(!RR_GridCtrl_Exit_Edit(hWnd))
{
ReturnValue= -1;
}
break;
case GM_GET_TITLE_TEXT:
{
char* pszTitle = (char*)wParam;
int buf_size = (int)lParam;
RR_ASSERT(pGridData!=NULL);
if(pGridData->pszTitle == NULL)
{
pszTitle[0] =0;
}
else
{
int len =strlen(pGridData->pszTitle);
if(len<buf_size)
{
strcpy(pszTitle,pGridData->pszTitle);
}
else
{
strncpy(pszTitle,pGridData->pszTitle,buf_size-1);
pszTitle[buf_size-1] =0;
}
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return ReturnValue;
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_DETACH:
#ifdef _DEBUG
_CrtDumpMemoryLeaks(); //内存泄露检测
#endif
default:
break;
}
return TRUE;
}
/////////////////////////////////--提供给外部的接口函数-------------
BOOL RR_GridCtrl_Register(HINSTANCE hInstance)
{
static BOOL s_bRegister = FALSE;
WNDCLASS wclass;
if(s_bRegister)
{
//已经注册
return FALSE;
}
wclass.style = CS_DBLCLKS;//CS_HREDRAW|CS_VREDRAW;
wclass.lpfnWndProc = (WNDPROC)RR_GridCtrlProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hInstance;
wclass.hIcon = NULL;
wclass.hCursor = NULL;
wclass.hbrBackground =NULL;//(HBRUSH)(GetStockObject(GRAY_BRUSH));
wclass.lpszClassName = RR_GRIDCTRL_CLASS;
wclass.lpszMenuName = NULL;
if( (void *)RegisterClass (&wclass)!=NULL )
{
s_bRegister = TRUE;
}
else
{
RR_ASSERT(0);
return FALSE;
}
return TRUE;
}
void RR_GridCtrl_SetCell(GridCell_T *cell,int row, int col)
{
cell->row = row;
cell->col = col;
}
BOOL RR_GridCtrl_CmpCell(const GridCell_T *pCell1,const GridCell_T *pCell2)
{
if(pCell1 == NULL && pCell2 == NULL)
{
return TRUE;
}
else if (pCell1 == NULL || pCell2 == NULL)
{
return FALSE;
}
else if(pCell1->row == pCell2->row && pCell1->col == pCell2->col)
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL RR_GridCtrl_GetCellText(HWND hGrid,int row ,int col ,char *pszBuf,int buf_size)
{
int ReturnValue=0;
GridCell_T tCell;
char szText[CELL_TEXT_MAX+1];
if(pszBuf==NULL ||buf_size<1 || hGrid == NULL)
{
return FALSE;
}
tCell.row = row;
tCell.col = col;
ReturnValue = SendMessage(hGrid,GM_GET_CELL_TEXT,(WPARAM)&tCell,(LPARAM)szText);
if(ReturnValue<0)
{
pszBuf[0] =0;
return FALSE;
}
else
{
int len = strlen(szText);
if(len >= buf_size)
{
strncpy(pszBuf,szText,buf_size-1);
pszBuf[buf_size-1]=0;
}
else
{
strcpy(pszBuf,szText);
}
}
return TRUE;
}
BOOL RR_GridCtrl_SetCellText(HWND hGrid,int row ,int col ,char *pszText)
{
int ReturnValue=0;
GridCell_T tCell;
if(hGrid == NULL)
{
return FALSE;
}
tCell.row = row;
tCell.col = col;
ReturnValue = SendMessage(hGrid,GM_SET_CELL_TEXT,(WPARAM)&tCell,(LPARAM)pszText);
if(ReturnValue<0)
{
return FALSE;
}
RR_GridCtrl_Refresh(hGrid,FALSE);
return TRUE;
}
BOOL RR_GridCtrl_GetEditText(HWND hGrid,int row ,int col ,char *pszBuf,int buf_size)
{
int ReturnValue=0;
GridCell_T tCell;
char szText[CELL_TEXT_MAX+1];
if(pszBuf==NULL ||buf_size<1 || hGrid == NULL)
{
return FALSE;
}
tCell.row = row;
tCell.col = col;
ReturnValue = SendMessage(hGrid,GM_GET_EDIT_TEXT,(WPARAM)&tCell,(LPARAM)szText);
if(ReturnValue<0)
{
pszBuf[0] =0;
return FALSE;
}
else
{
int len = strlen(szText);
if(len >= buf_size)
{
strncpy(pszBuf,szText,buf_size-1);
pszBuf[buf_size-1]=0;
}
else
{
strcpy(pszBuf,szText);
}
}
return TRUE;
}
BOOL RR_GridCtrl_SetEditText(HWND hGrid,int row ,int col ,char *pszText)
{
int ReturnValue=0;
GridCell_T tCell;
if(hGrid == NULL)
{
return FALSE;
}
tCell.row = row;
tCell.col = col;
ReturnValue = SendMessage(hGrid,GM_SET_EDIT_TEXT,(WPARAM)&tCell,(LPARAM)pszText);
if(ReturnValue<0)
{
return FALSE;
}
return TRUE;
}
BOOL RR_GridCtrl_SetTitle(HWND hGrid,char szTitle[])
{
int ReturnValue=0;
if(hGrid == NULL)
{
return FALSE;
}
ReturnValue = SendMessage(hGrid,WM_SETTEXT,0,(LPARAM)szTitle);
if(ReturnValue<0)
{
return FALSE;
}
return TRUE;
}
BOOL RR_GridCtrl_GetTitle(HWND hGrid,char szTitle[],int buf_size)
{
int ReturnValue=0;
if(szTitle==NULL || buf_size<1)
{
return FALSE;
}
if(hGrid == NULL )
{
szTitle[0] =0;
return FALSE;
}
ReturnValue = SendMessage(hGrid,GM_GET_TITLE_TEXT,(WPARAM)szTitle,(LPARAM)buf_size);
if(ReturnValue<0)
{
return FALSE;
}
return TRUE;
}
//pGridRect --相对于父窗口客户区域的矩形
//hWndParent -- 创建子窗口一定要指定父窗口
HWND RR_Create_GridCtrl(DWORD dwStyle,HWND hWndParent,RECT *pGridRect, int nId,char szGridTitle[],int rows,int cols)
{
HWND hGrid=NULL;
RECT rtDst;
RECT rtParent;
Grid_T * pGridData = NULL;
BOOL bVisible = FALSE;
if(hWndParent==NULL||pGridRect==NULL )
{
return NULL;
}
if(IsRectEmpty(pGridRect))
{
return NULL;
}
GetClientRect(hWndParent,&rtParent);
if(!IntersectRect(&rtDst,pGridRect,&rtParent))
{
//两个矩形没有交集
return NULL;
}
pGridData = (Grid_T *)RR_MALLOC(sizeof(Grid_T));
RR_ASSERT(pGridData!=NULL);
if(szGridTitle!=NULL)
{
pGridData->pszTitle = (char*)RR_MALLOC(strlen(szGridTitle)+1);
strcpy(pGridData->pszTitle,szGridTitle);
}
else
{
pGridData->pszTitle = (char*)RR_MALLOC(1);
}
//如果没有第0行,第0行高度为0
//如果没有第0列,第0行宽度为0
//但是rows/cols仍需加上第0行/第0列的计数
if(rows>0)
{
if(rows>ROWS_MAX)
{
pGridData->rows = ROWS_MAX+1;
}
else
{
pGridData->rows = rows+1;//加上第0行
}
}
else
{
pGridData->rows = 2;
}
if(cols>0)
{
if(cols>COLS_MAX)
{
pGridData->cols =COLS_MAX+1;
}
else
{
pGridData->cols = cols+1;//加上第0列
}
}
else
{
pGridData->cols = 2;
}
RR_GridCtrl_InitStruct(pGridData);
pGridData->dwStyle = pGridData->dwStyle | dwStyle;
if(dwStyle&GS_VISIBLE)
{
bVisible = TRUE;
}
if(dwStyle & GS_NO_COLHEAD)
{
pGridData->headerrowheight =0;
}
if(dwStyle & GS_NO_ROWHEAD)
{
pGridData->columnwidths[0] = 0;
}
pGridData->init_rows = pGridData->rows ;
pGridData->init_cols = pGridData->cols ;
pGridData->dwInitStyle = pGridData->dwStyle;
pGridData->nGridId = (UINT)nId;
//WS_EX_CLIENTEDGE: 有边框,边框是凹下去的
//WS_CLIPCHILDREN 因为列宽变化造成编辑控件移动,使用该风格会带来显示上的问题
hGrid=CreateWindowEx(WS_EX_CLIENTEDGE,RR_GRIDCTRL_CLASS,"",
WS_CHILD/*|WS_CLIPCHILDREN/*|WS_HSCROLL |WS_VSCROLL*/,0,0,0,0,hWndParent,(HMENU)nId,(HINSTANCE)GetWindowLong(hWndParent,GWL_HINSTANCE),(LPVOID)pGridData);
if(hGrid!=NULL)
{
if(!(pGridData->dwStyle & GS_READONLY))
{
//可编辑
SetWindowLong(hGrid,GWL_STYLE ,GetWindowLong(hGrid,GWL_STYLE) | WS_TABSTOP);
}
MoveWindow(hGrid,rtDst.left,rtDst.top,rtDst.right-rtDst.left,rtDst.bottom - rtDst.top,FALSE);
if(bVisible)
{
ShowWindow(hGrid,SW_SHOW);
}
}
else
{
RR_GridCtrl_FreeStruct(pGridData);
}
return hGrid;
}
BOOL RR_Save_GridCtrl(char szFile[],HWND hGrid)
{
if(szFile == NULL ||szFile[0]==0 || hGrid == NULL)
{
return FALSE;
}
//放入消息队列
if(SendMessage(hGrid,GM_SAVE_GRID,(WPARAM)szFile,0)==0)
{
return TRUE;
}
return FALSE;
}
BOOL RR_Load_GridCtrl(char szFile[],HWND hGrid,BOOL* pbFileError)
{
HANDLE hFile;
BYTE buf[RR_STRUCT_SIZE_MAX];
GridSaveStruct_T tSaveStruct;
ULONG size =0;
int lRet;
StringLink_T *plink=NULL;
BOOL bReadSucess = TRUE;
if(pbFileError!=NULL)
{
*pbFileError = FALSE;
}
if(szFile==NULL|| szFile[0] == 0)
{
if(pbFileError!=NULL)
{
*pbFileError = TRUE;
}
return FALSE;
}
if(hGrid == NULL)
{
return FALSE;
}
//打开已存在的文件
hFile = CreateFile(szFile,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,NULL);
if(INVALID_HANDLE_VALUE == hFile) //文件不存在
{
bReadSucess = FALSE;
}
if(bReadSucess)
{
if(!ReadFile(hFile,buf,RR_STRUCT_SIZE_MAX,&size,NULL) ||
size!=RR_STRUCT_SIZE_MAX)
{
bReadSucess = FALSE;
}
CloseHandle(hFile);
}
if(bReadSucess)
{
if(strcmp((char*)buf,RR_GRID_FILE_HEAD)==0)
{
memcpy(&tSaveStruct,buf+strlen(RR_GRID_FILE_HEAD)+1,sizeof(tSaveStruct));
}
else
{
bReadSucess = FALSE;
}
}
plink = (StringLink_T*)RR_MALLOC(sizeof(StringLink_T));
RR_InitStringLink(plink);
if(bReadSucess)
{
if(!RR_Load_File_To_StringLink(szFile,RR_STRUCT_SIZE_MAX,plink))
{
RRFreeStringLink(plink);
}
}
if(bReadSucess)
{
//link链表数据将传给Grid,由Grid负责释放
lRet = SendMessage(hGrid,GM_LOAD_GRID,(WPARAM)&tSaveStruct,(LPARAM)plink);
}
else
{
if(pbFileError!=NULL)
{
*pbFileError = TRUE;
}
lRet = SendMessage(hGrid,GM_LOAD_GRID,(WPARAM)NULL,(LPARAM)plink);
}
if(lRet==0)
{
return TRUE;
}
else
{
return FALSE;
}
}
HWND RR_GetDlgGridItem(HWND hDlg,int id)
{
//char szClassName[101];
//HWND hGrid= NULL;
if(hDlg==NULL)
{
return NULL;
}
return GetDlgItem(hDlg,id) ;
/*GetClassName(hDlg,szClassName,sizeof(szClassName));
if(strcmp(szClassName,"#32770")==0)//父窗口是否对话框类
{
hGrid = GetDlgItem(hDlg,id);
if(hGrid!= NULL)
{
GetClassName(hGrid,szClassName,sizeof(szClassName));
if(strcmp(szClassName,RR_GRIDCTRL_CLASS) != 0)
{
hGrid = NULL;
}
}
return hGrid;
}
else
{
return NULL;
}*/
}