|
위의 답변을 수정하였습니다.
위글의 방법으로 할경우 스크롤바가 생겼을때 처리에 심각한 문제가 있습니다.
MouseMove때 Column의 경계선에 마우스가 와있는지 확인하는 방법을 바꾸었으며
또 MouseUp때 현재 sizing중이었으면 선택된 컬럼의 넓이를 수정해주는 부분도 좀 바뀌었습니다.
그리고 Sizing중일때 Mouse가 Down된 상태로 움직이므로
Cell의 선택이 바뀝니다.
이문제를 해결하기위해
Sizing중에는 Grid의 Options에서 goRangeSelect 를 뺐다고
끝난후(MouseUp)이벤트에 복귀시켰습니다.
그렇게 해도 Sizing중에 선택된 Cell이 단 하나지만 움직이는 위치에 따라 바뀝니다.
그걸 해결하기 위해 Sizing중에는 sub-classing으로 WM_MOUSEMOVE 메세지만 처리하고
return했습니다.
그러나 아직 문제가 남아있네요
[남은 문제들...]
1. Sizing하면서 StringGrid를 벗어나는 경우에 처리에 문제가 있습니다.
이건 어떻게 해야 될까요? 아직 저도 특별한 아이디어가 안떠오르네요..
좋은생각나면 수정해서 올려드리겠습니다.
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
int __fastcall IABS(int a ,int b)
{
if(a>b)return a-b;
else return b-a;
}
//---------------------------------------------------------------------------
bool bSize;
TPoint FsPoint,LaPoint;
int iColNum;
TColor clPenColor;
TPenMode pmPenMode;
typedef void __fastcall (__closure *TWNDPROC)(TMessage &msg); //VCL용 WNDPROC 타입 선언
TWNDPROC OriginalProc;
void __fastcall TForm1::FormCreate(TObject *Sender)
{
//
for(int r=0;r<sgrd->RowCount;r++)
{
for(int c=0;c<sgrd->RowCount;c++)
{
sgrd->Cells[r][c]=IntToStr(r)+" - "+IntToStr(c);
}
}
pmPenMode=sgrd->Canvas->Pen->Mode;
clPenColor=sgrd->Canvas->Pen->Color;
sgrd->Options=sgrd->Options>>goColSizing;
OriginalProc=sgrd->WindowProc; // 프로그램이 시작되면서 원래 WndProc를 따로 저장해두고..
sgrd->WindowProc=SGridMessageProc; //내가 만든 WndProc함수를 TracBar에 설정해줍니다.
}
//---------------------------------------------------------------------------
//TarckBar 원래의 WinProc 저장할 변수
void __fastcall TForm1::sgrdMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if(sgrd->Cursor==crHSplit)
{
bSize=true;
FsPoint.x=X;
FsPoint.y=0;
LaPoint.x=X;
LaPoint.y=sgrd->RowCount*(sgrd->DefaultRowHeight+sgrd->GridLineWidth);
sgrd->Canvas->Pen->Mode=pmNot;
sgrd->Canvas->Pen->Color=clBlack;
sgrd->Canvas->MoveTo(FsPoint.x,FsPoint.y);
sgrd->Canvas->LineTo(LaPoint.x,LaPoint.y);
sgrd->Canvas->Pen->Mode=pmPenMode;
sgrd->Canvas->Pen->Color=clPenColor;
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::SGridMessageProc(TMessage &msg)
{
if(msg.Msg==WM_MOUSEMOVE)
{
if(bSize)
{
int X;
// msg.LParamHi; //Y값
// msg.LParamLo; //X값
X=msg.LParamLo;
sgrd->Canvas->Pen->Mode=pmNot;
sgrd->Canvas->Pen->Color=clBlack;
sgrd->Canvas->MoveTo(FsPoint.x,FsPoint.y);
sgrd->Canvas->LineTo(LaPoint.x,LaPoint.y);
FsPoint.x=X;
FsPoint.y=0;
LaPoint.x=X;
LaPoint.y=sgrd->RowCount*(sgrd->DefaultRowHeight+sgrd->GridLineWidth);
sgrd->Canvas->MoveTo(FsPoint.x,FsPoint.y);
sgrd->Canvas->LineTo(LaPoint.x,LaPoint.y);
sgrd->Canvas->Pen->Mode=pmPenMode;
sgrd->Canvas->Pen->Color=clPenColor;
return; //MouseWheel 이벤트는 모두 return 해버리고
}
}
OriginalProc(msg); //그밖에 메세지는 원래 tracbar의 WndProc함수를 돌려서 동작하도록 합니다.
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sgrdMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
if(!bSize)
{
if(!Shift.Contains(ssLeft))
{
int iX=0;
int iCol,iRow;
Label1->Caption="X:"+IntToStr(X)+" , Y:"+IntToStr(Y);
sgrd->MouseToCell(X,Y,iCol,iRow);
TRect rc=sgrd->CellRect(iCol,iRow);
if(IABS(rc.right,X)<3)
{
sgrd->Cursor=crHSplit;
iColNum=iCol;
sgrd->Options>>goRangeSelect;
return;
}
else if(IABS(rc.Left,X)<3)
{
sgrd->Cursor=crHSplit;
iColNum=iCol-1;
sgrd->Options>>goRangeSelect;
return;
}
}
if(sgrd->Cursor==crHSplit)
{
sgrd->Cursor=crDefault;//
sgrd->Options=sgrd->Options<<goRangeSelect;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sgrdMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
sgrd->Invalidate();
sgrd->Canvas->Pen->Color=clWhite;
if(bSize)
{
TRect rc=sgrd->CellRect(iColNum,0);
if(rc.Left<=X)
{
sgrd->ColWidths[iColNum]=X-rc.Left;
}
}
bSize=false;
sgrd->Cursor=crDefault;
sgrd->Options=sgrd->Options<<goRangeSelect;
}
//---------------------------------------------------------------------------
장성호 님이 쓰신 글 :
: 전에도 똑같은 질문 올리셨죠?
:
: 기본적으로는 TStringGrid * 에서는 안되기 때문에.. 답변을 못해드렸는데...
:
: 아래코드는 직접 코딩으로 구현한것입니다.
: MouseDown , MouseMove , MouseUp 이벤트를 이용했습니다.
:
: 급하게 만들어서 문제가 좀 있습니다.
:
: [문제들]
: 1. 스크롤바가 생겼을때 처리 ( 옆으로 옮긴 위치만큼 처리안됨)
: 2. Paint문제가 좀 있는것 같아요
: 3. Click할때 Cell이 선택되는 문제...
:
: 그대로 가져가셔서 붙인후 테스트 해보세요
:
: 위 몇가지 문제만 해결하면 쓸만할 겁니다. (특히 1번문제 반드시 처리해야함)
:
: 시간이 없어서 이만..
: 조만간 시간되면 위에 문제도 해결해서 올려드릴께요
:
: 그럼
:
:
:
:
: ==========<<샘플>>===========================================================
: TForm1 *Form1;
: //---------------------------------------------------------------------------
: __fastcall TForm1::TForm1(TComponent* Owner)
: : TForm(Owner)
: {
: }
: //---------------------------------------------------------------------------
: bool bSize;
: TPoint FsPoint,LaPoint;
: int iColNum;
: TColor clPenColor;
: TPenMode pmPenMode;
: void __fastcall TForm1::FormCreate(TObject *Sender)
: {
: //
: for(int r=0;r<sgrd->RowCount;r++)
: {
: for(int c=0;c<sgrd->RowCount;c++)
: {
: sgrd->Cells[r][c]=IntToStr(r)+" - "+IntToStr(c);
: }
: }
:
: pmPenMode=sgrd->Canvas->Pen->Mode;
: clPenColor=sgrd->Canvas->Pen->Color;
: sgrd->Options=sgrd->Options>>goColSizing;
: }
: //---------------------------------------------------------------------------
: int __fastcall IABS(int a ,int b)
: {
: if(a>b)return a-b;
: else b-a;
: }
: //---------------------------------------------------------------------------
: void __fastcall TForm1::sgrdMouseDown(TObject *Sender, TMouseButton Button,
: TShiftState Shift, int X, int Y)
: {
: if(sgrd->Cursor==crHSplit)
: {
: bSize=true;
: FsPoint.x=X;
: FsPoint.y=0;
: LaPoint.x=X;
: LaPoint.y=sgrd->RowCount*(sgrd->DefaultRowHeight+sgrd->GridLineWidth);
:
:
: sgrd->Canvas->Pen->Mode=pmNot;
: sgrd->Canvas->Pen->Color=clBlack;
: sgrd->Canvas->MoveTo(FsPoint.x,FsPoint.y);
: sgrd->Canvas->LineTo(LaPoint.x,LaPoint.y);
: sgrd->Canvas->Pen->Mode=pmPenMode;
: sgrd->Canvas->Pen->Color=clPenColor;
:
: }
: }
: //---------------------------------------------------------------------------
:
: void __fastcall TForm1::sgrdMouseMove(TObject *Sender, TShiftState Shift,
: int X, int Y)
: {
: if(bSize)
: {
: sgrd->Canvas->Pen->Mode=pmNot;
: sgrd->Canvas->Pen->Color=clBlack;
: sgrd->Canvas->MoveTo(FsPoint.x,FsPoint.y);
: sgrd->Canvas->LineTo(LaPoint.x,LaPoint.y);
:
: FsPoint.x=X;
: FsPoint.y=0;
: LaPoint.x=X;
: LaPoint.y=sgrd->RowCount*(sgrd->DefaultRowHeight+sgrd->GridLineWidth);
: sgrd->Canvas->MoveTo(FsPoint.x,FsPoint.y);
: sgrd->Canvas->LineTo(LaPoint.x,LaPoint.y);
: sgrd->Canvas->Pen->Mode=pmPenMode;
: sgrd->Canvas->Pen->Color=clPenColor;
: //enum TPenMode {pmBlack, pmWhite, pmNop, pmNot, pmCopy, pmNotCopy, pmMergePenNot, pmMaskPenNot, pmMergeNotPen, pmMaskNotPen, pmMerge, pmNotMerge, pmMask, pmNotMask, pmXor, pmNotXor};
:
:
: }
: else
: {
: if(!Shift.Contains(ssLeft))
: {
: int iX=0;
: for(int c=0;c<sgrd->RowCount;c++)
: {
: iX=iX+sgrd->ColWidths[c]+1;
: if(IABS(iX,X)<2)
: {
: sgrd->Cursor=crHSplit;
: iColNum=c;
: sgrd->Options>>goRangeSelect;
: return;
: }
: }
: }
: if(sgrd->Cursor==crHSplit)
: {
: sgrd->Cursor=crDefault;//
: sgrd->Options=sgrd->Options<<goRangeSelect;
: }
: }
:
: }
: //---------------------------------------------------------------------------
:
:
: void __fastcall TForm1::sgrdMouseUp(TObject *Sender, TMouseButton Button,
: TShiftState Shift, int X, int Y)
: {
:
: sgrd->Invalidate();
: sgrd->Canvas->Pen->Color=clWhite;
: if(bSize)
: {
: int iX=0;
: for(int c=0;c<iColNum;c++)
: {
: iX=iX+sgrd->ColWidths[c]+1;
: }
:
: sgrd->ColWidths[iColNum]=X-iX;
: }
: bSize=false;
: sgrd->Cursor=crDefault;
: sgrd->Options=sgrd->Options<<goRangeSelect;
:
: }
: //---------------------------------------------------------------------------
:
:
:
: 쥐르미온 님이 쓰신 글 :
: : 회섹으로 된 고정셀의 경우, 마우스를 셀의 경계선쪽으로 가져가면 열이나 너비를 수정할 수가 있게 되는데요. 일반 셀에서는 그것이 불가능합니다.
: :
: : 맨윗줄을 회색의 고정셀로 하지 않고도 너비 수정을 할 수 있었으면 좋겠는데요. 어떻게 해야하죠?
|