procedure TSEHStringGrid.Sort(SortCol: integer);
type
PStrList = ^AStrList;
AStrList = record
AKeyItem : string;
AKeyItemN : integer;
AItemRecord: TStrings;
end;
var
StrList: TList;
AItem: PStrList;
i: integer;
TempStrList: array of TStringList;
DataType : Char;
function StrCompareList(Item1,Item2:Pointer):Integer;
var
stTemp1, stTemp2 :PStrList;
begin
stTemp1:= Item1;
stTemp2:= Item2;
if stTemp1^.AKeyItem < stTemp2^.AKeyItem then Result:= -1
else
if stTemp1^.AKeyItem = stTemp2^.AKeyItem then Result:= 0
else
Result:= 1;
end;
function NumberCompareList(Item1,Item2:Pointer):Integer;
var
stTemp1, stTemp2 :PStrList;
begin
stTemp1:= Item1;
stTemp2:= Item2;
if stTemp1^.AKeyItemN < stTemp2^.AKeyItemN then Result:= -1
else
if stTemp1^.AKeyItemN = stTemp2^.AKeyItemN then Result:= 0
else
Result:= 1;
end;
begin
DataType := FDisplayFormat[SortCol + 1];
if FixedRows <= 0 then begin
MessageBox(Parent.Handle, 'FixedRow가 0보다 커야합니다','확장 스트링그리드',MB_OK);
exit;
end;
StrList := TList.Create;
try
for i := 1 to RowCount - 1 do begin
New(AItem);
if DataType = 'N' then begin
if IsNumber(Cells[SortCol, i]) then
AItem^.AKeyItemN := StrToInt(Cells[SortCol, i])
else
AItem^.AKeyItemN := 0;
AItem^.AKeyItem := '';
end
else begin
AItem^.AKeyItemN := 0;
AItem^.AKeyItem := Cells[SortCol, i];
end;
AItem^.AItemRecord := Rows[i];
StrList.Add(AItem);
end;
if DataType = 'N' then
StrList.Sort(@NumberCompareList)
else
StrList.Sort(@StrCompareList);
SetLength(TempStrList, StrList.Count);
for i := 0 to (StrList.Count - 1) do begin
TempStrList[i] := TStringList.Create;
TempStrList[i].AddStrings(PStrList(StrList.Items[i])^.AItemRecord);
end;
// ZapGrid;
for i := 0 to (StrList.Count - 1) do begin
Rows[i+1] := TempStrList[i];
end;
finally
for i := 0 to (StrList.Count - 1) do
begin
AItem := StrList.Items[i];
Dispose(AItem);
TempStrList[i].Free;
end;
StrList.Free;
end;
end;
procedure DrawRaisedInner(hd: THandle; Rect: TRect);
begin
DrawEdge(hd, Rect, BDR_RAISEDINNER, BF_RIGHT or BF_BOTTOM);
DrawEdge(hd, Rect, BDR_RAISEDINNER, BF_LEFT or BF_TOP);
end;
procedure DrawSunkenOuter(hd: THandle; Rect: TRect);
begin
DrawEdge(hd, Rect, BDR_SUNKENOUTER, BF_RIGHT or BF_BOTTOM);
DrawEdge(hd, Rect, BDR_SUNKENOUTER, BF_LEFT or BF_TOP);
end;
procedure TSEHStringGrid.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
inherited;
if Not FSortEnabled then exit;
FCurrent := MouseCoord(X, Y);
FRect := CellRect(FCurrent.X, FCurrent.Y);
if (FCurrent.Y >= 0) and (FCurrent.Y < FixedRows) and (FCurrent.X >= 0) then
begin
FMouseDown := True;
DrawSunkenOuter(Canvas.Handle, FRect);
end;
end;
procedure TSEHStringGrid.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
inherited;
if Not FSortEnabled then exit;
if not FMouseDown then exit;
if PtInRect(FRect, Point(X, Y)) then
DrawSunkenOuter(Canvas.Handle, FRect)
else
DrawRaisedInner(Canvas.Handle, FRect);
end;
//Title에서 마우스를 업하면...해당 칼럼을 기준으로 소팅한다
procedure TSEHStringGrid.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
HeaderStore : TStringList;
begin
inherited;
HeaderStore := TStringList.Create;
try
if Not FSortEnabled then exit;
if not FMouseDown then exit;
FMouseDown := False;
HeaderStore.AddStrings(Rows[0]);
DrawRaisedInner(Canvas.Handle, FRect);
if (FCurrent.Y >= 0) and (FCurrent.Y < FixedRows) and (FCurrent.X >= 0) then
Sort(FCurrent.X);
Rows[0] := HeaderStore;
finally
HeaderStore.Free;
end;
end;
적어 드립니다.
소트는 TList의 Sort메소드를 이용하면 편합니다.
코딩도 의외로 간결하죠...
procedure TSEHStringGrid.Sort(SortCol: integer);
type
PStrList = ^AStrList;
AStrList = record
AKeyItem : string;
AKeyItemN : integer;
AItemRecord: TStrings;
end;
var
StrList: TList;
AItem: PStrList;
i: integer;
TempStrList: array of TStringList;
DataType : Char;
function StrCompareList(Item1,Item2:Pointer):Integer;
var
stTemp1, stTemp2 :PStrList;
begin
stTemp1:= Item1;
stTemp2:= Item2;
if stTemp1^.AKeyItem < stTemp2^.AKeyItem then Result:= -1
else
if stTemp1^.AKeyItem = stTemp2^.AKeyItem then Result:= 0
else
Result:= 1;
end;
function NumberCompareList(Item1,Item2:Pointer):Integer;
var
stTemp1, stTemp2 :PStrList;
begin
stTemp1:= Item1;
stTemp2:= Item2;
if stTemp1^.AKeyItemN < stTemp2^.AKeyItemN then Result:= -1
else
if stTemp1^.AKeyItemN = stTemp2^.AKeyItemN then Result:= 0
else
Result:= 1;
end;
begin
DataType := FDisplayFormat[SortCol + 1];
if FixedRows <= 0 then begin
MessageBox(Parent.Handle, 'FixedRow가 0보다 커야합니다','확장 스트링그리드',MB_OK);
exit;
end;
StrList := TList.Create;
try
for i := 1 to RowCount - 1 do begin
New(AItem);
if DataType = 'N' then begin
if IsNumber(Cells[SortCol, i]) then
AItem^.AKeyItemN := StrToInt(Cells[SortCol, i])
else
AItem^.AKeyItemN := 0;
AItem^.AKeyItem := '';
end
else begin
AItem^.AKeyItemN := 0;
AItem^.AKeyItem := Cells[SortCol, i];
end;
AItem^.AItemRecord := Rows[i];
StrList.Add(AItem);
end;
if DataType = 'N' then
StrList.Sort(@NumberCompareList)
else
StrList.Sort(@StrCompareList);
SetLength(TempStrList, StrList.Count);
for i := 0 to (StrList.Count - 1) do begin
TempStrList[i] := TStringList.Create;
TempStrList[i].AddStrings(PStrList(StrList.Items[i])^.AItemRecord);
end;
// ZapGrid;
for i := 0 to (StrList.Count - 1) do begin
Rows[i+1] := TempStrList[i];
end;
finally
for i := 0 to (StrList.Count - 1) do
begin
AItem := StrList.Items[i];
Dispose(AItem);
TempStrList[i].Free;
end;
StrList.Free;
end;
end;
procedure DrawRaisedInner(hd: THandle; Rect: TRect);
begin
DrawEdge(hd, Rect, BDR_RAISEDINNER, BF_RIGHT or BF_BOTTOM);
DrawEdge(hd, Rect, BDR_RAISEDINNER, BF_LEFT or BF_TOP);
end;
procedure DrawSunkenOuter(hd: THandle; Rect: TRect);
begin
DrawEdge(hd, Rect, BDR_SUNKENOUTER, BF_RIGHT or BF_BOTTOM);
DrawEdge(hd, Rect, BDR_SUNKENOUTER, BF_LEFT or BF_TOP);
end;
procedure TSEHStringGrid.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
inherited;
if Not FSortEnabled then exit;
FCurrent := MouseCoord(X, Y);
FRect := CellRect(FCurrent.X, FCurrent.Y);
if (FCurrent.Y >= 0) and (FCurrent.Y < FixedRows) and (FCurrent.X >= 0) then
begin
FMouseDown := True;
DrawSunkenOuter(Canvas.Handle, FRect);
end;
end;
procedure TSEHStringGrid.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
inherited;
if Not FSortEnabled then exit;
if not FMouseDown then exit;
if PtInRect(FRect, Point(X, Y)) then
DrawSunkenOuter(Canvas.Handle, FRect)
else
DrawRaisedInner(Canvas.Handle, FRect);
end;
//Title에서 마우스를 업하면...해당 칼럼을 기준으로 소팅한다
procedure TSEHStringGrid.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
HeaderStore : TStringList;
begin
inherited;
HeaderStore := TStringList.Create;
try
if Not FSortEnabled then exit;
if not FMouseDown then exit;
FMouseDown := False;
HeaderStore.AddStrings(Rows[0]);
DrawRaisedInner(Canvas.Handle, FRect);
if (FCurrent.Y >= 0) and (FCurrent.Y < FixedRows) and (FCurrent.X >= 0) then
Sort(FCurrent.X);
Rows[0] := HeaderStore;
finally
HeaderStore.Free;
end;
end;