VCL에서는 디자인타임과 런타임때 동작이 좀 다릅니다.
어떻게 동작하는지는 저도 정확히는 알지못하니 나중에 좀더 연구해서 ...
[런타임에 컨트롤 Resize 및 Move]
일단 런타임때 디자인타임때처럼 컨트롤의 위치를 움직이려면
팁 게시판의 임프님이 올린 방법으로 하던지..
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=47
지난번 linuxman 질문에 제가 답변드린 WM_NCHITTEST 를 이용한 방식으로 하면 될듯 합니다.
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_qna&no=54591
[런타임에 컨트롤 가장자리에 사각형 표시]
( 빌더나 델파이 개발툴에서 어떻게 하는지는 나중에 설명하구요 - 아직 정확히 몰라서..)
사각형이 생기는것은 그려주는 방법 말고 뾰족한 방법이 있겠습니까?
그런데 조그만한 사각형을 자세히 보면
사각형이 폼과 자신(컨트롤)과 혹은 또다른 컨트롤에 걸쳐서 그려져 있습니다.
일반 윈도우 dc에 그림을 그릴때는 자신과 다른윈도우 dc에 한번에 그릴수 없습니다.
한번에 그리는 방법은 Desktop DC에 그려야죠 - 핵심1
그리고 컨트롤이 폼이나 Parnet컨트롤 영역안에만 표시되기때문에 Parent영역 밖에는
그려지지 않죠 - 주의1
그리기는?
1. Paint 때 ..
원래 컨트롤 모양 그려주고
2. 사각형을 그립니다.
3. 사각형을 그리는 DC는 데스트톱의 dc이므로 GetDC(0) 로 구해서 그려야 겠죠 - 핵심1
4. 컨트롤이 Parent 영역 안에 만 있어야 하므로 각 박스의 위치가 Parent영역 인지 확인해 보구 그립니다.
PtInRect 등을 이용하여...
[샘플]
아래는 샘플입니다.
깔끔하지는 않습니다. TPanel을 교체신으로 구현했습니다.
// header파일에서 TForm1 class선언 보다 앞쪽에 Panel클래스를 선언합니다.
class TPanel: public Extctrls::TPanel
{
private:
TCanvas *DeskCanvas;
bool bDesign,bNoSize;
public:
__fastcall virtual TPanel(TComponent* Owner)
: Extctrls::TPanel(Owner)
{
bDesign=true;
bNoSize=true;
DeskCanvas=new TCanvas;
DeskCanvas->Handle=GetDC(0);
DeskCanvas->Brush->Color=clBlack;
DeskCanvas->Pen->Color=clBlack;
}
__fastcall virtual ~TPanel()
{
ReleaseDC(0,DeskCanvas->Handle);
delete DeskCanvas;
}
virtual void __fastcall Paint(void);
void __fastcall WMSysCommand(TMessage &Msg);
void __fastcall WMNCHITTEST(TMessage &Msg);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_SYSCOMMAND,TMessage,WMSysCommand);
MESSAGE_HANDLER(WM_NCHITTEST,TMessage,WMNCHITTEST);
END_MESSAGE_MAP(Extctrls::TPanel);
};
#define TPanel ::TPanel
class TForm1 : public TForm
{
...
};
그리고 WM_PAINT , WM_NCHITTEST , WM_SYSCOMMAND 에 대해 CPP에서 구현한 내용입니다.
TControl *DesignControl;
void __fastcall TPanel::Paint(void)
{
inherited::Paint();
if(bDesign && bNoSize && this->Parent && DesignControl==this)
{
TPoint pt=Point(0,0);
pt=this->ClientToScreen(pt);
TRect rcP;
TPoint ptP=Parent->ClientToScreen(Point(0,0));
rcP=Rect(ptP.x-2,ptP.y-2,ptP.x+Parent->Width-2,ptP.y+Parent->Height-2);
if(PtInRect(rcP,pt)) //상-좌
DeskCanvas->Rectangle(Rect(pt.x-2,pt.y-2,pt.x+2,pt.y+2));
if(PtInRect(rcP,Point(pt.x+Width/2,pt.y))) //상-가운데
DeskCanvas->Rectangle(Rect(pt.x-2+Width/2,pt.y-2,pt.x+2+Width/2,pt.y+2));
if(PtInRect(rcP,Point(pt.x+Width,pt.y))) //상-우
DeskCanvas->Rectangle(Rect(pt.x-2+Width,pt.y-2,pt.x+2+Width,pt.y+2));
if(PtInRect(rcP,Point(pt.x,pt.y+Height/2))) //중-좌
DeskCanvas->Rectangle(Rect(pt.x-2,pt.y-2+Height/2,pt.x+2,pt.y+2+Height/2));
if(PtInRect(rcP,Point(pt.x+Width,pt.y+Height/2))) //중-우
DeskCanvas->Rectangle(Rect(pt.x-2+Width,pt.y-2+Height/2,pt.x+2+Width,pt.y+2+Height/2));
if(PtInRect(rcP,Point(pt.x,pt.y+Height))) //하-좌
DeskCanvas->Rectangle(Rect(pt.x-2,pt.y-2+Height,pt.x+2,pt.y+2+Height));
if(PtInRect(rcP,Point(pt.x+Width/2,pt.y+Height))) //하-가운데
DeskCanvas->Rectangle(Rect(pt.x-2+Width/2,pt.y-2+Height,pt.x+2+Width/2,pt.y+2+Height));
if(PtInRect(rcP,Point(pt.x+Width,pt.y+Height))) //하-우
DeskCanvas->Rectangle(Rect(pt.x-2+Width,pt.y-2+Height,pt.x+2+Width,pt.y+2+Height));
}
}
void __fastcall TPanel::WMSysCommand(TMessage &Msg)
{
bNoSize=false;
if(DesignControl && DesignControl!=this)
DesignControl->Repaint();
if(this->Parent) Parent->Repaint();
this->Repaint();
DesignControl=this;
DefaultHandler(&Msg);
bNoSize=true;
Repaint();
}
void __fastcall TPanel::WMNCHITTEST(TMessage &Msg)
{
TPoint MousePos;
if(bDesign)
{
MousePos = Point(Msg.LParam & 0xFFFF, (Msg.LParam >> 16) & 0xFFFF);
MousePos = this->ScreenToClient(MousePos);
if (MousePos.x <= 2) Msg.Result = HTLEFT;
if (Width - 2 <= MousePos.x) Msg.Result = HTRIGHT;
if (Height - 2 <= MousePos.y) Msg.Result = HTBOTTOM;
if (MousePos.y <= 2) Msg.Result = HTTOP;
if ((MousePos.x <= 4) && (MousePos.y <= 4)) Msg.Result = HTTOPLEFT;
if ((MousePos.x <= 4) && (Height - 4 <= MousePos.y)) Msg.Result = HTBOTTOMLEFT;
if ((Width - 4 <= MousePos.x) && (MousePos.y <= 4)) Msg.Result = HTTOPRIGHT;
if ((Width - 4 <= MousePos.x) && (Height - 4 <= MousePos.y)) Msg.Result = HTBOTTOMRIGHT;
if ((Msg.ResultHTBOTTOMRIGHT))
{
Msg.Result=HTCAPTION;
}
}
else
{
DefaultHandler(&Msg);
}
}
깔끔하지 못한 부분이 있는데..
다른 컨트롤하고 겹쳐 졌을때 사각형의 흔적이 남거나 하는 부분이 좀 문제가 있습니다.
미흡한 부분은 직접 수정해 보세요
델마당이나 한델에 찾아보면 관련 샘플이 좀 있는것으로 알고 있습니다.
(민성기님과 양병규님이 만든 샘플은 본적이 있는듯)
그럼..
linuxman 님이 쓰신 글 :
: 안녕하세요..
:
: 폼디자인시에 컨트롤을 폼위에 놓으면... 사이즈를 조정할수 있도록 상하,좌우 에 조그만 사각형
: 박스 생기잖아요... 그건 어떤 원리로 만드는것인가요?
:
: 저는 일종의 편집기 같은기능으로써,
: 제가 폼디자인시에 올려놓은 이미지나,라벨들을 선택하면, 선택되었다는 표시로 위에서 말한
: 조그만 사각형들을 컨트롤 주위에 표시하고, 폼디자인에서 처럼 마우스로 드래그하면 사이즈
: 조절이 가능한 그런 기능을 만들고 싶은데...원리를 알고 싶습니다..
:
: 아니면..그런 기능을 제공하는 콤포넌트가 있는지 (상용이라도 )? 궁금합니다.
:
:
: 수고하세요.