#include "stdafx.h" //#include "GlwGlobalVariable.h" #include "GlwSkin.h" #include "resource.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif // extern HWND global_hwnd; // extern bool global_bWndMoveStart; // extern bool global_bNCLD; namespace { void CreateFont(LPCTSTR name, int height, CFont &font) { if (font.GetSafeHandle()) font.DeleteObject(); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); lf.lfHeight = height; //lf.lfCharSet = GB2312_CHARSET; _tcscpy(lf.lfFaceName, name); font.CreateFontIndirect(&lf); } CSize GetBitMapSize(const HBITMAP& hBitmap) { CBitmap *p = CBitmap::FromHandle(hBitmap); if (!p) return CSize(0, 0); BITMAP mapinfo; memset(&mapinfo, 0, sizeof(BITMAP)); if (!p->GetBitmap(&mapinfo)) return CSize(0, 0); return CSize(mapinfo.bmWidth, mapinfo.bmHeight); } bool BitBlt( CDC &dcDest, const CPoint &ptDest, const HBITMAP& hBitmap, DWORD dwRop ) { CDC memDC; memDC.CreateCompatibleDC(&dcDest); memDC.SelectObject(hBitmap); CSize sz = GetBitMapSize(hBitmap); BOOL bRel = ::BitBlt(dcDest.GetSafeHdc(), ptDest.x, ptDest.y, sz.cx, sz.cy, memDC.GetSafeHdc(), 0, 0, dwRop); memDC.DeleteDC(); return bRel ? true : false; } } GlwSkin::GlwSkin() : m_hRgn(NULL), m_hBrush(NULL), m_reOldWnd(0, 0, 0, 0), m_bInit(false), m_bActive(FALSE), m_nTopHeight(33), m_nLBorderW(3), m_nRBorderW(3), m_nBBorderW(3), m_bSizable(false), m_bCaption(false), m_bCBtnClick(false), m_bCBtnMoveon(false), m_bCornerTitle(false), m_szMin(150, 150), m_sTitle(_T("")), m_dwOldLong(0), m_bNcLBDCaption(false), m_bNcLBDBorder(false), m_bDragTrans(true), m_colorDlg(RGB(214, 214, 214)) { CreateFont(_T("宋体"), 12, m_font); SetLabel(false);// 此函数会设置 m_nTopHeight, 故在此调用 } GlwSkin::~GlwSkin() { if (m_hRgn) ::DeleteObject(m_hRgn); if (m_hBrush) ::DeleteObject(m_hBrush); } BOOL GlwSkin::Hook(CWnd *wnd) { if ( m_bInit ) m_bInit = FALSE; m_bInit = TRUE; if ( !wnd || !m_bInit ) return FALSE; HookWindow( (HWND)NULL); int r = HookWindow( wnd ); LONG_PTR style = ::GetWindowLongPtr( m_hWnd, GWL_STYLE ); m_bSizable = (style & WS_SIZEBOX) == 0 ? false : true; m_bCaption = (style & WS_CAPTION) == 0 ? false : true; if (!m_bSizable) m_nBBorderW = 1; style &= ~WS_MINIMIZEBOX; style &= ~WS_MAXIMIZEBOX; style &= ~WS_SYSMENU; ::SetWindowLongPtr( m_hWnd, GWL_STYLE, style ); if (!m_bSizable) { m_nLBorderW = m_nRBorderW = m_nBBorderW = 1; } return r; } LRESULT GlwSkin::WindowProc(UINT msg, WPARAM wp, LPARAM lp) { if ( !IsWindow(m_hWnd) ) return 0; if ( !m_bInit ) return Default(); switch ( msg ) { case WM_SHOWWINDOW: if ( wp ) SetWindowPos( m_hWnd, 0, 0, 0, 400, 400, SWP_NOSIZE|SWP_NOMOVE|SWP_FRAMECHANGED ); Default(); return 0; break; case WM_INITMENUPOPUP: Default(); return 0; case WM_SYSCOMMAND: 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( (UINT)wp, LOWORD(lp), HIWORD(lp) ); return Default(); case WM_NCACTIVATE: return OnNcActivate( (BOOL)wp ); case WM_NCHITTEST: return OnNcHitTest(CPoint(LOWORD(lp), HIWORD(lp))); case WM_NCLBUTTONUP: OnNcLButtonUp((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCLBUTTONDOWN: OnNcLButtonDown((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCLBUTTONDBLCLK: OnNcLButtonDblClk((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); Default(); case WM_NCRBUTTONUP: Default(); return 0; case WM_NCRBUTTONDOWN: Default(); return 0; case WM_NCMOUSEMOVE: OnNcMouseMove( (UINT)wp,CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_GETMINMAXINFO: OnGetMinMaxInfo( (MINMAXINFO *)lp ); return 0; case WM_WINDOWPOSCHANGING: Default(); return 0; case WM_SIZING: Default(); return 0; case WM_ACTIVATE: OnActivate( (UINT)wp, CWnd::FromHandle((HWND)lp), 0 ); return 0; case WM_COMMAND: Default(); return 0; case WM_CTLCOLORDLG: return Default(); case WM_LBUTTONUP: Default(); return 0; default: return Default(); } } void GlwSkin::OnNcPaint(HRGN rgn1) { if (!m_bInit) return; if (!m_bCaption) { Default(); return; } CDC memDC, *pDC = CWnd::FromHandle(m_hWnd)->GetWindowDC(); CRect wr; ::GetWindowRect(m_hWnd, &wr); OffsetRect(&wr, -wr.left, -wr.top); // 生成一个 rgn 包括 title 和 border,不包含客户区 CRgn rgnBig, rgnSml, rgnRel; rgnBig.CreateRectRgn(wr.left, wr.top, wr.right, wr.bottom); rgnSml.CreateRectRgn(wr.left + m_nLBorderW, wr.top + m_nTopHeight, wr.right - m_nRBorderW, wr.bottom - m_nBBorderW); rgnRel.CreateRectRgn(0, 0, 0, 0); rgnBig.CombineRgn(&rgnBig, &rgnSml, RGN_DIFF); pDC->SelectClipRgn(&rgnBig); CAcModuleResourceOverride vTemp; memDC.CreateCompatibleDC( pDC ); CBitmap bit; bit.LoadBitmap(IDB_T20_DLG_RES); memDC.SelectObject((HBITMAP)bit); // 标题栏左上行 pDC->BitBlt(0, 0, 4, 16, &memDC, 0, 0, SRCCOPY); // 标题栏右上行 pDC->BitBlt(wr.right-18, 0, 18, 16, &memDC, 45, 0, SRCCOPY); // 标题栏上行 pDC->StretchBlt(1, 0, wr.Width()-2, 16, &memDC, 1, 0, 2, 13, SRCCOPY); pDC->BitBlt(wr.right-19, 3, 3, 10, &memDC, 44, 16, SRCCOPY); int count = wr.Width()-(4+22); if (count % 2) ++count; count = (int)(count*.5); int deltaX = 0; for (int i = 0; i < count; ++i) { pDC->BitBlt(4+deltaX, 0, 2, 16, &memDC, 44, 0, SRCCOPY); deltaX += 2; } // 标题栏下行 if (m_bHasName) { DWORD oldClr = pDC->SetTextColor((DWORD)0); int oldMode = pDC->SetBkMode(TRANSPARENT); CFont *pOldFont = pDC->SelectObject(&m_font); int txtW = pDC->GetOutputTextExtent(m_sTitle).cx; pDC->BitBlt(0, 16, 8, 17, &memDC, 0, 13, SRCCOPY); pDC->BitBlt(8+txtW, 16, 8, 17, &memDC, 15, 13, SRCCOPY); pDC->StretchBlt(8, 16, txtW, 17, &memDC, 1, 13, 2, 17, SRCCOPY); pDC->TextOut(8, 16+3, m_sTitle); pDC->SelectObject(pOldFont); pDC->SetTextColor(oldClr); pDC->SetBkMode(oldMode); pDC->StretchBlt(8+txtW+8, 16, wr.Width()-(8+txtW+8)-2, 17, &memDC, 23, 13, 2, 17, SRCCOPY); pDC->BitBlt(wr.right-2, 16, 2, 17, &memDC, 35, 13, SRCCOPY); } if (m_bSizable) { // 左边框 pDC->StretchBlt(0, m_nTopHeight, m_nLBorderW, wr.Height()-m_nTopHeight, &memDC, 41, 12, m_nLBorderW, 1, SRCCOPY); // 右边框 pDC->StretchBlt(wr.right-m_nRBorderW, m_nTopHeight, m_nRBorderW, wr.Height()-m_nTopHeight, &memDC, 41, 11, m_nRBorderW, 1, SRCCOPY); // 下边框 pDC->StretchBlt(1, wr.bottom-m_nBBorderW, wr.Width()-2, m_nBBorderW, &memDC, 41, 13, 1, m_nBBorderW, SRCCOPY); } else { // 左边框 pDC->StretchBlt(0, m_nTopHeight, m_nLBorderW, wr.Height()-m_nTopHeight, &memDC, 23, 7, m_nLBorderW, 1, SRCCOPY); // 右边框 pDC->StretchBlt(wr.right-m_nRBorderW, m_nTopHeight, m_nRBorderW, wr.Height()-m_nTopHeight, &memDC, 23, 7, m_nRBorderW, 1, SRCCOPY); // 下边框 pDC->StretchBlt(1, wr.bottom-m_nBBorderW, wr.Width()-2, m_nBBorderW, &memDC, 23, 7, 1, m_nBBorderW, SRCCOPY); } // if (m_bSizable) // pDC->TransparentBlt(wr.right-2-6, wr.bottom-2-6, 6, 6, // &memDC, 31, 0, 6, 6, RGB(214, 214, 214)); // 画关闭按钮 CBitmap bitYiban, bitDanji, bitJinguo; bitYiban.LoadBitmap(IDB_T20_TITLE_CLOSE_YIBAN); bitDanji.LoadBitmap(IDB_T20_TITLE_CLOSE_DANJI); bitJinguo.LoadBitmap(IDB_T20_TITLE_CLOSE_JINGUO); CRect reClose = GetCloseBtnRect(false); BitBlt(*pDC, reClose.TopLeft(), (HBITMAP)bitYiban, SRCCOPY); if (m_bCBtnClick) BitBlt(*pDC, reClose.TopLeft(), (HBITMAP)bitDanji, SRCCOPY); if (m_bCBtnMoveon) BitBlt(*pDC, reClose.TopLeft(), (HBITMAP)bitJinguo, SRCCOPY); pDC->SelectClipRgn(NULL); ::ReleaseDC(m_hWnd, pDC->GetSafeHdc()); memDC.DeleteDC(); rgnBig.DeleteObject(); rgnSml.DeleteObject(); } void GlwSkin::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *lpncsp) { if (bCalcValidRects && m_bCaption) { lpncsp->rgrc[0].left = lpncsp->rgrc[0].left + m_nLBorderW; lpncsp->rgrc[0].right = lpncsp->rgrc[0].right - m_nRBorderW; lpncsp->rgrc[0].top = lpncsp->rgrc[0].top + m_nTopHeight; lpncsp->rgrc[0].bottom = lpncsp->rgrc[0].bottom - m_nBBorderW; lpncsp->rgrc[1] = lpncsp->rgrc[0]; } else { Default(); } } void GlwSkin::OnSize(UINT nType, int cx, int cy) { OnNcPaint(0); ::SetWindowRgn(m_hWnd, GetRegion(), TRUE); } HRGN GlwSkin::GetRegion() { CRect rect; ::GetWindowRect(m_hWnd, &rect); OffsetRect(&rect, -rect.left, -rect.top); if (m_bCornerTitle) { rect.right += 1; if (m_hRgn) ::DeleteObject(m_hRgn); m_hRgn = ::CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 5, 5); HRGN hDif = ::CreateRectRgn(rect.left, rect.bottom-3, rect.right, rect.bottom); ::CombineRgn(m_hRgn, m_hRgn, hDif, RGN_OR); ::DeleteObject(hDif); } else { if (m_hRgn) ::DeleteObject(m_hRgn); m_hRgn = ::CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom); } return m_hRgn; } BOOL GlwSkin::OnNcActivate(BOOL bActive) { m_bActive = bActive; OnNcPaint(0); if ( !bActive ) return TRUE; else return FALSE; } UINT GlwSkin::OnNcHitTest(CPoint point) { CRect wr; ::GetWindowRect(m_hWnd, &wr); if (GetCloseBtnRect(true).PtInRect(point)) return HTCLOSE; CRect reTitle(wr.left+m_nLBorderW, wr.top+1, wr.right-m_nRBorderW, wr.top + m_nTopHeight); CRect reClient(wr.left+m_nLBorderW, wr.top+m_nTopHeight, wr.right-m_nRBorderW, wr.bottom-m_nBBorderW); CRect reLeftBar(wr.left, wr.top + m_nTopHeight, wr.left+m_nLBorderW, wr.bottom-5); CRect reRightBar(wr.right-m_nRBorderW, wr.top + m_nTopHeight, wr.right, wr.bottom-5); CRect reBottomBar(wr.left+5, wr.bottom-m_nBBorderW, wr.right-5, wr.bottom); CRect reTopBar(wr.left+5, wr.top, wr.right-5, wr.top+m_nBBorderW); CRect reTL(wr.TopLeft(), CSize(5, 5)); CRect reTR(wr.right-5, wr.top, wr.right, wr.top+5); CRect reBL(wr.left, wr.bottom-m_nBBorderW, wr.left+m_nLBorderW, wr.bottom); CRect reBR(wr.right-/*m_nRBorderW*/5, wr.bottom-/*m_nBBorderW*/5, wr.right, wr.bottom); if (reTitle.PtInRect(point)) return HTCAPTION; if (reClient.PtInRect(point)) return HTCLIENT; if (m_bSizable) { if (reLeftBar.PtInRect(point)) return HTLEFT; if (reRightBar.PtInRect(point)) return HTRIGHT; if (reBL.PtInRect(point)) return HTBOTTOMLEFT; if (reBR.PtInRect(point)) return HTBOTTOMRIGHT; if (reBottomBar.PtInRect(point)) return HTBOTTOM; // if (reTopBar.PtInRect(point)) // return HTTOP; // if (reTL.PtInRect(point)) // return HTTOPLEFT; // if (reTR.PtInRect(point)) // return HTTOPRIGHT; } return HTCLIENT; } void GlwSkin::OnNcLButtonDblClk(UINT nHitTest, CPoint point) { CRect wr; ::GetWindowRect(m_hWnd, wr); ::OffsetRect(&wr, -wr.left, -wr.top); HRGN hRgnWnd(NULL), hRgnDif(NULL); hRgnWnd = ::CreateRectRgn(wr.left, wr.top, wr.right, wr.bottom); if (!m_reOldWnd.IsRectEmpty()) // 本操作为扩展 { hRgnDif = ::CreateRectRgn(m_reOldWnd.left, m_reOldWnd.top, m_reOldWnd.right, m_reOldWnd.bottom); m_reOldWnd.SetRect(0, 0, 0, 0); } else { hRgnDif = ::CreateRectRgn(wr.left, wr.top+m_nTopHeight, wr.right, wr.bottom); ::CombineRgn(hRgnWnd, hRgnWnd, hRgnDif, RGN_DIFF); m_reOldWnd = wr; } ::SetWindowRgn(m_hWnd, hRgnWnd, TRUE); ::DeleteObject(hRgnWnd); ::DeleteObject(hRgnDif); } void GlwSkin::OnNcLButtonDown(UINT nHitTest, CPoint point) { if (nHitTest == HTCLOSE) { m_bCBtnClick = true; m_bCBtnMoveon = false; OnNcPaint(0); return; } else if (nHitTest == HTCAPTION) { m_bNcLBDCaption = true; m_dwOldLong = GetWindowLong(m_hWnd, GWL_EXSTYLE); if (m_bDragTrans) { // global_hwnd = m_hWnd; // global_bNCLD = true; } //透明 // SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)^WS_EX_LAYERED); // ::SetLayeredWindowAttributes(m_hWnd, 0, 123, LWA_ALPHA); } else if (nHitTest == HTBOTTOM || nHitTest == HTLEFT || nHitTest == HTRIGHT) { m_bNcLBDBorder = true; } Default(); } void GlwSkin::OnNcLButtonUp(UINT nHitTest, CPoint point) { m_bCBtnClick = false; if (nHitTest == HTCLOSE) { ::SendMessage(m_hWnd, WM_CLOSE, 0, 0); return; } else if (nHitTest == HTCAPTION) { if (m_bNcLBDCaption) { SetWindowLong(m_hWnd, GWL_EXSTYLE, m_dwOldLong); m_bNcLBDCaption = false; if (m_bDragTrans) { // global_bNCLD = false; // global_hwnd = NULL; // global_bWndMoveStart = false; } } } else if (nHitTest == HTBOTTOM || nHitTest == HTLEFT || nHitTest == HTRIGHT) { if (m_bNcLBDBorder) (CWnd::FromHandle(m_hWnd))->RedrawWindow(); //::PostMessage(m_hWnd, WM_PAINT, 0, 0); m_bNcLBDBorder = false; } OnNcPaint(0); } void GlwSkin::OnNcMouseMove(UINT nHitTest, CPoint point) { if (!m_bCBtnClick && nHitTest == HTCLOSE) { if (!m_bCBtnClick) { m_bCBtnMoveon = true; OnNcPaint(0); } } else { if (m_bCBtnMoveon) { m_bCBtnMoveon = false; OnNcPaint(0); } Default(); } } void GlwSkin::OnGetMinMaxInfo(MINMAXINFO *lpMMI) { lpMMI->ptMinTrackSize = CPoint( m_szMin.cx, m_szMin.cy ); } BOOL GlwSkin::OnEraseBkgnd(CDC *pDC) { return FALSE; } void GlwSkin::OnActivate(UINT nState, CWnd *pWndOther, BOOL bMinimized) { m_bActive = ( nState == WA_ACTIVE || nState == WA_CLICKACTIVE ); OnNcActivate(m_bActive); Default(); } LRESULT GlwSkin::OnSetText(WPARAM wp, LPARAM lp) { TCHAR *str = (TCHAR*)lp; // Default(); m_sTitle = str; OnNcPaint(0); return 0; } CRect GlwSkin::GetCloseBtnRect(bool bScreen) { CRect wr; ::GetWindowRect(m_hWnd, &wr); if (!bScreen) OffsetRect(&wr, -wr.left, -wr.top); //return CRect(CPoint(wr.right-2-10, wr.top+2), CSize(10, 9)); return CRect(CPoint(wr.right-2-12, wr.top+2), CSize(12, 12));//jsx 2015-4-8 14:41:12 } HBRUSH GlwSkin::OnCtlColorDlg( HWND hwnd, CDC *pDc, HWND hDlg ) { if (m_hBrush) ::DeleteObject(m_hBrush); m_hBrush = ::CreateSolidBrush(m_colorDlg); return m_hBrush; } void GlwSkin::SetFont( LPCTSTR name, int fHeight ) { CreateFont(name, fHeight, m_font); OnNcPaint(0); } void GlwSkin::SetLabel( bool bset ) { m_bHasName = bset; if (!m_bHasName) m_nTopHeight = 16;//jsx 2015-4-8 11:12:30 原值13 else m_nTopHeight = 33;//原值30 } void GlwSkin::SerColorDlg(COLORREF colorDlg) { m_colorDlg = colorDlg; }