// SkinWin.cpp: implementation of the CSkinWin class. // // A class to enable draw windows-blind style window // // ToDo: // how to popup system menu by my program?? // // History: // 2002.11.24 // CAN WORK NOW. // 2002.11.23 intial version // // // // AUthor: // szhao00@mails.tsinghua.edu.cn // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "SkinWin.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSkinWin::CSkinWin() { m_bInit = FALSE; m_winstate = 0; m_barcolor = RGB(207,207,207); m_menucolor = RGB(207,207,207); } CSkinWin::~CSkinWin() { } CString GetPathName( const char * filename ); CString GetFileName( const char * filename, int ext = 0); char *next_token( char *buf, char *token, char *stopchars ); COLORREF ReadColor( CString section, CString key, CString file, COLORREF defcolor ) { char buf[1000]; GetPrivateProfileString( section, key, "", buf, 1000, file ); if ( *buf ) { char token[255]; char *p = buf; int r, g, b; p = next_token( p, token, NULL ); r = atoi(token); p = next_token( p, token, NULL ); g = atoi(token); p = next_token( p, token, NULL ); b = atoi(token); return RGB(r, g, b ); } else return defcolor; } BOOL CSkinWin::LoadSkin( const char * skinfile ) { static const char * ps = "Personality"; char buf[1000]; CString path = GetPathName( skinfile ); if ( m_bInit ) { m_bmpDlg.DeleteObject(); m_bmpTitle.DeleteObject(); m_bmpLeft.DeleteObject(); m_bmpRight.DeleteObject(); m_bmpBottom.DeleteObject(); m_bmpMaxBtn.DeleteObject(); m_bmpRestoreBtn.DeleteObject(); m_bmpMinBtn.DeleteObject(); m_bmpCloseBtn.DeleteObject(); //set deafult m_barcolor = RGB(207,207,207); m_menucolor = RGB(207,207,207); m_bInit = FALSE; } GetPrivateProfileString( ps, "DialogBmp", "", buf, 1000, skinfile ); if ( *buf != 0 ) m_bmpDlg.LoadBitmap( path + "/" + GetFileName( buf,1 )); GetPrivateProfileString( ps, "Top", "", buf, 1000, skinfile ); if ( *buf == 0 || !m_bmpTitle.LoadBitmap( path + "/" + GetFileName( buf,1 )) ) return FALSE; GetPrivateProfileString( ps, "Left", "", buf, 1000, skinfile ); if ( *buf == 0 || !m_bmpLeft.LoadBitmap( path + "/" + GetFileName( buf,1 ) )) return FALSE; GetPrivateProfileString( ps, "Right", "", buf, 1000, skinfile ); if ( *buf == 0 || !m_bmpRight.LoadBitmap( path + "/" + GetFileName( buf,1 ) )) return FALSE; GetPrivateProfileString( ps, "Bottom", "", buf, 1000, skinfile ); if ( *buf == 0 || !m_bmpBottom.LoadBitmap( path + "/" + GetFileName( buf,1 ) )) return FALSE; m_TitleHeight = m_bmpTitle.Height()/2; m_BorderLeftWidth = m_bmpLeft.Width()/2; m_BorderRightWidth = m_bmpRight.Width()/2; m_BorderBottomHeight = m_bmpBottom.Height()/2; m_titleoff1 = GetPrivateProfileInt( ps, "TopTopHeight", 0, skinfile ); m_titleoff2 = m_bmpTitle.Width() - GetPrivateProfileInt( ps, "TopBotHeight", 0, skinfile ); if ( m_titleoff2 <= m_titleoff1 ) m_titleoff2 = m_titleoff1 + 1; m_leftoff1 = GetPrivateProfileInt( ps, "LeftTopHeight", 0, skinfile ); m_leftoff2 = m_bmpLeft.Height() - GetPrivateProfileInt( ps, "LeftBotHeight", 0, skinfile ); if ( m_leftoff2 <= m_leftoff1 ) m_leftoff2 = m_leftoff1 + 1; m_rightoff1 = GetPrivateProfileInt( ps, "RightTopHeight", 0, skinfile ); m_rightoff2 = m_bmpRight.Height() - GetPrivateProfileInt( ps, "RightBotHeight", 0, skinfile ); if ( m_rightoff2 <= m_rightoff1 ) m_rightoff2 = m_rightoff1 + 1; m_bottomoff1 = GetPrivateProfileInt( ps, "BottomTopHeight", 0, skinfile ); m_bottomoff2 = m_bmpBottom.Width() - GetPrivateProfileInt( ps, "BottomBotHeight", 0, skinfile ); if ( m_bottomoff2 <= m_bottomoff1 ) m_bottomoff2 = m_bottomoff1 + 1; //load buttons int count = GetPrivateProfileInt( ps, "ButtonCount", 0, skinfile ); int icount = GetPrivateProfileInt( ps, "ButtonImgCount", 3, skinfile ); for ( int i = 0; i < count; i++ ) { CString sec; sec.Format( "Button%d", i ); GetPrivateProfileString( sec, "ButtonImage", "", buf, 1000, skinfile ); int action = GetPrivateProfileInt( sec, "Action", 0, skinfile ); int x = GetPrivateProfileInt( sec, "XCoord", 0, skinfile ); int y = GetPrivateProfileInt( sec, "YCoord", 0, skinfile ); int state = icount; if ( action == 0 ) { //close if ( !m_bmpCloseBtn.LoadBitmap( path + "/" + GetFileName( buf,1 )) ) return FALSE; //state = m_bmpCloseBtn.Width()/m_bmpCloseBtn.Height(); m_rectCloseBtn = CRect( x-m_bmpCloseBtn.Width()/state, y, x , y + m_bmpCloseBtn.Height() ); } if ( action == 2 ) { //min if ( !m_bmpMinBtn.LoadBitmap( path + "/" + GetFileName( buf,1 )) ) return FALSE; //state = m_bmpMinBtn.Width()/m_bmpMinBtn.Height(); m_rectMinBtn = CRect( x-m_bmpMinBtn.Width()/state, y, x, y + m_bmpMinBtn.Height() ); } if ( action == 1 ) { if ( !m_bmpMaxBtn.GetSafeHandle() ) { //max if ( !m_bmpMaxBtn.LoadBitmap( path + "/" + GetFileName( buf,1 )) ) return FALSE; //state = m_bmpMaxBtn.Width()/m_bmpMaxBtn.Height(); m_rectMaxBtn = CRect( x-m_bmpMaxBtn.Width()/state, y, x , y + m_bmpMaxBtn.Height() ); } else { //restore if ( !m_bmpRestoreBtn.LoadBitmap( path + "/" + GetFileName( buf,1 )) ) return FALSE; //state = m_bmpRestoreBtn.Width()/m_bmpRestoreBtn.Height(); m_rectRestoreBtn = CRect( x-m_bmpRestoreBtn.Width()/state, y, x , y + m_bmpRestoreBtn.Height() ); } } if ( action == 4 ) { } } m_textShift = GetPrivateProfileInt( ps, "TextShift", 0, skinfile ); m_textShiftVer = GetPrivateProfileInt( ps, "TextShiftVert", 0, skinfile ); char * colours = "Colours"; m_colTitle1 = ReadColor(colours, "TitleText", skinfile, GetSysColor(COLOR_CAPTIONTEXT) ); m_colTitle2 = ReadColor(colours, "InactiveTitleText", skinfile, GetSysColor(COLOR_CAPTIONTEXT) ); m_bTrans = GetPrivateProfileInt( ps, "UsesTran", 0, skinfile ); if ( m_bTrans ) m_colTrans = ReadColor(colours, "TransColor", skinfile, RGB(255,0,255) ); m_barcolor = ReadColor(colours, "BarColor", skinfile, RGB(207,207,207) ); m_menucolor = ReadColor(colours, "MenuColor", skinfile, RGB(207,207,207) ); m_btnbgcolor = ReadColor(colours, "ButtonFace", skinfile, GetSysColor(COLOR_BTNFACE) ); m_btntextcolor = ReadColor(colours, "ButtonText", skinfile, GetSysColor(COLOR_BTNTEXT)); m_btnhovercolor = ReadColor(colours, "ButtonHilight", skinfile, GetSysColor(COLOR_BTNFACE) ); m_btnfocuscolor = ReadColor(colours, "ButtonFocus", skinfile, GetSysColor(COLOR_BTNFACE) ); m_bInit = TRUE; return TRUE; } BOOL CSkinWin::DrawTitle(CDC *pDC, int x, int y, int w, int state) { int padding; int ox = x; padding = ( w - m_bmpTitle.Width() )/( m_titleoff2 - m_titleoff1 ) + 1 ; if ( padding < 0 ) padding = 0; RECT sr; if ( state == 0 ) sr = CRect( 0, 0, m_titleoff1, m_TitleHeight ); else sr = CRect( 0, m_TitleHeight, m_titleoff1, m_bmpTitle.Height() ); m_bmpTitle.Draw( pDC, x, y, &sr ); x += m_titleoff1; if ( state == 0 ) sr = CRect( m_titleoff1, 0, m_titleoff2, m_TitleHeight ); else sr = CRect( m_titleoff1, m_TitleHeight, m_titleoff2, m_bmpTitle.Height() ); for ( int i = 0; i <= padding; i++, x += m_titleoff2 - m_titleoff1 ) { int d = ( x + m_titleoff2 - m_titleoff1 - ox - w); if ( d > 0 ) sr.right = sr.right - d; m_bmpTitle.Draw( pDC, x, y, &sr ); } x = ox + w - ( m_bmpTitle.Width() - m_titleoff2 ) + 1 ; if ( state == 0 ) sr = CRect( m_titleoff2, 0, m_bmpTitle.Width()-1, m_TitleHeight); else sr = CRect( m_titleoff2, m_TitleHeight, m_bmpTitle.Width()-1, m_bmpTitle.Height() ); m_bmpTitle.Draw( pDC, x, y, &sr ); return TRUE; } BOOL CSkinWin::DrawBottom(CDC *pDC, int x, int y, int w, int state) { int padding; int ox = x; padding = ( w - m_bmpBottom.Width() )/( m_bottomoff2 - m_bottomoff1 ) + 1 ; if ( padding < 0 ) padding = 0; RECT sr; if ( state == 0 ) sr = CRect( 0, 0, m_bottomoff1, m_BorderBottomHeight); else sr = CRect( 0, m_BorderBottomHeight, m_bottomoff1, m_bmpBottom.Height() ); m_bmpBottom.Draw( pDC, x, y, &sr ); x += m_bottomoff1; if ( state == 0 ) sr = CRect( m_bottomoff1, 0, m_bottomoff2, m_BorderBottomHeight ); else sr = CRect( m_bottomoff1, m_BorderBottomHeight, m_bottomoff2, m_bmpBottom.Height() ); for ( int i = 0; i <= padding; i++, x += m_bottomoff2 - m_bottomoff1 ) { int d = ( x + m_bottomoff2 - m_bottomoff1 - ox - w); if ( d > 0 ) sr.right = sr.right - d; m_bmpBottom.Draw( pDC, x, y, &sr ); } x = ox + w - ( m_bmpBottom.Width() - m_bottomoff2 ); if ( state == 0 ) sr = CRect( m_bottomoff2, 0, m_bmpBottom.Width()-1, m_BorderBottomHeight ); else sr = CRect( m_bottomoff2, m_BorderBottomHeight, m_bmpBottom.Width()-1, m_bmpBottom.Height() ); m_bmpBottom.Draw( pDC, x, y, &sr ); return TRUE; } BOOL CSkinWin::DrawLeft(CDC *pDC, int x, int y, int h, int state) { int padding; int oy = y; padding = ( h - m_bmpLeft.Height() )/( m_leftoff2 - m_leftoff1 ) + 1 ; if ( padding < 0 ) padding = 0; RECT sr; if ( state == 0 ) sr = CRect( 0, 0, m_BorderLeftWidth, m_leftoff1 ); else sr = CRect( m_BorderLeftWidth, 0, m_bmpLeft.Width(), m_leftoff1 ); m_bmpLeft.Draw( pDC, x, y, &sr ); y += m_leftoff1; if ( state == 0 ) sr = CRect( 0, m_leftoff1, m_BorderLeftWidth, m_leftoff2 ); else sr = CRect( m_BorderLeftWidth, m_leftoff1, m_bmpLeft.Width(), m_leftoff2 ); for ( int i = 0; i <= padding; i++, y += m_leftoff2 - m_leftoff1 ) { int d = ( y + m_leftoff2 - m_leftoff1 - oy - h); if ( d > 0 ) sr.bottom = sr.bottom - d; m_bmpLeft.Draw( pDC, x, y, &sr ); } y = oy + h - ( m_bmpLeft.Height() - m_leftoff2 ) ; if ( state == 0 ) sr = CRect( 0, m_leftoff2, m_BorderLeftWidth, m_bmpLeft.Height()); else sr = CRect( m_BorderLeftWidth, m_leftoff2, m_bmpLeft.Width(), m_bmpLeft.Height() ); m_bmpLeft.Draw( pDC, x, y, &sr ); return TRUE; } BOOL CSkinWin::DrawRight(CDC *pDC, int x, int y, int h, int state) { int padding; int oy = y; padding = ( h - m_bmpRight.Height() )/( m_rightoff2 - m_rightoff1 ) + 1 ; if ( padding < 0 ) padding = 0; RECT sr; if ( state == 0 ) sr = CRect( 0, 0, m_BorderRightWidth, m_rightoff1 ); else sr = CRect( m_BorderRightWidth, 0, m_bmpRight.Width(), m_rightoff1 ); m_bmpRight.Draw( pDC, x, y, &sr ); y += m_rightoff1; if ( state == 0 ) sr = CRect( 0, m_rightoff1, m_BorderRightWidth, m_rightoff2 ); else sr = CRect( m_BorderRightWidth, m_rightoff1, m_bmpRight.Width(), m_rightoff2 ); for ( int i = 0; i <= padding; i++, y += m_rightoff2 - m_rightoff1 ) { int d = ( y + m_rightoff2 - m_rightoff1 - oy - h); if ( d > 0 ) sr.bottom = sr.bottom - d; m_bmpRight.Draw( pDC, x, y, &sr ); } y = oy + h - ( m_bmpRight.Height() - m_rightoff2 ) ; if ( state == 0 ) sr = CRect( 0, m_rightoff2, m_BorderRightWidth, m_bmpRight.Height()); else sr = CRect( m_BorderRightWidth, m_rightoff2, m_bmpRight.Width(), m_bmpRight.Height() ); m_bmpRight.Draw( pDC, x, y, &sr ); return TRUE; } BOOL CSkinWin::DrawFrame(CDC *pDC, int x, int y, int w, int h, int state, int title ) { if ( title ) DrawTitle( pDC, x + m_BorderLeftWidth , y, w - m_BorderRightWidth - m_BorderLeftWidth + 1, state ); DrawLeft( pDC, x, y, h, state ); DrawRight( pDC, x + w - m_BorderRightWidth , y, h, state ); DrawBottom( pDC, x + m_BorderLeftWidth, y + h - m_BorderBottomHeight, w - m_BorderRightWidth - m_BorderLeftWidth, state ); return TRUE; } BOOL CSkinWin::InstallSkin(CWnd *wnd) { if ( !wnd || !m_bInit ) return FALSE; HookWindow( (HWND)NULL); int r = HookWindow( wnd ); DWORD style = GetWindowLong( m_hWnd, GWL_STYLE ); m_sizable = style & WS_SIZEBOX; m_minable = style & WS_MINIMIZEBOX; m_maxable = style & WS_MAXIMIZEBOX; //m_sysmenu = style & WS_MAXIMIZEBOX; style &= ~(WS_MINIMIZEBOX); style &= ~WS_MAXIMIZEBOX; style &= ~WS_SYSMENU; SetWindowLong( m_hWnd, GWL_STYLE, style ); return r; } LRESULT CSkinWin::WindowProc(UINT msg, WPARAM wp, LPARAM lp) { if ( !IsWindow(m_hWnd) ) return 0; if ( !m_bInit ) return Default(); switch ( msg ) { case WM_SHOWWINDOW: //call setwindowpos to force OnNcCalcSize when hWnd is a dialog if ( wp ) SetWindowPos( m_hWnd, 0, 0, 0, 400, 400, SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED ); Default(); return 0; break; //case WM_ERASEBKGND: case WM_INITMENUPOPUP: Default(); return 0; // return OnEraseBkgnd(CDC::FromHandle((HDC)wp) ); /* case WM_INITMENU: //a hack, when popup sysmenu, redraw title bar HMENU h; h = (HMENU)wp; int c; h = GetSubMenu(h, 0); c = GetMenuItemID( h, 0 ); if ( c == SC_RESTORE ) { CRect r; GetClientRect( m_hWnd, r ); OnNcPaint(0); r.bottom = GetSystemMetrics(SM_CYCAPTION); InvalidateRect( m_hWnd, r, TRUE ); UpdateWindow( m_hWnd ); } Default(); return 0; */ case WM_SYSCOMMAND: OnSysCommand( wp, lp ); //Default(); return 0; case WM_SETTEXT: return OnSetText( wp, lp ); case WM_NCPAINT: OnNcPaint( (HRGN)wp ); return 0; case WM_NCCALCSIZE: OnNcCalcSize( (BOOL)wp, (NCCALCSIZE_PARAMS *)lp ); return 0; case WM_SIZE: OnSize( wp, LOWORD(lp), HIWORD(lp) ); return 0; case WM_NCACTIVATE: return OnNcActivate( (BOOL)wp ); case WM_NCHITTEST: return OnNcHitTest(CPoint(LOWORD(lp), HIWORD(lp))); case WM_NCLBUTTONUP: OnNcLButtonUp(wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCLBUTTONDOWN: OnNcLButtonDown(wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCLBUTTONDBLCLK: OnNcLButtonDblClk(wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCRBUTTONUP: OnNcRButtonUp(wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCRBUTTONDOWN: OnNcRButtonDown(wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCMOUSEMOVE: OnNcMouseMove( wp,CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_GETMINMAXINFO: OnGetMinMaxInfo( (MINMAXINFO *)lp ); return 0; case WM_WINDOWPOSCHANGING: OnWindowPosChanging((WINDOWPOS *)lp); return 0; case WM_SIZING: OnSizing( wp, (LPRECT)lp ); return 0; case WM_ACTIVATE: OnActivate( wp, CWnd::FromHandle((HWND)lp), 0 ); return 0; case WM_COMMAND: if ( !HandleSysCommand( wp, lp ) ) Default(); return 0; default: return Default(); } } void CSkinWin::OnNcPaint(HRGN rgn1) { CWnd *pWnd = CWnd::FromHandle(m_hWnd); CDC * pDC = pWnd->GetWindowDC(); CRect wr; pWnd->GetWindowRect( wr ); //f ( (DWORD)rgn) //pDC->SelectClipRgn( CRgn::FromHandle(rgn) ); //m_bActive = GetActiveWindow() == m_hWnd; int state = 0; if ( m_bActive) state = 0; else state = 1; pDC->ExcludeClipRect(0, 0, wr.Width(), m_TitleHeight ); DrawFrame( pDC, 0, 0, wr.Width(), wr.Height(), state, 0 ); pDC->SelectClipRgn( NULL ); CDC memDC, *pNewDC; CMyBitmap bmp; CBitmap *obmp; memDC.CreateCompatibleDC( pDC ); bmp.CreateCompatibleBitmap( pDC, wr.Width(), m_TitleHeight ); obmp = memDC.SelectObject(&bmp); pNewDC = &memDC; DrawTitle( pNewDC, m_BorderLeftWidth , 0, wr.Width() - m_BorderRightWidth - m_BorderLeftWidth + 1, state ); DrawLeft( pNewDC, 0, 0, m_bmpLeft.Height(), state ); DrawRight( pNewDC, wr.Width() - m_BorderRightWidth , 0, m_bmpRight.Height(), state ); CRgn newrgn; newrgn.CreateRectRgn( 0, 0, wr.Width(), wr.Height() ); if ( m_bTrans ) { CRgn rgn; rgn.CreateRectRgn( 0, m_TitleHeight, wr.Width(), wr.Height() ); HRGN hrgn = bmp.CreateRgnFromFile( m_colTrans ); newrgn.CombineRgn( &rgn, CRgn::FromHandle(hrgn), RGN_XOR ); pDC->SelectClipRgn( &newrgn ); } else SetWindowRgn( m_hWnd, newrgn, FALSE ); if ( m_downHitTest == HTCLOSE ) DrawButton( pNewDC, 0, 1 ); else if ( m_moveHitTest == HTCLOSE) DrawButton( pNewDC, 0, 2 ); else DrawButton( pNewDC, 0, 0 ); if ( m_downHitTest == HTMINBUTTON ) DrawButton( pNewDC, 2, 1 ); else if ( m_moveHitTest == HTMINBUTTON) DrawButton( pNewDC, 2, 2 ); else DrawButton( pNewDC, 2, 0 ); if ( m_downHitTest == HTMAXBUTTON ) DrawButton( pNewDC, 1, 1 ); else if ( m_moveHitTest == HTMAXBUTTON) DrawButton( pNewDC, 1, 2 ); else DrawButton( pNewDC, 1, 0 ); int cx = GetSystemMetrics(SM_CXSMICON); int cy = GetSystemMetrics(SM_CYSMICON); HICON hi = (HICON)SendMessage( m_hWnd, WM_GETICON, ICON_SMALL, 0); if ( !hi ) { #ifdef IDR_MAINFRAME hi = AfxGetApp()->LoadIcon(IDR_MAINFRAME); #endif } //draw icon ::DrawIconEx( pNewDC->GetSafeHdc(), m_BorderLeftWidth, 5, (HICON) CopyImage( hi, IMAGE_ICON, cx, cy, 0), cx, cy, 0, 0, DI_NORMAL); //draw text if ( m_title.IsEmpty() ) pWnd->GetWindowText(m_title); if (m_bActive) pNewDC->SetTextColor( m_colTitle1 ); else pNewDC->SetTextColor( m_colTitle2 ); CFont font, *ofont; font.CreatePointFont( GetSystemMetrics(SM_CYSMCAPTION), "System" ); ofont = pNewDC->SelectObject(&font); pNewDC->SetBkMode(TRANSPARENT); pNewDC->DrawText( m_title, CRect( m_textShift, m_textShiftVer, wr.Width() - m_bmpTitle.Width() + m_titleoff2, m_TitleHeight ), DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_WORD_ELLIPSIS ); pNewDC->SelectObject(&font); pDC->BitBlt( 0, 0, wr.Width(), m_TitleHeight, pNewDC, 0, 0, SRCCOPY ); memDC.SelectObject(obmp); pDC->SelectClipRgn(NULL); } void CSkinWin::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *lpncsp) { if ( bCalcValidRects ) { lpncsp->rgrc[0].left = lpncsp->rgrc[0].left + m_BorderLeftWidth; lpncsp->rgrc[0].right = lpncsp->rgrc[0].right - m_BorderRightWidth; lpncsp->rgrc[0].top = lpncsp->rgrc[0].top + m_TitleHeight; lpncsp->rgrc[0].bottom = lpncsp->rgrc[0].bottom - m_BorderBottomHeight; lpncsp->rgrc[1] = lpncsp->rgrc[0]; } else { Default(); } } void CSkinWin::OnSizing(UINT nSide, LPRECT lpRect) { //Default(); CWnd *pWnd = CWnd::FromHandle(m_hWnd); CRect wr(lpRect); /* if ( m_bTrans ) SetWindowRgn( m_hWnd, GetRegion(wr.Width(), wr.Height() ), TRUE ); else SetWindowRgn( m_hWnd, NULL, TRUE ); */ } void CSkinWin::OnSize(UINT nType, int cx, int cy) { //Default(); CWnd *pWnd = CWnd::FromHandle(m_hWnd); CRect wr; Default(); pWnd->GetWindowRect(wr); pWnd->Invalidate(); OnNcPaint(0); if ( m_bTrans ) SetWindowRgn( m_hWnd, GetRegion(wr.Width(), wr.Height() ), TRUE ); else SetWindowRgn( m_hWnd, NULL, TRUE ); } HRGN CSkinWin::GetRegion(int w, int h) { CWnd *pWnd = CWnd::FromHandle(m_hWnd); CRect wr; pWnd->GetWindowRect(wr); CRgn rgn; if ( m_bTrans ) { CDC *pDC = pWnd->GetDC(); CDC memDC; CMyBitmap bmp; CBitmap *obmp; memDC.CreateCompatibleDC(pDC); bmp.CreateCompatibleBitmap( pDC, w, m_TitleHeight ); obmp = memDC.SelectObject(&bmp); /* memDC.FillSolidRect( 0, 0, w, h, 0 ); DrawFrame( &memDC, 0, 0, w, h, 0 ); */ DrawTitle( &memDC, m_BorderLeftWidth , 0, wr.Width() - m_BorderRightWidth - m_BorderLeftWidth + 1, 0 ); DrawLeft( &memDC, 0, 0, m_bmpLeft.Height(), 0 ); DrawRight( &memDC, wr.Width() - m_BorderRightWidth , 0, m_bmpRight.Height(), 0 ); memDC.SelectObject(obmp); pWnd->ReleaseDC( pDC ); rgn.CreateRectRgn( 0, m_TitleHeight, wr.Width(), wr.Height() ); HRGN hrgn = bmp.CreateRgnFromFile( m_colTrans ); CRgn newrgn; newrgn.CreateRectRgn( 0, m_TitleHeight, wr.Width(), wr.Height() ); newrgn.CombineRgn( &rgn, CRgn::FromHandle(hrgn), RGN_XOR ); return (HRGN)newrgn.Detach(); } else rgn.CreateRectRgn( 0, 0, wr.Width(), wr.Height() ); return (HRGN)rgn.Detach(); } BOOL CSkinWin::OnNcActivate(BOOL bActive) { m_bActive = bActive; OnNcPaint(0); if ( !bActive ) { return 1; } else return 0; } UINT CSkinWin::OnNcHitTest(CPoint point) { CWnd *pWnd = CWnd::FromHandle(m_hWnd); CRect wr; pWnd->GetWindowRect(wr); point.x -= wr.left; point.y -= wr.top; if ( PtInRect( GetButtonRect(0), point ) ) return HTCLOSE; if ( PtInRect( GetButtonRect(2), point ) && m_minable ) return HTMINBUTTON; if ( PtInRect( GetButtonRect(1), point ) && m_maxable ) return HTMAXBUTTON; CRect r; int cx = GetSystemMetrics(SM_CXSMICON); int cy = GetSystemMetrics(SM_CYSMICON); if ( PtInRect( CRect(m_BorderLeftWidth, 5, m_BorderLeftWidth + cx, cy + 5), point ) ) return HTSYSMENU; r = CRect( 0, 0, m_BorderLeftWidth, m_TitleHeight ); if ( PtInRect( r, point ) && m_sizable && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) return HTTOPLEFT; r = CRect( wr.Width() - m_BorderLeftWidth, 0, wr.Width(), m_TitleHeight ); if ( PtInRect( r, point ) && m_sizable && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) return HTTOPRIGHT; r = CRect( 0, wr.Height() - m_BorderBottomHeight, m_BorderLeftWidth, wr.Height() ); if ( PtInRect( r, point ) && m_sizable && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) return HTBOTTOMLEFT; r = CRect( wr.Width()-m_BorderRightWidth, wr.Height() - m_BorderBottomHeight, wr.Width(), wr.Height() ); if ( PtInRect( r, point ) && m_sizable && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) return HTBOTTOMRIGHT; r = CRect( 0, m_TitleHeight, m_BorderLeftWidth, wr.Height() - m_BorderBottomHeight ); if ( PtInRect( r, point ) && m_sizable && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) return HTLEFT; r = CRect( wr.Width()-m_BorderRightWidth, m_TitleHeight, wr.Width(), wr.Height() - m_BorderBottomHeight ); if ( PtInRect( r, point ) && m_sizable && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) return HTRIGHT; r = CRect( m_BorderLeftWidth, wr.Height() - m_BorderBottomHeight, wr.Width()-m_BorderRightWidth, wr.Height() ); if ( PtInRect( r, point ) && m_sizable && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) return HTBOTTOM; r = CRect( m_BorderLeftWidth, 0, wr.Width()-m_BorderRightWidth, m_BorderBottomHeight ); if ( PtInRect( r, point ) && m_sizable && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) return HTTOP; //set to boder 5 r = CRect( m_BorderLeftWidth, 5 , wr.Width()-m_BorderRightWidth, m_TitleHeight ); if ( PtInRect( r, point ) ) return HTCAPTION; return HTCLIENT; } void CSkinWin::OnNcLButtonDblClk(UINT nHitTest, CPoint point) { if ( nHitTest == HTCAPTION && m_sizable ) { if ( m_winstate == 1 ) Restore(); else Maximize(); //ShowWindow(m_hWnd, SW_MAXIMIZE); m_downHitTest = 0; m_moveHitTest = 0; OnNcPaint(0); } } void CSkinWin::OnNcLButtonDown(UINT nHitTest, CPoint point) { m_downHitTest = nHitTest; m_moveHitTest = m_downHitTest; OnNcPaint(0); if ( nHitTest >= HTLEFT && nHitTest <= HTBOTTOMRIGHT || nHitTest == HTCAPTION && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) Default(); else if ( nHitTest == HTSYSMENU ) { PopupSysMenu(point); /* CWnd * pWnd = CWnd::FromHandle(m_hWnd); //a tricky hack pWnd->ModifyStyle( 0, WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ); Default(); pWnd->ModifyStyle( WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 0 ); */ } } void CSkinWin::OnNcLButtonUp(UINT nHitTest, CPoint point) { if ( nHitTest == HTCLOSE ) { SendMessage(m_hWnd, WM_CLOSE, 0, 0); return; } else if ( nHitTest == HTMINBUTTON ) Minimize(); else if ( nHitTest == HTMAXBUTTON ) { if ( m_winstate == 1 ) // IsZoomed(m_hWnd) ) Restore(); //ShowWindow(m_hWnd, SW_RESTORE); else Maximize(); //ShowWindow(m_hWnd, SW_MAXIMIZE); } else return; m_downHitTest = 0; m_moveHitTest = 0; OnNcPaint(0); } void CSkinWin::OnNcMouseMove(UINT nHitTest, CPoint point) { if ( nHitTest >= HTLEFT && nHitTest <= HTBOTTOMRIGHT || nHitTest == HTCAPTION && m_winstate != 1 ) //!IsZoomed(m_hWnd) ) Default(); m_moveHitTest = nHitTest; m_downHitTest = 0; if ( m_oldHitTest != nHitTest ) { /* CRect r; r = GetButtonRect(0); r.UnionRect( r, GetButtonRect(1) ); r.UnionRect( r, GetButtonRect(2) ); CRgn rgn; rgn.CreateRectRgn( r.left, r.top, r.right, r.bottom ); */ OnNcPaint(0); m_oldHitTest = nHitTest; } } void CSkinWin::OnNcRButtonDown(UINT nHitTest, CPoint point) { if ( nHitTest == HTCAPTION ) { /* CWnd * pWnd = CWnd::FromHandle(m_hWnd); pWnd->ModifyStyle( 0, WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ); Default(); pWnd->ModifyStyle( WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 0 ); */ PopupSysMenu(point); } } void CSkinWin::OnNcRButtonUp(UINT nHitTest, CPoint point) { } CRect CSkinWin::GetButtonRect(int i) { CWnd *pWnd = CWnd::FromHandle(m_hWnd); CRect wr; pWnd->GetWindowRect(wr); CRect r; if ( i == 0 && m_bmpCloseBtn.GetSafeHandle() ) { //close r = m_rectCloseBtn; r.left = wr.Width() - m_rectCloseBtn.right; r.right = wr.Width() - m_rectCloseBtn.left; } if ( i == 1 && m_bmpMaxBtn.GetSafeHandle()) { //max if ( m_winstate != 1 || !m_bmpRestoreBtn.GetSafeHandle() ) { r = m_rectMaxBtn; r.left = wr.Width() - m_rectMaxBtn.right; r.right = wr.Width() - m_rectMaxBtn.left; } else { r = m_rectRestoreBtn; r.left = wr.Width() - m_rectRestoreBtn.right; r.right = wr.Width() - m_rectRestoreBtn.left; } } if ( i == 2 && m_bmpMinBtn.GetSafeHandle()) { //min r = m_rectMinBtn; r.left = wr.Width() - m_rectMinBtn.right; r.right = wr.Width() - m_rectMinBtn.left; } return r; } BOOL CSkinWin::DrawButton( CDC * pDC, int i, int state) { if ( i == 0 ) { if ( m_bmpCloseBtn.GetSafeHandle() ) { CRect r = GetButtonRect(0); m_bmpCloseBtn.Draw( pDC, r.left, r.top, CRect( state * r.Width(), 0, (state + 1 ) * r.Width(), m_bmpCloseBtn.Height() ), m_colTrans, m_bTrans ); } } if ( i == 1 ) { CRect r = GetButtonRect(1); if ( m_maxable && m_bmpMaxBtn.GetSafeHandle() ) if ( m_winstate == 1&& m_bmpRestoreBtn.GetSafeHandle() ) m_bmpRestoreBtn.Draw( pDC, r.left, r.top, CRect( state * r.Width(), 0, (state + 1 ) * r.Width(), m_bmpCloseBtn.Height() ), m_colTrans, m_bTrans ); else m_bmpMaxBtn.Draw( pDC, r.left, r.top, CRect( state * r.Width(), 0, (state + 1 ) * r.Width(), m_bmpCloseBtn.Height() ) , m_colTrans, m_bTrans); } if ( i == 2 ) { if ( m_minable && m_bmpMinBtn.GetSafeHandle() ) { CRect r = GetButtonRect(2); m_bmpMinBtn.Draw( pDC, r.left, r.top, CRect( state * r.Width(), 0, (state + 1 ) * r.Width(), m_bmpCloseBtn.Height() ) , m_colTrans, m_bTrans); } } return TRUE; } void CSkinWin::OnGetMinMaxInfo(MINMAXINFO *lpMMI) { lpMMI->ptMinTrackSize = CPoint( m_bmpTitle.Width() + m_bmpLeft.Width() + m_bmpRight.Width(), m_bmpLeft.Height() + 20 ); } void CSkinWin::OnWindowPosChanging(WINDOWPOS *lpwndpos) { } BOOL CSkinWin::OnEraseBkgnd(CDC *pDC) { if ( m_bmpDlg.GetSafeHandle() ) { CRect r; GetClientRect( m_hWnd, r); for ( int i = 0; i < r.Width()/m_bmpDlg.Width() + 1; i++ ) for ( int j = 0; j < r.Height()/m_bmpDlg.Height() + 1; j++ ) { m_bmpDlg.Draw( pDC, CRect( i * m_bmpDlg.Width(), j * m_bmpDlg.Height(), i * m_bmpDlg.Width() + m_bmpDlg.Width(), j * m_bmpDlg.Height() + m_bmpDlg.Height() ) ); } return TRUE; } else return FALSE; } CRect CSkinWin::GetMaximizeRect() { CRect r; SystemParametersInfo(SPI_GETWORKAREA, 0, r, 0); return r; } BOOL CSkinWin::Maximize() { CRect r = GetMaximizeRect(); GetWindowRect( m_hWnd, m_rectRestoreWin ); m_winstate = 1; ::MoveWindow( m_hWnd, r.left, r.top, r.Width(), r.Height(), TRUE ); UpdateWindow( m_hWnd ); return TRUE; } BOOL CSkinWin::Minimize() { m_oldwinstate = m_winstate; m_winstate = 2; ShowWindow(m_hWnd, SW_MINIMIZE); return TRUE; } BOOL CSkinWin::Restore() { if ( m_winstate == 1 ) { ::MoveWindow( m_hWnd, m_rectRestoreWin.left, m_rectRestoreWin.top, m_rectRestoreWin.Width(), m_rectRestoreWin.Height(), TRUE ); m_winstate = 0; UpdateWindow( m_hWnd ); } return TRUE; } //void OnActivate(UINT nState,CWnd* pWndOther, BOOL bMinimized ); void CSkinWin::OnActivate(UINT nState, CWnd *pWndOther, BOOL bMinimized) { //Default(); m_bActive = ( nState == WA_ACTIVE || nState == WA_CLICKACTIVE ); OnNcActivate(m_bActive); } LRESULT CSkinWin::OnSetText(WPARAM wp, LPARAM lp) { char * str = ( char *)lp; Default(); m_title = str; OnNcPaint(0); return 0; } void CSkinWin::OnSysCommand(UINT nID, LPARAM lParam) { if ( nID == SC_MAXIMIZE ) Maximize(); else if ( nID == SC_RESTORE && m_winstate == 1 ) Restore(); else if ( nID == SC_RESTORE && m_winstate == 2 ) { ShowWindow( m_hWnd, SW_RESTORE ); m_winstate = m_oldwinstate; OnNcPaint(0); } else Default(); } BOOL CSkinWin::PopupSysMenu(CPoint point) { CWnd * pWnd = CWnd::FromHandle(m_hWnd); CMenu SysMenu; SysMenu.Attach( GetSystemMenu(m_hWnd, FALSE) ); /* when gray menuitem, a strange line appears!! if ( m_winstate == 0 ) { SysMenu.EnableMenuItem( SC_MINIMIZE, MF_BYCOMMAND|MF_ENABLED ); SysMenu.EnableMenuItem( SC_MAXIMIZE, MF_BYCOMMAND|MF_ENABLED ); SysMenu.EnableMenuItem( SC_RESTORE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED ); } else if ( m_winstate == 1 ) { SysMenu.EnableMenuItem( SC_MAXIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED ); SysMenu.EnableMenuItem( SC_RESTORE, MF_BYCOMMAND|MF_ENABLED ); } else if ( m_winstate == 2 ) { SysMenu.EnableMenuItem( SC_MINIMIZE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED ); SysMenu.EnableMenuItem( SC_RESTORE, MF_BYCOMMAND|MF_ENABLED ); } */ SysMenu.TrackPopupMenu( 0, point.x, point.y, pWnd ); SysMenu.Detach(); return TRUE; } BOOL CSkinWin::HandleSysCommand(WPARAM wp, LPARAM lp) { if ( lp == 0 ) { int i = 0; CMenu SysMenu; SysMenu.Attach( GetSystemMenu(m_hWnd, FALSE) ); int count = SysMenu.GetMenuItemCount(); for( i = 0; i < count ; i++ ) if ( SysMenu.GetMenuItemID(i) == wp ) break; SysMenu.Detach(); if ( i >= count ) return FALSE; if ( wp == SC_MAXIMIZE ) Maximize(); else if ( wp == SC_MINIMIZE ) Minimize(); else if ( wp == SC_RESTORE && m_winstate == 1 ) Restore(); else if ( wp == SC_RESTORE && m_winstate == 2 ) { ShowWindow( m_hWnd, SW_RESTORE ); m_winstate = m_oldwinstate; OnNcPaint(0); } else SendMessage( m_hWnd, WM_SYSCOMMAND, wp, lp ); return TRUE; } return FALSE; }