void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, LONG xStart, LONG yStart, COLORREF cTransparentColor)
{
BITMAP bm;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
POINT ptSize;
/* 초기화 작업 */
hdcTemp = CreateCompatibleDC(hdc);
SelectObject(hdcTemp, hBitmap); // 비트맵 선택
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
ptSize.x = bm.bmWidth; // 비트맵 가로 크기
ptSize.y = bm.bmHeight; // 비트맵 세로 크기
DPtoLP(hdcTemp, &ptSize, 1); // 디바이스를 논리적 위치로 변경
// 작업용 DC 생성
hdcBack = CreateCompatibleDC(hdc);
hdcObject = CreateCompatibleDC(hdc);
hdcMem = CreateCompatibleDC(hdc);
hdcSave = CreateCompatibleDC(hdc);
// 흑백 연산 (and,or연산)에 필요한 비트맵 생성
bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
// 작업용 비트맵들 생성
bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
// 각 비트맵 삭제 위한 old 비트맵 생성
bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack);
bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem);
bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave);
//그려질 DC와 생성된 임시DC의 맵핑 모드 일치화
SetMapMode(hdcTemp, GetMapMode(hdc));
// 원본 보전 작업
BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
// 투명화 시킬 색을 Tempdc의 배경색으로 설정,
// 이때 SetBkColor의 리턴 값으로 원본 색 저장
cColor = SetBkColor(hdcTemp, cTransparentColor);
/* 주어진 비트맵의 투명색(BkColor로 지정된)은 힌색으로,
나머지는 검은색으로하여 BlackWhitedc_1에 저장 */
BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
SRCCOPY);
// 배경 색을 원본 색상 DC를 가져오기
SetBkColor(hdcTemp, cColor);
// BlackWhitedc_1를 이용 투명 영역(검은색), 비투명 영역(힌색)으로 된 DC생성
BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);
// 그려질 hdc에서 비트맵이 위치할 곳의 배경을 작업용 DC로 이동
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, SRCCOPY);
//BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, 0, 0, SRCCOPY);
// 그려질 배경과 and 연산을 통해 배경투명구현(힌색 소멸), 비투명 영역은 검은 색으로
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
// 주어진 비트맵과 and 연산을 통해 투명부분(검은색으로), 비투명은 그대로
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
// 위에서 만든 2개의 DC(Workdc, Tempdc)의 or 연산을 통해 두 DC결합
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
// 결과를 표시
BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY);
// 원본을 임시 DC에 복구
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
// 메모리에 있는 각 비트맵 삭제
DeleteObject(SelectObject(hdcBack, bmAndBack));
DeleteObject(SelectObject(hdcObject,bmAndObject));
DeleteObject(SelectObject(hdcMem, bmAndMem));
DeleteObject(SelectObject(hdcSave, bmSave));
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject,bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcSave, bmSaveOld));
// 각 DC삭제
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcMem);
DeleteDC(hdcSave);
DeleteDC(hdcTemp);
DeleteDC(hdc); // 자신의 DC를 삭제하지 않으면 GDI 객체는 계속 늘어나게 된다..
}
/// 사용 예시..
DrawTransparentBitmap(::GetDC(((CStatic*)GetDlgItem(컨트롤))->GetSafeHwnd()), (BMP), 0, 0, 색상);
// 미리 정의해 놓고 사용하면 좀더 편리함...
#define TRANS_BITMAP(CTRL, BMP); DrawTransparentBitmap(::GetDC(((CStatic*)GetDlgItem(CTRL))->GetSafeHwnd()), (BMP), 0, 0, BLACK);
'1.소프트웨어 이야기 > 01.MFC(Visual Studio)' 카테고리의 다른 글
SetWindow와 MoveWindow 사용시 유의점 (0) | 2009.11.25 |
---|---|
대화 상자 및 Windows 팁 모음 (0) | 2009.11.18 |
Window Messages Define (0) | 2009.08.04 |