윈도우를 투명하게 만들기 [Bottom] [Top]
가끔 윈도우를 투명하게 하고 싶을 때가 있는데, 이렇게 윈도우 전체를 투명하게 하는 방법이 있다. 이 방법은 윈도우가 WS_CHILD 속성을 가지고 있을 경우에는 효과가 나타나지 않는다. 즉 어떤 윈도우의 자식인 이부분의 윈도우를 투명하게는 못한다. 윈도우의 하위 윈도우를 투명하게 할때는 직접 그려주는 방법밖에는 없는듯하다. Win32 로는 AlphaBlend 함수를 이용하면 되고, GDI+ 를 이용하면 더 간단하게 투명하게 그릴 수가 있다. (Win2000 이상)
아래는 간단하게 윈도우 전체를 투명하게 하는 방법이다. SetLayeredWindowAttributes 함수를 이용해서 동작하는 간단한 효과이다.
1 // 데이터형 / 상수 선언 2 typedef BOOL (WINAPI * SLWA)(HWND hWnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags); 3 4 #define LWA_ALPHA 0x00000002 5 6 7 //------------------------------------------------------------------------------ 8 // 함수 코드 9 BOOL SetWindowTransparent( HWND hWnd, BYTE nAlpha ) 10 { 11 if( FALSE == ::IsWindow( hWnd ) ) 12 { 13 return FALSE; 14 } 15 16 // 투명윈도우를 위한 LayeredWindow 설정 17 LONG lOldWinStyle = GetWindowLong( hWnd, GWL_STYLE ); 18 ::SetWindowLong( hWnd, GWL_STYLE, 19 lOldWinStyle & WS_POPUPWINDOW & ~WS_BORDER ); 20 21 LONG lStyle = ::GetWindowLong( hWnd, GWL_EXSTYLE ); 22 if( !( lStyle & 0x00080000 ) ) 23 { 24 ::SetWindowLong( hWnd, GWL_EXSTYLE, lStyle | 0x00080000 ); 25 } 26 27 BYTE chAlpha = nAlpha; 28 HINSTANCE hUSER32 = LoadLibrary( "USER32.DLL" ); 29 SLWA pSetLayeredWindowAttributes = (SLWA)GetProcAddress( 30 hUSER32, "SetLayeredWindowAttributes" ); 31 pSetLayeredWindowAttributes( hWnd, NULL, chAlpha, LWA_ALPHA ); 32 FreeLibrary( hUSER32 ); 33 34 return TRUE; 35 }
Bitmap 모양 그대로 투명 윈도우 만들기 (MFC) [Bottom] [Top]
이 방법은 전체 윈도우의 알파값을 조정하는 투명윈도우가 아니라, 윈도우 모양 자체를 자기 마음대로 만드는 방법입니다. 참고로 이 상태에서 resize 하면 상당한 부담이 가니 자제 하시는게 쾌적한 프로그래밍을 위해 좋습니다.
어떤 bitmap 으로든 윈도우를 만들었다면 특정색(투명화시킬 부분색)을 없애주면 됩니다. 만약 특정부위에 투명화 시킬 색이 있다면 그 부분만 검사해서 투명화 시켜주면 빠른 투명화가 가능합니다. 다음 코드는 코드구루에서 받은 어떤 소스를 수정한 것입니다.
먼저 멤버변수로 BOOL bRun = TRUE; 을 만들어주시고, dialog에 원하는 bitmap 을 입힙니다. 그리고, 다음 코드를 OnPaint 맨뒤에 넣어주세요.
1 // 상수 선언 2 #define USER_TRANSPARENCY_COLOR_KEY RGB(0,0,0) 3 4 #define USER_X_MAX (100) 5 #define USER_Y_MAX (100) 6 7 8 //------------------------------------------------------------------------------ 9 // 함수 코드 10 CRect rect; 11 GetWindowRect( rect ); 12 13 HDC hdc = dc.GetSafeHdc(); 14 15 int nX, nY; 16 COLORREF getColor; 17 CRgn Working, Temp; 18 19 if( bRun ) 20 { 21 int nSet = 0; 22 23 for( nX = 0; nX <= rect.Width(); ++nX ) 24 { 25 //특정 부분만 검사해줄때 이런식으로 코드를 넣어줍니다. 26 for( nY = rect.Height() - 90; nY <= rect.Height() + 90; ++nY ) 27 { 28 getColor = GetPixel( hdc, nX, nY ); 29 if( getColor == USER_TRANSPARENCY_COLOR_KEY ) 30 { 31 if( nSet == 0 ) 32 { 33 Working.CreateRectRgn( nX, nY, nX + 1, nY + 1 ); 34 nSet = 1; 35 } 36 else 37 { 38 Temp.CreateRectRgn( nX, nY, nX + 1, nY + 1 ); 39 Working.CombineRgn( &Working, &Temp, RGN_OR ); 40 Temp.DeleteObject(); 41 } 42 } 43 } 44 } 45 46 bRun = FALSE; 47 48 //최대값 X와 Y는 실제 Dialog의 최대 가로, 세로 값보다 넉넉하게 잡아주셔야 합니다. 49 Temp.CreateRectRgn( 0, 0, USER_X_MAX, USER_Y_MAX ); 50 51 //그렇지 않을 경우, resize할때 에러가 납니다. 52 Working.CombineRgn( &Working, &Temp, RGN_XOR ); 53 Temp.DeleteObject(); 54 if( nSet ) 55 { 56 SetWindowRgn( (HRGN)Working, TRUE ); 57 } 58 59 RedrawWindow(); 60 }
만약 resize 를 해야하는 윈도우라면, OnSize( UINT nType, int cx, int cy ) 안에
nRun = 1; Invalidate();
해주면 다시 검사후 투명화 시킵니다.
Bitmap 을 이용한 투명윈도우 만들기 [Bottom] [Top]
이전 소스를 찾아보면 비슷한게 있습니다. 그러나 이것과 그것의 차이는 USER32.DLL 모듈의 함수를 사용함으로 성능이 월등이 좋다는 겁니다.
샘플은 코드 프로젝트의 CDialogSK_demo 입니다.
http://www.codeproject.com/dialog/cdialogsk.asp
1 // 상수 선언 2 #define WS_EX_LAYERED 0x00080000 3 4 #define LWA_COLORKEY 1 // Use color as the transparency color. 5 #define LWA_ALPHA 2 // Use bAlpha to determine the opacity of the layer 6 7 // =========================================================================== 8 // Function pointer for lyering API in User32.dll 9 // =========================================================================== 10 typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes) 11 (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags); 12 13 lpfnSetLayeredWindowAttributes g_pSetLayeredWindowAttributes; 14 15 16 // 초기화 함수 (생성자나 OninitDialog 에서 호출하면 되겠습니다. 전 생성자에서 했음) 17 void CWaitDlg::Init() 18 { 19 // Get the function from the user32.dll 20 HMODULE hUser32 = GetModuleHandle( _T( "USER32.DLL" ) ); 21 g_pSetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes) 22 GetProcAddress( hUser32, "SetLayeredWindowAttributes" ); 23 } 24 25 // 투명하게 할 색을 정의 합니다. 26 BOOL CWaitDlg::SetTransparentColor( COLORREF col, BOOL bTrans ) 27 { 28 if( g_pSetLayeredWindowAttributes == NULL ) 29 { 30 return FALSE; 31 } 32 33 if( bTrans ) 34 { 35 // Set layered style for the dialog 36 SetWindowLong( m_hWnd, GWL_EXSTYLE, 37 GetWindowLong( m_hWnd, GWL_EXSTYLE ) | WS_EX_LAYERED ); 38 39 // Call it with 0 alpha for the given color 40 g_pSetLayeredWindowAttributes( m_hWnd, col, 0, LWA_COLORKEY ); 41 } 42 else 43 { 44 SetWindowLong( m_hWnd, GWL_EXSTYLE, 45 GetWindowLong( m_hWnd, GWL_EXSTYLE ) & ~WS_EX_LAYERED ); 46 47 // Ask the window and its children to repaint 48 ::RedrawWindow( m_hWnd, NULL, NULL, 49 RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN ); 50 } 51 52 return TRUE; 53 } 54 55 // 생성자에서 SetTransparentClor 을 호출합니다. 56 // 물론 Bitmap 을 로드하여 OnPaint 에서 뿌려줘야겠슴돠. 57 BOOL CWaitDlg::OnInitDialog() 58 { 59 Init(); 60 61 // Set green as the transparent color 62 SetTransparentColor( RGB( 255, 0, 255 ) ); 63 }
초간단 투명윈도우 (win2k 이상) [Bottom] [Top]
http://blog.naver.com/forcepsb/100001673901
1 // 데이터형 / 상수 선언 2 typedef BOOL (WINAPI *SetLayer)(HWND hWnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags); 3 4 #define LWA_COLORKEY 0x01 5 #define LWA_ALPHA 0x02 6 7 8 //------------------------------------------------------------------------------ 9 // 함수 코드 10 HMODULE hUser32 = GetModuleHandle( _T( "USER32.DLL" ) ); 11 SetLayer pSetLayer = (SetLayer)GetProcAddress( hUser32, "SetLayeredWindowAttributes" ); 12 13 if( pSetLayer == NULL ) 14 { 15 MessageBox("win2000 이상"); 16 return; 17 } 18 19 // 투명도 설정 (0 ~ 255) 20 char chAlpha = m_slider.GetPos(); 21 SetWindowLong( this->m_hWnd, GWL_EXSTYLE, 22 GetWindowLong( this->m_hWnd, GWL_EXSTYLE ) | 0x80000 ); 23 24 pSetLayer( this->m_hWnd, 0, chAlpha, LWA_ALPHA );
m_slider 는 Slider Control 변수.
