음..
이번에는 질문을 제대로 이해했길 기대합니다.
아래 박지훈.임프 님께서 올려주신 팁을 참조하신거죠?
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=47
위 팁에 소개된 방법으로 런타임에 control을 resize하려는데
Panel 은 되는데 TMemo나 TEdit의 경우 잘 안된다는 거죠?
TPanel과 TMemo,TEdit의 공통된 속성중에 차이점을 살펴보면
Default로 생성될때 BorderStyle이 다릅니다.
Panel의 경우 BorderStyle이 bsNone 이구
TMemo 나 TEdit의 경우 BorderStyle이 bsSingle 입니다.
즉 Panel은 되는데 TMemo는 잘 안되는것은 BorderStyle이 다르기 때문입니다.
그러므로 Panel 도 BorderStyle을 bsSingle로 바꾸면 잘안되고
TMemo나 TEdit도 BorderStyle을 bsNone로 바꾸면 잘 됩니다.
그런데 TMemo나 TEdit의 BorderStyle을 bsNone로 바꾸면 모양이 이상하게 나오죠?
왜그런가하면 BorderStyle을 bsSingle로 두면 Control의 가장자리에 Border영역이 생기는데
이 영역에서는 MouseMove이벤트가 발생하지 않기 때문입니다.
Border영역 안으로 들어와서 발생하는 이벤트는 이미 re-size 마우스 위치를 벗어났을 때죠
방법1.
Border영역 신경쓰지 않고 가능하게 하려면
Control의 Width와 Height 대신 ClientWidth 와 ClientHeight로 바꾸시면 됩니다.
( MouseMove이벤트는 Control의 Client영역을 기준으로 발생하기 때문입니다.)
void __fastcall TForm1::Memo2MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
TWinControl *SenderControl = dynamic_cast(Sender);
int SysCommWparam;
if(X < 4 && Y < 4)
SysCommWparam = SC_DRAG_RESIZEUL;
else if(X > SenderControl->ClientWidth-4 && Y > SenderControl->ClientHeight-4)
SysCommWparam = SC_DRAG_RESIZEDR;
else if(X < 4 && Y > SenderControl->ClientHeight-4)
SysCommWparam = SC_DRAG_RESIZEDL;
else if(X > SenderControl->ClientWidth-4 && Y < 4)
SysCommWparam = SC_DRAG_RESIZEUR;
else if(X < 4)
SysCommWparam = SC_DRAG_RESIZEL;
else if(X > SenderControl->ClientWidth-4)
SysCommWparam = SC_DRAG_RESIZER;
else if(Y < 4)
SysCommWparam = SC_DRAG_RESIZEU;
else if(Y > SenderControl->ClientHeight-4)
SysCommWparam = SC_DRAG_RESIZED;
else
SysCommWparam = SC_DRAG_MOVE;
ReleaseCapture();
SendMessage(SenderControl->Handle, WM_SYSCOMMAND, SysCommWparam, 0);
}
void __fastcall TForm1::Memo2MouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
TControl *SenderControl = dynamic_cast(Sender);
if((X < 4 && Y < 4) || (X > SenderControl->ClientWidth-4 && Y > SenderControl->
ClientHeight-4))
SenderControl->Cursor = crSizeNWSE;
else if((X < 4 && Y > SenderControl->ClientHeight-4) || (X > SenderControl->
ClientWidth-4 && Y < 4))
SenderControl->Cursor = crSizeNESW;
else if(X < 4 || X > SenderControl->ClientWidth-4)
SenderControl->Cursor = crSizeWE;
else if(Y < 4 || Y > SenderControl->ClientHeight-4)
SenderControl->Cursor = crSizeNS;
else
SenderControl->Cursor = crDefault;
}
방법2.
그런데 위 방식에 한가지 깔끔하지 못한것이 하나있으니
컨트롤의 BorderStyle이 bsSingle 이고
Mouse가 Border영역에서 움직일때는 여전히 적용이 안된다는것입니다.
그럼 BorderStyle이 bsSingle일때 Mouse가 Border영역에서 움직일때
발생하는 메세지를 이용하면 가능하지 않을까요?
그것은 WM_NCHITTEST 메세지를 이용하시면 됩니다.
TWndMethod OrgPanelProc;
void __fastcall TForm1::FormCreate(TObject *Sender)
{
OrgPanelProc=Panel5->WindowProc;
Panel5->WindowProc=PanelProc;
}
//-------------------------------------------------
void __fastcall TForm1::PanelProc(TMessage &Msg)
{
if(Msg.Msg==WM_NCHITTEST)
{
TPoint MousePos=Point(Msg.LParamLo,Msg.LParamHi);
MousePos=Panel5->ScreenToClient(MousePos);
if (MousePos.x <= 4) Msg.Result = HTLEFT;
if (Panel5->Width - 4 <= MousePos.x) Msg.Result = HTRIGHT;
if (Panel5->Height - 4 <= MousePos.y) Msg.Result = HTBOTTOM;
if (MousePos.y <= 4) Msg.Result = HTTOP;
if ((MousePos.x <= 7) && (MousePos.y <= 7)) Msg.Result = HTTOPLEFT;
if ((MousePos.x <= 7) && (Panel5->Height - 7 <= MousePos.y)) Msg.Result = HTBOTTOMLEFT;
if ((Panel5->Width - 7 <= MousePos.x) && (MousePos.y <= 7)) Msg.Result = HTTOPRIGHT;
if ((Panel5->Width - 7 <= MousePos.x) && (Panel5->Height - 7 <= MousePos.y)) Msg.Result = HTBOTTOMRIGHT;
if ((Msg.ResultHTBOTTOMRIGHT) )
OrgPanelProc(Msg);
return;
}
OrgPanelProc(Msg);
}
생각건데 방법2를 좀더 보완해서 하는 방향을 추천합니다.
그럼..
linuxman 님이 쓰신 글 :
: 안녕하세요..
:
: 팁에 있는 패널에 대한 콤포넌트 사이즈 변경에 대한것을 보고...(마우스 커서를 이용한 )
: 그것을 그대로 메모장이나,editbox에 적용하려고 해보니, 패널은 상하,좌우 모두 마우스 잘 동작됩니다.
: 그런데.. 메모장이나 editbox는 왼쪽과 윘쪽은 잘 동작하는데...
:
: 오른쪽과 아랫쪽은 마우스가 잘 인지 못하는것 같습니다... 모두 TControl을 상속 받아서, 패널과 틀릴것이 없다고 생각이 되는데... 왜 이런 차이가 생기는건가요?
:
:
: void __fastcall TForm1::Panel1MouseDown(TObject *Sender,
: TMouseButton Button, TShiftState Shift, int X, int Y)
: {
:
:
: TControl *SenderControl = dynamic_cast<TControl *>(Sender);
: int SysCommWparam;
:
: if(X < 4 && Y < 4)
: SysCommWparam = SC_DRAG_RESIZEUL;
: else if(X > SenderControl->Width-4 && Y > SenderControl->Height-4)
: SysCommWparam = SC_DRAG_RESIZEDR;
: else if(X < 4 && Y > SenderControl->Height-4)
: SysCommWparam = SC_DRAG_RESIZEDL;
: else if(X > SenderControl->Width-4 && Y < 4)
: SysCommWparam = SC_DRAG_RESIZEUR;
: else if(X < 4)
: SysCommWparam = SC_DRAG_RESIZEL;
: else if(X > SenderControl->Width-4)
: SysCommWparam = SC_DRAG_RESIZER;
: else if(Y < 4)
: SysCommWparam = SC_DRAG_RESIZEU;
: else if(Y > SenderControl->Height-4)
: SysCommWparam = SC_DRAG_RESIZED;
: else
: SysCommWparam = SC_DRAG_MOVE;
:
: ReleaseCapture();
: SendMessage(Panel1->Handle, WM_SYSCOMMAND, SysCommWparam, 0);
:
: }
: //---------------------------------------------------------------------------
: void __fastcall TForm1::Panel1MouseMove(TObject *Sender, TShiftState Shift,
: int X, int Y)
: {
:
: TControl *SenderControl = dynamic_cast<TControl *>(Sender);
: if((X < 4 && Y < 4) || (X > SenderControl->Width-4 && Y > SenderControl->
: Height-4))
: SenderControl->Cursor = crSizeNWSE;
: else if((X < 4 && Y > SenderControl->Height-4) || (X > SenderControl->
: Width-4 && Y < 4))
: SenderControl->Cursor = crSizeNESW;
: else if(X < 4 || X > SenderControl->Width-4)
: SenderControl->Cursor = crSizeWE;
: else if(Y < 4 || Y > SenderControl->Height-4)
: SenderControl->Cursor = crSizeNS;
: else
: SenderControl->Cursor = crDefault;
: }