콤보박스를 투명하게 만들일이야 없겠지만, 한번 도전해봤습니다.
하지만 불완전한 구현이 되고 말았습니다.
리스트박스가 보일경우 리스트의 스크롤바 무브 이벤트를 처리하지 못하겠더군요.. -_-;

스크롤바를 드래그해서 움직일 경우 잔상이 남습니다.

[요 부분에 대한 아이디어가 있으신 분은.. 메시지좀 남겨주시와요 ^^]

기본적인 아이디어:
리스트 박스가 그려질 영역만큼, 보여지기 전에 미리 화면을 캡처 해놓은 다음에..
드롭된 리스트의 배경에 캡처된 화면을 그려주면 투명한 것처럼 보일 것이다.


//
윈도우 화면에서 주어진 사격형 만큼을 캡처해서 비트맵으로 넘겨준다.
//
저 콤보박스의 리스트 영역의 배경을 직접 그려주어 투명한것 처럼 보여주는
//
꽁수를 쓰기 위해서 필요한 함수.

BOOL Capture(CRect rc, CBitmap& m_Bitmap)
{
    //
화면 사이즈를 읽어온다.
    int cx = GetSystemMetrics(SM_CXSCREEN);
    int cy = GetSystemMetrics(SM_CYSCREEN);
   
    //
스크린 캡처를 위한 DC를 맹근다.
    CDC ScreenDC;
    ScreenDC.CreateDC("DISPLAY", NULL, NULL, NULL);
   
    //
비트맵을 로딩할 임시 DC를 만든다.
    CDC memDC;
    memDC.CreateCompatibleDC(&ScreenDC);
   
    //
비트맵이 살아있으면, 살짝 날려준다.
    if(m_Bitmap.m_hObject)
        m_Bitmap.DeleteObject();

    //
스크린 호환용 비트맵을 주어진 크기만큼 만든다.
    m_Bitmap.CreateCompatibleBitmap(&ScreenDC, rc.Width(), rc.Height());
   
    //
비트맵에 캡처된 화면을 그린다.
    memDC.SelectObject(&m_Bitmap);
    memDC.BitBlt(0,0,rc.Width(), rc.Height(),&ScreenDC,rc.left,rc.top, SRCCOPY);
   
    return TRUE;
}

 

HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
    switch(nCtlColor)
    {
    case CTLCOLOR_STATIC:
    case CTLCOLOR_EDIT:
            pDC->SetTextColor(RGB(0, 0, 255));
            pDC->SetBkMode(TRANSPARENT);
            return (HBRUSH)GetStockObject(NULL_BRUSH);
    case CTLCOLOR_LISTBOX:
        {
            pDC->SetTextColor(RGB(255, 0, 0));
            pDC->SetBkMode(TRANSPARENT);

             // 리스트 영역의 크기를 구한다.
            CRect rc;
            pWnd->GetClientRect(rc);

            //
임시 DC를 하나 만든다.
            CDC mdc;
            mdc.CreateCompatibleDC(pDC);
            mdc.SelectObject(&m_bmp);

            //
아까 캡처해두었던 배경을 리스트의 바탕에 그려준다.
            pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &mdc, 0, 0, SRCCOPY);
            return (HBRUSH)GetStockObject(NULL_BRUSH);
        }
    }

  return hbr;
}

BOOL CSssDlg::PreTranslateMessage(MSG* pMsg)
{
    if(m_combo2.GetDroppedState())
    {
        //
리스트가 보여지고 있을 때 마우스 무브 이벤트시 리스트를 갱신해준다.
        if(pMsg->message == WM_MOUSEMOVE && ::GetDlgCtrlID(pMsg->hwnd) == 1000)
            CWnd::FromHandle(pMsg->hwnd)->Invalidate();
    }

  return CDialog::PreTranslateMessage(pMsg);
}

 

// 콤보박스의 리스트가 드롭될 때 발생하는 이벤트.
void CSssDlg::OnDropdownCombo2()
{
    //
현재 콤보박스의 위치를 읽어온 후..
    CRect rc;
    m_combo2.GetWindowRect(rc);

    //
대략 오프셑을 넣은 후, 드롭된 리스트의 크기를 예상하여 넣는다.
    //
실제 드롭이 되기 전까지는 크기를 알수 없어, 적당하게 높이를 200으로 주었다.
    //
만든 사람은 본인이 높이를 아니, 적당하게 값을 주면 된다.

    rc.left += 1;
    rc.top = rc.bottom+1;
    rc.bottom += 200;

     Capture(rc, m_bmp);
}

원하는 만큼 깔끔한 코드가 나오지는 못했지만, 드롭리스트에 스크롤바만 않생기면..
그럭저럭 설렁 설렁 넘어갈만 하다고.. 생각만 해봅니다. ㅜㅜ

105.zip
0.03MB

 



스태틱 컨트롤중에 Text 기능을 이용하여 배경을 투명하게 만드는 것은 에디트 컨트롤에 비하여
훨씬 쉽다.

위의 샘플이 컨트롤의 배경을 투명하게 만든것인데..

우선 글자가 써진 컨트롤의 아이디를  IDC_STATIC_1 이라고 변경한 후..
코드를 다음과 같이 변경하면 끝이다.

HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
   
    switch(nCtlColor)
    {
    case CTLCOLOR_STATIC:
        {
            if(pWnd->GetDlgCtrlID() == IDC_STATIC_1)
            {
                pDC->SetTextColor(RGB(255, 0, 0));
                pDC->SetBkMode(TRANSPARENT);
                return (HBRUSH)GetStockObject(NULL_BRUSH);;
            }
        }
    }
    // TODO: Return a different brush if the default is not desired
    return hbr;  
}

25.zip
0.04MB

에디트 컨트롤의 배경을 투명하게 만드는 건 쉬운일이 아니다..

www.codeguru.com(이하 그루)이나 www.codeproject.com (이하 플젝)에 찾아보면..
그나마 플젝 사이트에나 쓸만한거 하나 건질 수 있다.

버뜨... 에디트 컨트롤 배경하나 투명하게 만들자고.. 클래스 나부랭이를 자꾸 추가하는건..
전혀 입맞에 맞는일이 못된다.
작업하다 보면 늘어나는 클래스에 골머리 뽀사지고, 이기능 넣느라 이 클래스 추가하고
저 기능 넣느라 저거 추가하고.. ㅜㅜ

그냥 다얄로그에 몇줄 추가해서 해결할 방법이 있을까? 당연히 있다.. ㅎㅎ
좀 귀찬긴 하지만 원하는 기능을 만드는 즐거움을 어떤것에 비할까..

이전의 샘플 sample2.zip 프로젝트를 조금 변화 시켜보았다.
배경에 그림을 하나 깔고.. 에디트를 올려서 처리하는 것이다.



이전의 IDC_EDIT9 에디트가 글자가 빨강 색으로 나오는걸 타겟으로 잡았다.

다아일로그에서 클래스 위저드를 띄운 후..
1. PreTranslateMessage 이벤트 핸들러를 추가한다.
2. Object IDs: IDC_EDIT9를 선택하고 EN_CHANGE 이벤트 핸들러를 추가한다.

그리고 코드를 다음과 같이 수정한다.

HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
   
    switch(nCtlColor)
    {
    case CTLCOLOR_EDIT:
        {
            if(pWnd->GetDlgCtrlID() == IDC_EDIT9)
            {
                pDC->SetTextColor(RGB(255, 0, 0));
               

                pDC->SetBkMode(TRANSPARENT);
                pDC->SelectStockObject(NULL_BRUSH);
                return NULL;

            }
        }
    }
   
    // TODO: Return a different brush if the default is not desired
    return hbr;
}

BOOL CSssDlg::PreTranslateMessage(MSG* pMsg)
{
   

if(::GetDlgCtrlID(pMsg->hwnd) == IDC_EDIT9)
    {
        // 에디트 컨트롤 IDC_EDIT9 번의 이벤트 중에서 아래 이벤트가 발생하면
        // 에디트 컨트롤 영역만큼 부모 윈도우의 화면을 갱신한다.

        switch(pMsg->message)
        {
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_KILLFOCUS:
            {
                CRect rc;
                CWnd* pWnd = GetDlgItem(IDC_EDIT9);
                pWnd->GetWindowRect(rc);
                ScreenToClient(rc);
                InvalidateRect(rc);
            }
        }
    }

   
    return CDialog::PreTranslateMessage(pMsg);
}

// 이 것을 PreTranslateMessage 에서 처리하지 못하는 이유는
// 이벤트를 잡을 수 없기 때문이다.
// 이 전체 기능을 CEdit서브클래싱하여 구현하여 놓은 것이 플젝사이트의 샘플이라고 봐도 무방하다.


void CSssDlg::OnChangeEdit9()
{

    // 에디트 컨트롤에서 글자에 변화가 생기면.
    // 에디트 컨트롤 영역만큼 부모 윈도우의 화면을 갱신한다.

   

    CRect rc;
    CWnd* pWnd = GetDlgItem(IDC_EDIT9);
    pWnd->GetWindowRect(rc);
    ScreenToClient(rc);
    InvalidateRect(rc);

}


샘플을 실행하면 화면이 좀 구리지만.. 참고하는데는 문제 없다 -_-;;;

18.zip
0.04MB

+ Recent posts