새우의 세상사

원문 링크 : [펌] MDI 폼에서 Client 영역에 배경 그리기 2

MDI 폼에서 Client 영역에 배경 그리기 2 - 더욱 쉽게

작성자 : 장성호  (nasilso)  읽음 : 415    2007-05-25 오전 1:57:59

================================================

MDI 폼의 메인 화면에 배경 이미지 그리기 - 여기는 직접 작성한 것임.

1, 메인 화면의 클래스에 다음과 같이 정의한다.

    TCanvas *MDICanvas;
   Graphics::TBitmap *imgBG;

2. 폼의 FormCreate 함수에 다음을 넣어 초기화한다.

void __fastcall TCMain::FormCreate(TObject *Sender)
{
    MDICanvas=new TCanvas;
    MDICanvas->Handle=GetDC(ClientHandle);
    imgBG = new Graphics::TBitmap;
    if (FileExists ("bgfile.bmp"))
        imgBG->LoadFromFile("bgfile.bmp");
}

3. 폼의 FormResize 함수에 다음과 같이 넣어준다.

void __fastcall TCMain::FormResize(TObject *Sender)
{
    MDICanvas->Draw(0, 0, imgBG);
}

4. 폼의 FormPaint 함수에 다음과 같이 넣어준다.

void __fastcall TCMain::FormPaint(TObject *Sender)
{
    MDICanvas->Draw(0, 0, imgBG);
} // 여기까지

================================================

여기 tip 게시판에 이미 같은 내용의 tip을 민병권님께서 올려놓은 것이 있습니다.

http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=357

위에 tip은 한가지가 문제가 있던데.. Form을 Resize할 때는 WM_ERASEBKGND 메세지가 발생하지 않아 잔상이 있거나 이상하게 되더군요

위 팁에 문제점을 보완하려면 그냥 Form의 Resize 이벤트에서 다시 한번 똑같이 그려주면 문제가 해결되더군요

----------------------------------------------------------------------------------

[쉬운방법]

그런데 위 팁에서 또하나 불편한것은 sub-classing을 해야한다는 것입니다.
뭐 서브클래싱이 그렇게 어렵고 복잡한것은 아니지만....

sub-classing 하지않고 하는 쉬운방법은 그냥 Form의 Repaint 이벤트와 Resize 이벤트에 배경을 그려주면 됩니다.

여기서 중요한 것은 Form의 Handle과 MDI Client의 Handle이 다르다는데 있습니다.
그러므로 그려져야할 HDC도 Form의 DC인 Canvas에 그려주는 것이 아니라 MDI Client의 HDC에 그려줘야 하는것입니다.


즉 아래와 같이 간단히 하면 됩니다.

문론 bmp에 배경 이미지가 들어있어야 하구요

//---------------------------------------------------------------------------

void __fastcall TDLG_MAIN::FormPaint(TObject *Sender)
{
        HDC DC=GetDC(ClientHandle);
       BitBlt(DC,0,0,bmp->Width,bmp->Height,bmp->Canvas->Handle ,0,0,SRCCOPY    );
       //StretchBlt(DC, 0, 0, Width, Height, bmp->Canvas->Handle, 0, 0, bmp->Width, bmp->Height, SRCCOPY);
}

//---------------------------------------------------------------------------

void __fastcall TDLG_MAIN::FormResize(TObject *Sender)
{
        HDC DC=GetDC(ClientHandle);
       BitBlt(DC,0,0,bmp->Width,bmp->Height,bmp->Canvas->Handle ,0,0,SRCCOPY    );
       //StretchBlt(DC, 0, 0, Width, Height, bmp->Canvas->Handle, 0, 0, bmp->Width, bmp->Height, SRCCOPY);

}

//---------------------------------------------------------------------------

[응용 방법]

이를 좀더 응용하여서 하는 쉬운 방법이 있는데요

VCL의 Canvas를 이용하는 방법입니다.

여기 tip에 보면 김태선님의 "바탕화면을 TCanvas로 만들어 주는 클래스"라는 것을 응용한 것으로 http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=551 TCanvas를 하나 new 하시고 그 canvas의 HDC를 MDI Clinet 영역의 HDC로 설정해주면 됩니다
그러면 아래와 같이 Paint 나 Resize 이벤트때 코딩이 더 짧아질 수 있습니다.

TCanvas *MDICanvas;

void __fastcall TDLG_MAIN::FormCreate(TObject *Sender)
{
       MDICanvas=new TCanvas;
       MDICanvas->Handle=GetDC(ClientHandle);
}

//---------------------------------------------------------------------------

void __fastcall TDLG_MAIN::FormPaint(TObject *Sender)
{
        MDICanvas->Draw(0,0,bm_bg);
}

//---------------------------------------------------------------------------

void __fastcall TDLG_MAIN::FormResize(TObject *Sender)
{
      MDICanvas->Draw(0,0,bm_bg);
}

//---------------------------------------------------------------------------

그리고 또 이렇게 Client영역에 Canvas로 접근할 수 있으므로 아래와 같이 쉽게 원하는 내용을 client 영역에 그릴수 있습니다.

void __fastcall TDLG_MAIN::FormPaint(TObject *Sender)
{
        MDICanvas->Draw(0,0,bm_bg);
        MDICanvas->Brush->Color=clRed;
        MDICanvas->Pen->Color=clWhite;
        MDICanvas->Rectangle(Rect(100,100,200,300));

}

//---------------------------------------------------------------------------

요즘에 MDI로 프로그램하는경우가  많이 없는것 같기는 한데 혹 누군가 필요하실 수도 있을것 같아서 올려봅니다.

Posted by 새우날다 Trackback 2 Comment 0

댓글을 달아 주세요

원문 링크 : [펌] C++ Builder에서 MDI 메인화면에 배경 그리기


MDI폼에 Bitmap 이미지 넣기.

작성자 : 민병권  (minbk)  읽음 : 1204    2002-08-14 오후 5:37:22

MDI폼 배경에 bmp 이미지 화일을 표시하는 방법입니다.

cpp-faq자료를 뒤지다보니 방법이 있네요.

Modal폼, MdiChild폼 등을 더 뛰워도 전혀 이상 없습니다.
아주 간단합니다.

먼저, MDI폼 위에 TImage를 하나 올려놓고, 여기에 Picture 속성에 표시 하고자하는 그림을 하나 선택합니다(확장자가 bmp인 것만 되네요. 다른것도 될려나?......).

그런다음 소스를 아래와 같이 하세요.

1. MDI폼의 헤더화일에 다음을 추가하세요.

    TFarProc MdiInstance;
    TFarProc OldMdiWindowProc;
    void __fastcall MdiWndProc(TMessage &Message);

2. MDI폼 소스 부분에 다음을 추가하세요.

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)        // <-- 폼 생성시 자동으로 만들어지죠..
//---------------------------------------------------------------------------
{
    // 아래의 3줄 추가.
    MdiInstance = MakeObjectInstance(MdiWndProc);
    OldMdiWindowProc = (void *)(GetWindowLong(ClientHandle, GWL_WNDPROC));
    SetWindowLong(ClientHandle, GWL_WNDPROC, (LONG)(MdiInstance));
}

//---------------------------------------------------------------------------
// 임의로 새로 만든 함수입니다.
void __fastcall TForm1::MdiWndProc(TMessage &Message)
//---------------------------------------------------------------------------
{
    if (Message.Msg == WM_ERASEBKGND){
        Message.Result = 0;
        HDC DC = (HDC)Message.WParam;
        StretchBlt(DC, 0, 0, Width, Height,
        Image1->Canvas->Handle, 0, 0,
        Image1->Picture->Bitmap->Width,
        Image1->Picture->Bitmap->Height,
        SRCCOPY);
    }
    else Message.Result = CallWindowProc((FARPROC)OldMdiWindowProc,

    ClientHandle, Message.Msg,
    Message.WParam, Message.LParam);
}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
//---------------------------------------------------------------------------
{
    SetWindowLong(ClientHandle, GWL_WNDPROC,
    (LONG)OldMdiWindowProc);
    FreeObjectInstance(MdiInstance);

    Action = caFree;
}

끝. 아주 간단하죠?


김유미
이거 하니까 실행 프로그램 아래의 배경이 그림으로 따라 다니네요...  2004/01/27 21:27

민병권
Form의 Scaled 속성을 False로 변경 하세요.
예전에 Win98에 Builder 5.0으로 테스트 했을때는 Scaled 속성에 관계없이 잘 됐는데,
지금은 Win2000에 Builder 6.0으로, Form을 MDIForm으로 만 하면 투명폼이 되어 버리네요.

Posted by 새우날다 Trackback 0 Comment 0

댓글을 달아 주세요