// DlgControlItem.cpp : 实现文件 // #include "stdafx.h" #include "SkinDialog.h" #include "RenderManager.h" #include "SkinComboBox.h" // CDlgControlItem 对话框 //边框宽度 CONST INT BORDERWIDTH = 3; IMPLEMENT_DYNAMIC(CSkinDialog, CDialog) CSkinDialog::CSkinDialog(UINT nIDTemplate,LPCTSTR lpszFileName/*=NULL*/,CWnd* pParent /*=NULL*/) : CDialog(nIDTemplate, pParent) { m_hMemDC = NULL; m_hMemBmp = m_hOldBmp = NULL; m_bClip = false; if( lpszFileName != NULL ) ParseWindow(lpszFileName); else m_bDefaultSkin = true; m_rcWindowSizeNow.SetRectEmpty(); } CSkinDialog::~CSkinDialog() { if (m_hMemDC != NULL && m_hMemBmp != NULL) { ::SelectObject(m_hMemDC, m_hOldBmp); ::DeleteObject(m_hMemBmp); ::DeleteDC(m_hMemDC); } m_hMemDC = NULL; m_hMemBmp = m_hOldBmp = NULL; } void CSkinDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CSkinDialog, CDialog) ON_WM_PAINT() ON_WM_NCHITTEST() ON_WM_SIZE() ON_WM_GETMINMAXINFO() ON_WM_ERASEBKGND() ON_WM_NCCALCSIZE() ON_WM_NCACTIVATE() ON_WM_SYSCOMMAND() //ON_WM_WINDOWPOSCHANGING() END_MESSAGE_MAP() // CDlgControlItem 消息处理程序 void CSkinDialog::OnPaint() { CPaintDC dc(this); // device context for painting CRect rcClient; GetClientRect(&rcClient); CMemoryDC BufferDC(&dc,rcClient); int cx = 0, cy = 0; if (m_hMemBmp != NULL) { BITMAP bmpInfo = {0}; ::GetObject(m_hMemBmp, sizeof(BITMAP), &bmpInfo); cx = bmpInfo.bmWidth; cy = bmpInfo.bmHeight; } if (rcClient.Width() != cx || rcClient.Height() != cy) { if (m_hMemDC != NULL && m_hMemBmp != NULL) { ::SelectObject(m_hMemDC, m_hOldBmp); ::DeleteObject(m_hMemBmp); } m_hMemBmp = ::CreateCompatibleBitmap(BufferDC.GetSafeHdc(), rcClient.Width(), rcClient.Height()); m_hOldBmp = (HBITMAP)::SelectObject(m_hMemDC, m_hMemBmp); } ::SetBkMode(m_hMemDC,TRANSPARENT); RenderEngine->DrawColor(m_hMemDC,rcClient,m_colBK); CDC*pDC = CDC::FromHandle(m_hMemDC); DrawClientArea(pDC,rcClient.Width(), rcClient.Height()); DrawImage(pDC); DrawString(pDC); ::BitBlt(BufferDC.m_hDC, 0, 0, rcClient.Width(), rcClient.Height(), m_hMemDC, 0, 0, SRCCOPY); } BOOL CSkinDialog::OnInitDialog() { CDialog::OnInitDialog(); SetOwnHwnd(GetSafeHwnd()); HDC hDC = ::GetDC(m_hWnd); m_hMemDC = ::CreateCompatibleDC(hDC); m_hMemBmp = ::CreateCompatibleBitmap(hDC, m_szWindowSize.cx,m_szWindowSize.cy); m_hOldBmp = (HBITMAP)::SelectObject(m_hMemDC, m_hMemBmp); ::ReleaseDC(m_hWnd, hDC); SetExtrude(m_bExtrude); SetWindowPos(NULL,0,0,m_szWindowSize.cx,m_szWindowSize.cy,SWP_NOMOVE); ParseControl(this); RectifyControl(m_szWindowSize.cx,m_szWindowSize.cy); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } LRESULT CSkinDialog::OnNcHitTest(CPoint point) { if( m_bExtrude ) { CRect rcWindow; GetWindowRect(&rcWindow); if ((point.x <= rcWindow.left+BORDERWIDTH) && (point.y>BORDERWIDTH) && (point.y= rcWindow.right-BORDERWIDTH) && (point.y>BORDERWIDTH) && (point.yBORDERWIDTH) && (point.x= rcWindow.bottom-BORDERWIDTH) && (point.x>BORDERWIDTH) && (point.x= rcWindow.right-BORDERWIDTH*2) && (point.y <= rcWindow.top+BORDERWIDTH*2)) return HTTOPRIGHT; else if ((point.x <= rcWindow.left+BORDERWIDTH*2) && (point.y >= rcWindow.bottom-BORDERWIDTH*2)) return HTBOTTOMLEFT; else if ((point.x >= rcWindow.right-BORDERWIDTH*2) && (point.y >= rcWindow.bottom-BORDERWIDTH*2)) return HTBOTTOMRIGHT; return CWnd::OnNcHitTest(point); } else return CDialog::OnNcHitTest(point); } void CSkinDialog::SetExtrude( bool bExtrude ) { m_bExtrude = bExtrude; } BOOL CALLBACK CSkinDialog::EnumChildProc( HWND hWndChild, LPARAM lParam ) { //获取位置 CRect rcWindow; ::GetWindowRect(hWndChild, &rcWindow); //创建区域 if ((rcWindow.Width()>0)&&(rcWindow.Height()>0)) { //变量定义 ASSERT(lParam!=0L); CWnd * pEnumChildInfo=(CWnd *)lParam; //窗口判断 HWND hWndParent=::GetParent(hWndChild); if (hWndParent!=pEnumChildInfo->GetSafeHwnd()) { return TRUE; } static DWORD time = GetTickCount(); if ( GetTickCount() - time > 33) { pEnumChildInfo->Invalidate(FALSE); time = GetTickCount(); } } return TRUE; } void CSkinDialog::SetClipChild( bool bClip ) { m_bClip = bClip; } void CSkinDialog::OnSize(UINT nType, int cx, int cy) { __super::OnSize(nType, cx, cy); if ( m_bClip ) { //EnumChildWindows(GetSafeHwnd(),EnumChildProc,(LPARAM)(CWnd*)this); } //设置圆角 if( (m_szRcSize.cx !=0) && (m_szRcSize.cy != 0) ) { #if defined(WIN32) && !defined(UNDER_CE) if( !IsIconic() && (m_szRcSize.cx != 0 || m_szRcSize.cy != 0) ) { CRect rcWnd; GetWindowRect(&rcWnd); rcWnd.OffsetRect(-rcWnd.left, -rcWnd.top); rcWnd.right++; rcWnd.bottom++; HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, m_szRcSize.cx, m_szRcSize.cy); SetWindowRgn(hRgn, TRUE); DeleteObject(hRgn); } #endif } RectifyControl(cx, cy); if( !m_bDefaultSkin ) OnNcPaint(); } BOOL CSkinDialog::PreTranslateMessage(MSG* pMsg) { if ( pMsg->message == WM_KEYDOWN ) { if ( pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN) { return TRUE; } } return __super::PreTranslateMessage(pMsg); } void CSkinDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { if( m_bDefaultSkin ) return __super::OnGetMinMaxInfo(lpMMI); MONITORINFO oMonitor = {}; oMonitor.cbSize = sizeof(oMonitor); ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTONEAREST), &oMonitor); CRect rcWork = oMonitor.rcWork; CRect rcMonitor = oMonitor.rcMonitor; rcWork.OffsetRect(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top); // 计算最大化时,正确的原点坐标 lpMMI->ptMaxPosition.x = rcWork.left; lpMMI->ptMaxPosition.y = rcWork.top; lpMMI->ptMaxTrackSize.x = m_szMaxSize.cx==0 ? rcWork.Width() : m_szMaxSize.cx; lpMMI->ptMaxTrackSize.y = m_szMaxSize.cy==0 ? rcWork.Height() : m_szMaxSize.cy; lpMMI->ptMinTrackSize.x =m_szMinSize.cx; lpMMI->ptMinTrackSize.y =m_szMinSize.cy; __super::OnGetMinMaxInfo(lpMMI); } void CSkinDialog::RectifyControl( int cx, int cy ) { //移动准备 HDWP hDwp=BeginDeferWindowPos(64); UINT uFlags=SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOZORDER; for (int i=0;i<(int)m_ControlArray.size();i++) { ISkinControl*pControl = m_ControlArray[i]; if ( pControl != NULL ) { CRect rcPos; //////////////////////////////位置//////////////////////////////////////////// if (pControl->m_FixedPostion[0] == en_LTop ) { rcPos.left = pControl->m_ptPosition.x; rcPos.top = pControl->m_ptPosition.y; } else if (pControl->m_FixedPostion[0] == en_RTop ) { rcPos.left = cx-pControl->m_ptPosition.x; rcPos.top = pControl->m_ptPosition.y; } else if (pControl->m_FixedPostion[0] == en_LBottom ) { rcPos.left = pControl->m_ptPosition.x; rcPos.top = cy-pControl->m_ptPosition.y; } else if (pControl->m_FixedPostion[0] == en_RBottom ) { rcPos.left = cx-pControl->m_ptPosition.x; rcPos.top = cy-pControl->m_ptPosition.y; } ///////////////////////////////大小/////////////////////////////////////////// if (pControl->m_FixedPostion[1] == en_LTop ) { rcPos.right = pControl->m_szSize.cx; rcPos.bottom = pControl->m_szSize.cy; } else if (pControl->m_FixedPostion[1] == en_RTop ) { rcPos.right = cx-pControl->m_szSize.cx; rcPos.bottom = pControl->m_szSize.cy; } else if (pControl->m_FixedPostion[1] == en_LBottom ) { rcPos.right = pControl->m_szSize.cx; rcPos.bottom = cy-pControl->m_szSize.cy; } else if (pControl->m_FixedPostion[1] == en_RBottom ) { rcPos.right = cx-pControl->m_szSize.cx; rcPos.bottom = cy-pControl->m_szSize.cy; } DeferWindowPos(hDwp,pControl->m_pOwnWnd->GetSafeHwnd(),NULL,rcPos.left,rcPos.top,rcPos.Width(),rcPos.Height(),SWP_NOACTIVATE); } } //结束调整 LockWindowUpdate(); EndDeferWindowPos(hDwp); UnlockWindowUpdate(); ////重新设置相应的属性,个别属性在设置位置前设置是不好使的 for (int i=0;i<(int)m_ControlArray.size();i++) { ISkinControl*pControl = m_ControlArray[i]; if ( pControl != NULL ) { if(pControl->m_bTransparent) pControl->SetParentBack(m_hMemDC); TCHAR szClassName[MAX_PATH]={0}; GetClassName(pControl->m_pOwnWnd->GetSafeHwnd(),szClassName,_countof(szClassName)); if ( _tcscmp(TEXT("ComboBox"),szClassName) == 0 ) { CSkinComboBox*pComboBox = (CSkinComboBox*)pControl->m_pOwnWnd; pComboBox->SetItemHeight(-1,pComboBox->GetEditItemHeight()); } } } GetWindowRect(&m_rcWindowSizeNow); Invalidate(FALSE); } BOOL CSkinDialog::OnEraseBkgnd(CDC* pDC) { return TRUE; } BOOL CSkinDialog::OnCommand(WPARAM wParam, LPARAM lParam) { switch ( LOWORD(wParam) ) { case 5000: PostQuitMessage(0); break; case 5001: ShowWindow(SW_MINIMIZE); break; } return __super::OnCommand(wParam, lParam); } void CSkinDialog::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp) { if( m_bDefaultSkin ) return __super::OnNcCalcSize(bCalcValidRects,lpncsp); //最大化时,计算当前显示器最适合宽高度 if ( IsZoomed()) { MONITORINFO oMonitor = {}; oMonitor.cbSize = sizeof(oMonitor); ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTONEAREST), &oMonitor); CRect rcWork = oMonitor.rcWork; CRect rcMonitor = oMonitor.rcMonitor; rcWork.OffsetRect(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top); lpncsp->rgrc[0].left += GetSystemMetrics(SM_CXFRAME); lpncsp->rgrc[0].top += GetSystemMetrics(SM_CYSIZEFRAME); lpncsp->rgrc[0].right = lpncsp->rgrc[0].left + rcWork.Width(); lpncsp->rgrc[0].bottom = lpncsp->rgrc[0].top + rcWork.Height(); } return; } BOOL CSkinDialog::OnNcActivate(BOOL bActive) { if( !m_bDefaultSkin ) { //OnNcPaint(); 不能直接调用该方法,Windows采用消息队列形式进行事件处理,直接调用未能将该消息增加到消息队列,所以会出现失去焦点时,出现大粗边框的情况 SendMessage(WM_NCPAINT); return TRUE; } return __super::OnNcActivate(bActive); } LRESULT CSkinDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if( !m_bDefaultSkin ) { if(message == 0x00AE || // WM_NCUAHDRAWCAPTION message == 0x00AF ) // WM_NCUAHDRAWFRAME { return WM_NCPAINT; } } return __super::WindowProc(message, wParam, lParam); } void CSkinDialog::OnSysCommand(UINT nID, LPARAM lParam) { //最大化显示 if ( nID == SC_MAXIMIZE ) { SetMaxWindow(); } else if ( nID == SC_RESTORE ) { SetWindowPos(NULL,m_rcWindowSizeNow.left,m_rcWindowSizeNow.top,m_rcWindowSizeNow.Width(),m_rcWindowSizeNow.Height(),SWP_NOACTIVATE); } __super::OnSysCommand(nID, lParam); } void CSkinDialog::SetMaxWindow() { //CRect rcWork(0,0,0,0); //::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0); //MoveWindow(&rcWork); MONITORINFO oMonitor = {}; oMonitor.cbSize = sizeof(oMonitor); ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTONEAREST), &oMonitor); CRect rcWork = oMonitor.rcWork; CRect rcMonitor = oMonitor.rcMonitor; rcWork.OffsetRect(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top); SetWindowPos(NULL,rcWork.left,rcWork.top,rcWork.Width(),rcWork.Height(),SWP_NOACTIVATE); }