#include "StdAfx.h" #include "..\include\skinwnd.h" #include "..\include\PopupMenuSkin.h" #define safe_delete(p){if(p){delete p;p=NULL;}} // constants used for drawing const int CXGAP = 0; // num pixels between button and text const int CXTEXTMARGIN = 0; // num pixels after hilite to start text const int CXBUTTONMARGIN = 0; // num pixels wider button is than bitmap const int CYBUTTONMARGIN = 0; // ditto for height // identifies owner-draw data as mine const LONG MYITEMID = MAKELONG(MAKEWORD(_T('m'),_T('i')),MAKEWORD(_T('d'),_T('0'))); // private struct: one of these for each owner-draw menu item struct CMyItemData { long magicNum; // magic number identifying me CString text; // item text UINT fType; // original item type flags CMyItemData() { magicNum = MYITEMID; } ~CMyItemData() { text.Empty(); } BOOL IsMyItemData() { return magicNum == MYITEMID; } }; /****************************************** * 函数名 : CSkinWnd * 功能 : 构造函数 *******************************************/ CSkinWnd::CSkinWnd(void) : m_bEnableSkin(TRUE) , m_bTrans(FALSE) { m_bHasMenu = TRUE; //为了让没有主菜单的对话框也支持弹出菜单,此处设置为TRUE,原来是FALSE。以后可以考虑去掉 zsd 20090601 m_hScrollTracking = 0; m_nTrackingBar = 0; m_nTrackingPos = 0; m_nTrackingVal = 0; m_pSkinScrollBar = GetSkin().GetScrollBarSkin(); m_pPopupMenu = GetSkin().GetPopupMenuSkin(); m_colorTrans = GetSkin().m_Application.colorTransparent; m_nHArrowLeftState = keScrollNormal; m_nHArrowRightState = keScrollNormal; m_nHThumbState = keScrollNormal; m_nVArrowTopState = keScrollNormal; m_nVArrowBottomState = keScrollNormal; m_nVThumbState = keScrollNormal; m_nTrackingBar = FALSE; m_rtHScroll= CRect(0,0,0,0); m_rtVScroll = CRect(0,0,0,0); m_nHScrollPos = 0; m_nVScrollPos = 0; SB_InitializeApp(); m_pScrollWnd = NULL; } /****************************************** * 函数名 : ~CSkinWnd * 功能 : 析构函数 *******************************************/ CSkinWnd::~CSkinWnd(void) { SB_UninitializeApp(); } void CSkinWnd::InstallSkin(HWND hWnd) { if(!hWnd) return; } void CSkinWnd::InstallSkin(HWND hWnd,CString strSkinName) { if(!hWnd) return; } void CSkinWnd::LoadSkin() { } /****************************************** * 函数名 : WindowProc * 功能 : 消息处理函数,在此进行处理需要处理的消息 *******************************************/ LRESULT CSkinWnd::WindowProc(UINT msg, WPARAM wp, LPARAM lp) { //当前窗口不存在返回 if ( !IsWindow(m_hWnd) ) return 0; //默认消息处理,不进行换肤 if(!m_bEnableSkin) return Default(); return OnWndMsg(msg, wp, lp); } /****************************************** * 函数名 : OnWndMsg * 功能 : 处理相应窗口消息 *******************************************/ LRESULT CSkinWnd::OnWndMsg(UINT msg, WPARAM wp, LPARAM lp) { switch ( msg ) { //下面非客户区消息处理 case WM_NCPAINT: OnNcPaint( (HRGN)wp ); return 0; case WM_NCCALCSIZE: OnNcCalcSize( (BOOL)wp, (NCCALCSIZE_PARAMS *)lp ); return 0; 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))); return 0; case WM_NCRBUTTONUP: OnNcRButtonUp((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCRBUTTONDOWN: OnNcRButtonDown((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCRBUTTONDBLCLK: OnNcRButtonDblClk((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_NCMOUSEMOVE: OnNcMouseMove( (UINT)wp,CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_SHOWWINDOW: OnShowWindow((BOOL)wp,(UINT)lp); return 0; case WM_PAINT: OnPaint(); return 0; case WM_SIZE: OnSize((UINT)wp,LOWORD(lp),HIWORD(lp)); return 0; case WM_SIZING: OnSizing((UINT)wp,(LPRECT)lp); return 0; case WM_ERASEBKGND: OnEraseBkgnd(CDC::FromHandle(reinterpret_cast(wp))); return 0; case WM_ACTIVATE: OnActivate((UINT)wp, (HWND)lp, 0 ); return 0; case WM_SETCURSOR: return OnSetCursor((HWND)wp,LOWORD(lp), HIWORD(lp)); case WM_LBUTTONUP: OnLButtonUp((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_LBUTTONDOWN: OnLButtonDown((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_MOUSEMOVE: OnMouseMove( (UINT)wp,CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_LBUTTONDBLCLK: OnLButtonDblClk((UINT)wp, CPoint(LOWORD(lp), HIWORD(lp))); return 0; case WM_GETMINMAXINFO: OnGetMinMaxInfo((LPMINMAXINFO)lp); return 0; case WM_DRAWITEM: return OnDrawItem((int)wp,(LPDRAWITEMSTRUCT)lp); case WM_MEASUREITEM: OnMeasureItem((LPMEASUREITEMSTRUCT)lp); return 0; case WM_SYSCOMMAND: OnSysCommand((UINT)wp,lp); return 0; case WM_TIMER: OnTimter((UINT_PTR)wp); return 0; case WM_HSCROLL: OnHScroll(wp,lp); return 0; case WM_SETFOCUS: OnSetFocus((HWND)wp); return 0; case WM_KILLFOCUS: OnKillFocus((HWND)wp); return 0; case WM_ENABLE: OnEnable((BOOL)wp); return 0; case WM_SETTEXT: OnSetText(wp,lp); return 0; case WM_SETICON: return OnSetIcon((UINT)wp,(HICON)lp); case WM_INITMENUPOPUP: OnInitMenuPopup(CMenu::FromHandle((HMENU)wp), (UINT)LOWORD(lp), (BOOL)HIWORD(lp)); return 0; case WM_MENUSELECT: OnMenuSelect((UINT)LOWORD(wp), (UINT)HIWORD(wp), (HMENU)lp); return 0; case WM_MENUCHAR: return OnMenuChar((TCHAR)LOWORD(wp), (UINT)HIWORD(wp), CMenu::FromHandle((HMENU)lp)); case WM_CAPTURECHANGED: OnCaptureChanged(wp,lp); return 0; case WM_DESTROY: OnDestroy(); return 0; //消息处理 default: return Default(); } return 0; } /****************************************** * 函数名 : OnDestroy * 功能 : *******************************************/ void CSkinWnd::OnDestroy() { Default(); } /****************************************** * 函数名 : OnCaptureChanged * 功能 : *******************************************/ void CSkinWnd::OnCaptureChanged(WPARAM wp,LPARAM lp) { Default(); } /****************************************** * 函数名 : OnInitMenuPopup * 功能 : *******************************************/ void CSkinWnd::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu) { if(m_bHasMenu) ConvertMenu(pMenu, nIndex, bSysMenu, TRUE); else Default(); } /****************************************** * 函数名 : OnMenuChar * 功能 : *******************************************/ LRESULT CSkinWnd::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu) { if(m_bHasMenu) { ASSERT_VALID(pMenu); UINT iCurrentItem = (UINT)-1; CUIntArray arItemsMatched; UINT nItem = pMenu->GetMenuItemCount(); for (UINT i=0; i< nItem; i++) { CMenuItemInfo info; info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_STATE; ::GetMenuItemInfo(*pMenu, i, TRUE, (MENUITEMINFO *)&info); CMyItemData* pmd = (CMyItemData*)info.dwItemData; if ((info.fType & MFT_OWNERDRAW) && pmd && pmd->IsMyItemData()) { CString& text = pmd->text; int iAmpersand = text.Find(_T('&')); if (iAmpersand >=0 && toupper(nChar)==toupper(text[iAmpersand+1])) arItemsMatched.Add(i); } if (info.fState & MFS_HILITE) iCurrentItem = i; // note index of current item } UINT nFound = (UINT)arItemsMatched.GetSize(); if (nFound == 0) return 0; else if (nFound==1) return MAKELONG(arItemsMatched[0], MNC_EXECUTE); // more than one found--return 1st one past current selected item; UINT iSelect = 0; for (int i=0; i < nFound; i++) { if (arItemsMatched[i] > iCurrentItem) { iSelect = i; break; } } return MAKELONG(arItemsMatched[iSelect], MNC_SELECT); } else return Default(); } /****************************************** * 函数名 : OnMenuSelect * 功能 : *******************************************/ void CSkinWnd::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu) { if(m_bHasMenu) { if (hSysMenu==NULL && nFlags==0xFFFF) { // Windows has closed the menu: restore all menus to original state while (!m_menuList.IsEmpty()) { ConvertMenu(CMenu::FromHandle((HMENU)m_menuList.RemoveHead()), 0, FALSE, FALSE); } } } Default(); } /****************************************** * 函数名 : OnSetIcon * 功能 : 设置窗口的图标 *******************************************/ LRESULT CSkinWnd::OnSetIcon(UINT nFlag,HICON hIcon) { return Default(); } /****************************************** * 函数名 : OnEnable * 功能 : 窗口状态发生变化时调用 *******************************************/ void CSkinWnd::OnSetText(WPARAM wp,LPARAM lp) { Default(); } /****************************************** * 函数名 : OnEnable * 功能 : 窗口状态发生变化时调用 *******************************************/ void CSkinWnd::OnEnable(BOOL bEnable) { Default(); } /****************************************** * 函数名 : OnNcRButtonUp * 功能 : 非客户区用户放开鼠标右键调用 *******************************************/ void CSkinWnd::OnNcRButtonUp( UINT nHitTest, CPoint point) { Default(); } /****************************************** * 函数名 : OnNcRButtonDown * 功能 : 非客户区用户按下鼠标右键调用 *******************************************/ void CSkinWnd::OnNcRButtonDown( UINT nHitTest, CPoint point ) { Default(); } /****************************************** * 函数名 : OnNcRButtonDblClk * 功能 : 非客户区用户双击鼠标右键调用 *******************************************/ void CSkinWnd::OnNcRButtonDblClk(UINT nHitTest, CPoint point) { Default(); } /****************************************** * 函数名 : OnNcMouseMove * 功能 : 非客户区鼠标移动 *******************************************/ void CSkinWnd::OnNcMouseMove( UINT nHitTest, CPoint point ) { Default(); } /****************************************** * 函数名 : OnNcLButtonUp * 功能 : 非客户区放开鼠标左键 *******************************************/ void CSkinWnd::OnNcLButtonUp( UINT nHitTest, CPoint point ) { Default(); } /****************************************** * 函数名 : OnNcLButtonDown * 功能 : 非客户区按下鼠标左键 *******************************************/ void CSkinWnd::OnNcLButtonDown( UINT nHitTest, CPoint point ) { Default(); } /****************************************** * 函数名 : OnNcLButtonDblClk * 功能 : 非客户区双击鼠标左键 *******************************************/ void CSkinWnd::OnNcLButtonDblClk( UINT nHitTest, CPoint point ) { Default(); } /****************************************** * 函数名 : OnNcHitTest * 功能 : 当鼠标移动时调用此函数 *******************************************/ UINT CSkinWnd::OnNcHitTest( CPoint point ) { return (UINT)Default(); } /****************************************** * 函数名 : OnNcActivate * 功能 : 改变非客户区活动或非活动状态调用 *******************************************/ BOOL CSkinWnd::OnNcActivate( BOOL bActive ) { return (BOOL)Default(); } /****************************************** * 函数名 : OnNcCalcSize * 功能 : 当计算非客户区大小和位置时调用 *******************************************/ void CSkinWnd::OnNcCalcSize( BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp) { Default(); } /****************************************** * 函数名 : OnNcPaint * 功能 : 当非客户需要重画时调用 *******************************************/ void CSkinWnd::OnNcPaint(HRGN rgn1) { Default(); } /****************************************** * 函数名 : OnShowWindow * 功能 : 当窗口被隐藏或显示调用 *******************************************/ void CSkinWnd::OnShowWindow( BOOL bShow, UINT nStatus) { Default(); } /****************************************** * 函数名 : OnPaint * 功能 : 当客户需要重画时调用 *******************************************/ void CSkinWnd::OnPaint() { Default(); } /****************************************** * 函数名 : OnSize * 功能 : 当窗口的大小被改变后调用 *******************************************/ void CSkinWnd::OnSize(UINT nType, int cx, int cy ) { Default(); } /****************************************** * 函数名 : OnSizing * 功能 : 用户正在改变窗口的大小 *******************************************/ BOOL CSkinWnd::OnSizing(UINT fwSide, LPRECT pRect) { return (BOOL)Default(); } /****************************************** * 函数名 : OnEraseBkgnd * 功能 : 查除窗口的背景调用 *******************************************/ BOOL CSkinWnd::OnEraseBkgnd(CDC* pDC) { CWnd *pWnd = CWnd::FromHandle(m_hWnd); CRect rtClient; pWnd->GetClientRect( rtClient ); return (BOOL)Default(); } /****************************************** * 函数名 : OnSetCursor * 功能 : 光标在窗口移动时调用 *******************************************/ BOOL CSkinWnd::OnSetCursor(HWND hWnd, UINT nHitTest, UINT message) { return (BOOL)Default(); } /****************************************** * 函数名 : OnSetFocus * 功能 : 窗口获得输入焦点时调用 *******************************************/ void CSkinWnd::OnSetFocus(HWND hWnd) { Default(); } /****************************************** * 函数名 : OnSetFocus * 功能 : 窗口失去输入焦点时调用 *******************************************/ void CSkinWnd::OnKillFocus(HWND hWnd) { Default(); } /****************************************** * 函数名 : OnActivateApp * 功能 : 应用程序被激活或退出激活状态时调用 *******************************************/ void CSkinWnd::OnActivateApp(BOOL bActive, HTASK hTask) { Default(); } /****************************************** * 函数名 : OnNcPaint * 功能 : 当需要知道最大化的位置和大小,或最小或最大跟踪尺寸时调用 *******************************************/ void CSkinWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { Default(); } /****************************************** * 函数名 : OnMouseMove * 功能 : 鼠标移动时调用 *******************************************/ void CSkinWnd::OnMouseMove(UINT nFlags, CPoint point) { Default(); } /****************************************** * 函数名 : OnLButtonDown * 功能 : 鼠标左键按下时调用 *******************************************/ void CSkinWnd::OnLButtonDown(UINT nFlags, CPoint point) { Default(); } /****************************************** * 函数名 : OnLButtonUp * 功能 : 鼠标左键放开时调用 *******************************************/ void CSkinWnd::OnLButtonUp(UINT nFlags, CPoint point) { Default(); } /****************************************** * 函数名 : OnLButtonDblClk * 功能 : 鼠标左键双击时调用 *******************************************/ void CSkinWnd::OnLButtonDblClk(UINT nFlags, CPoint point) { Default(); } /****************************************** * 函数名 : OnVScroll * 功能 : 用户单击窗口垂直滚动条调用 *******************************************/ void CSkinWnd::OnVScroll(WPARAM wParam, LPARAM lParam) { Default(); } /****************************************** * 函数名 : OnHScroll * 功能 : 用户单击窗口水平滚动条调用 *******************************************/ void CSkinWnd::OnHScroll(WPARAM wParam, LPARAM lParam) { Default(); } /****************************************** * 函数名 : OnNotify * 功能 : *******************************************/ LRESULT CSkinWnd::OnNotify(WPARAM wParam, LPARAM lParam) { return Default(); } /****************************************** * 函数名 : OnNotify * 功能 : *******************************************/ void CSkinWnd::OnNotify(UINT uNotify, UINT uID, CWnd* pCtrl) { Default(); } /****************************************** * 函数名 : OnNotifyReflect * 功能 : *******************************************/ LRESULT CSkinWnd::OnNotifyReflect(NMHDR* pNMHDR, LRESULT lrParent) { return Default(); } /****************************************** * 函数名 : OnNotifyReflect * 功能 : *******************************************/ void CSkinWnd::OnNotifyReflect(UINT uNotify, LRESULT lrParent) { Default(); } /****************************************** * 函数名 : OnStyleChanged * 功能 : *******************************************/ void CSkinWnd::OnStyleChanged(int nStyleType,LPSTYLESTRUCT lpStyleStruct) { Default(); } /****************************************** * 函数名 : OnSysCommand * 功能 : *******************************************/ void CSkinWnd::OnSysCommand(UINT nID, LPARAM lParam ) { Default(); } /****************************************** * 函数名 : OnDrawItem * 功能 : *******************************************/ BOOL CSkinWnd::OnDrawItem(int nIDCtrl,LPDRAWITEMSTRUCT lpds) { if(m_bHasMenu && (lpds->CtlType == ODT_MENU)) { CMenuItemInfo info; CRect rcText; CMyItemData* pmd = (CMyItemData*)lpds->itemData; ASSERT(pmd); if (!pmd->IsMyItemData()) return FALSE; ASSERT(lpds->itemAction != ODA_FOCUS); ASSERT(lpds->hDC); CDC dc; dc.Attach(lpds->hDC); const CRect& rcItem = lpds->rcItem; if (pmd->fType & MFT_SEPARATOR) { // draw separator CRect rc = rcItem; DrawSeparator(rc,dc); } else { // not a separator BOOL bDisabled = lpds->itemState & ODS_GRAYED; BOOL bSelected = lpds->itemState & ODS_SELECTED; BOOL bChecked = lpds->itemState & ODS_CHECKED; BOOL bHaveButn=FALSE; int cxButn = 0; // width of button //COLORREF colorBG = bSelected ? GuiDrawLayer::GetRGBFondoXP(): GetSysColor(WHITE_PEN) ; CRect rcBG = rcItem; if (bSelected || lpds->itemAction==ODA_SELECT) { if (bSelected && !bDisabled) PLSelectRect(dc, rcBG); else PLNormalRect(dc, rcBG); } else PLNormalRect(dc, rcBG); // compute text rectangle and colors rcText = rcItem; // start w/whole item rcText.left += cxButn + CXGAP + CXTEXTMARGIN+11; // left margin rcText.right -= cxButn; // right margin dc.SetBkMode(TRANSPARENT); // paint transparent text COLORREF colorText =m_pPopupMenu->m_itemPopup.textNormal; if (bDisabled) { DrawMenuText(dc, rcText + CPoint(1,1), pmd->text, m_pPopupMenu->m_itemPopup.textGrayed); } else if(bSelected) { DrawMenuText(dc, rcText + CPoint(1,1), pmd->text, m_pPopupMenu->m_itemPopup.textActive); } else DrawMenuText(dc, rcText, pmd->text, colorText); // finally! } dc.Detach(); return TRUE; // handled } else return (BOOL)Default(); } /****************************************** * 函数名 : OnMeasureItem * 功能 : *******************************************/ BOOL CSkinWnd::OnMeasureItem(LPMEASUREITEMSTRUCT lpms) { if(m_bHasMenu && (lpms->CtlType == ODT_MENU)) { ASSERT(lpms); CMyItemData* pmd = (CMyItemData*)lpms->itemData; ASSERT(pmd); if (lpms->CtlType != ODT_MENU || !pmd->IsMyItemData()) return FALSE; // not handled by me if (pmd->fType & MFT_SEPARATOR) { // separator: use half system height and zero width lpms->itemHeight = GetSystemMetrics(SM_CYMENU)>>1; lpms->itemWidth = 0; } else { CWindowDC dc(NULL); // screen DC--I won't actually draw on it CRect rcText(0,0,0,0); dc.DrawText(pmd->text, rcText, DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT); lpms->itemHeight= max(GetSystemMetrics(SM_CYMENU), rcText.Height()); int cx = rcText.Width()+20; cx += CXTEXTMARGIN<<1; cx += CXGAP; cx -= GetSystemMetrics(SM_CXMENUCHECK)-1; lpms->itemWidth = cx+20; // done deal lpms->itemHeight+=2; } return TRUE; // handled } else return (BOOL)Default(); } /****************************************** * 函数名 : OnMeasureItem * 功能 : *******************************************/ void CSkinWnd::OnActivate(UINT nState, HWND hWnd, BOOL bMinimized) { Default(); } void CSkinWnd::OnTimter(UINT_PTR nIDEvent) { Default(); CWnd *pWnd = CWnd::FromHandle(m_hWnd); CDC * pDC = pWnd->GetWindowDC(); /*if(m_bHScroll) DrawHScrollBar(pDC); if(m_bVScroll) DrawVScrollBar(pDC);*/ } void CSkinWnd::DrawHScrollBar(CDC *pDC) { CRect rtWindow; GetWindowRect(&rtWindow); CRect rtPos; int nArrowSize; int nThumbSize; int nThumbPos; GetScrollRect(SB_HORZ,&rtPos,&nArrowSize,&nThumbSize,&nThumbPos); CMemDC memDC(pDC,rtPos); m_pSkinScrollBar->DrawHBackground(&memDC,rtPos); m_pSkinScrollBar->DrawHArrowLeft(&memDC,CRect(rtPos.left,rtPos.top,rtPos.left + nArrowSize,rtPos.bottom),m_nHArrowLeftState); m_pSkinScrollBar->DrawHArrowRight(&memDC,CRect(rtPos.right - nArrowSize,rtPos.top,rtPos.right,rtPos.bottom),m_nHArrowRightState); if(nThumbSize) m_pSkinScrollBar->DrawHThumb(&memDC,CRect(rtPos.left + nThumbPos,rtPos.top+1,rtPos.left +nThumbPos + nThumbSize,rtPos.bottom-1),m_nHThumbState); } void CSkinWnd::DrawVScrollBar(CDC *pDC) { CRect rtWindow; GetWindowRect(&rtWindow); CRect rtPos; int nArrowSize; int nThumbSize; int nThumbPos; GetScrollRect(SB_VERT,&rtPos,&nArrowSize,&nThumbSize,&nThumbPos); CMemDC memDC(pDC,rtPos); m_pSkinScrollBar->DrawVBackground(&memDC,rtPos); m_pSkinScrollBar->DrawVArrowTop(&memDC,CRect(rtPos.left,rtPos.top,rtPos.right ,rtPos.top + nArrowSize),m_nVArrowTopState); m_pSkinScrollBar->DrawVArrowBottom(&memDC,CRect(rtPos.left,rtPos.bottom - nArrowSize,rtPos.right,rtPos.bottom),m_nVArrowBottomState); if(nThumbSize) m_pSkinScrollBar->DrawVThumb(&memDC,CRect(rtPos.left+1,rtPos.top +nThumbPos,rtPos.right -1,rtPos.top + +nThumbPos + nThumbSize),m_nVThumbState); } /****************************************** * 函数名 : GetScrollRect * 功能 : 计算滚动条的区域等大小根据绘制坐标系统 *******************************************/ BOOL CSkinWnd::GetScrollRect(int nBar,LPRECT lpRect,int *nArrowSize,int *nThumbSize,int *nThumbPos) { CRect rtClient,rtWindow; int pixels; BOOL vertical; GetClientRect(&rtClient); ClientToScreen(&rtClient); GetWindowRect(&rtWindow); switch(nBar) { case SB_HORZ: lpRect->left = rtClient.left - rtWindow.left; lpRect->top = rtClient.bottom - rtWindow.top; lpRect->right = rtClient.right - rtWindow.left; lpRect->bottom = lpRect->top + GetSystemMetrics(SM_CYHSCROLL); vertical = FALSE; break; case SB_VERT: if((GetExStyle() & WS_EX_LEFTSCROLLBAR) != 0) lpRect->left = rtClient.left - rtWindow.left - GetSystemMetrics(SM_CXVSCROLL); else lpRect->left = rtClient.right - rtWindow.left; lpRect->top = rtClient.top - rtWindow.top; lpRect->right = lpRect->left + GetSystemMetrics(SM_CXVSCROLL); lpRect->bottom = rtClient.bottom - rtWindow.top; vertical = TRUE; break; case SB_CTL: GetClientRect(lpRect ); vertical = ((GetStyle() & SBS_VERT) != 0); break; default: return FALSE; } if (vertical) pixels = lpRect->bottom - lpRect->top; else pixels = lpRect->right - lpRect->left; if (pixels <= 2*GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT) { if (pixels > SCROLL_MIN_RECT) *nArrowSize = (pixels - SCROLL_MIN_RECT) / 2; else *nArrowSize = 0; *nThumbPos = *nThumbSize = 0; } else { SCROLLINFO info ; ::ZeroMemory((void*)&info,sizeof(info)); info.cbSize = sizeof(SCROLLINFO); info.fMask = SIF_ALL; GetScrollInfo( m_hWnd, nBar, &info ); if(info.nPos < info.nMin) info.nPos = info.nMin; if(info.nPos > info.nMax) info.nPos = info.nMax; *nArrowSize = GetSystemMetrics(SM_CXVSCROLL); pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)); if (info.nPage) { *nThumbSize = MulDiv(pixels,info.nPage,(info.nMax - info.nMin+1)); if (*nThumbSize < SCROLL_MIN_THUMB) *nThumbSize = SCROLL_MIN_THUMB; } else *nThumbSize = GetSystemMetrics(SM_CXVSCROLL); if(info.nPage >= info.nMax -info.nMin + 1) { *nThumbPos = 0; *nThumbSize = 0; return vertical; } if ((pixels -= *nThumbSize ) < 0 ) { /* Rectangle too small or scrollbar disabled -> no thumb */ *nThumbPos = *nThumbSize = 0; } else { INT max = info.nMax - max( info.nPage-1, 0 ); if (info.nMin >= max) *nThumbPos = *nArrowSize - SCROLL_ARROW_THUMB_OVERLAP; else *nThumbPos = *nArrowSize - SCROLL_ARROW_THUMB_OVERLAP + MulDiv(pixels, (info.nPos-info.nMin),(max - info.nMin)); } } return vertical; } SCROLL_HITTEST CSkinWnd::ScrollHitTest(int nBar,CPoint pt, BOOL bDragging ) { int arrowSize, thumbSize, thumbPos; CRect rect; BOOL vertical = GetScrollRect(nBar, &rect, &arrowSize, &thumbSize, &thumbPos ); if ( !rect.PtInRect( pt ) ) return SCROLL_NOWHERE; if (vertical) { if (pt.y < rect.top + arrowSize) return SCROLL_TOP_ARROW; if (pt.y >= rect.bottom - arrowSize) return SCROLL_BOTTOM_ARROW; if (!thumbPos) return SCROLL_TOP_RECT; pt.y -= rect.top; if (pt.y < thumbPos) return SCROLL_TOP_RECT; if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT; } else /* horizontal */ { if (pt.x < rect.left + arrowSize) return SCROLL_TOP_ARROW; if (pt.x >= rect.right - arrowSize) return SCROLL_BOTTOM_ARROW; if (!thumbPos) return SCROLL_TOP_RECT; pt.x -= rect.left; if (pt.x < thumbPos) return SCROLL_TOP_RECT; if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT; } return SCROLL_THUMB; } BOOL CSkinWnd::IsScrollInfoActive(SCROLLINFO *si) { if((si->nPage > (UINT)si->nMax || si->nMax <= si->nMin || si->nMax == 0)) return FALSE; else return TRUE; } static TCHAR szPropStr[] = _T("SkinScrollBarPtr"); BOOL CSkinWnd::InitializeSB(HWND hwnd) { SCROLLWND *sw; SCROLLINFO *si; RECT rect; DWORD dwCurStyle; //BOOL fDisabled; ::GetClientRect(hwnd, &rect); //if we have already initialized Cool Scrollbars for this window, //then stop the user from doing it again if(GetScrollWndFromHwnd(hwnd) != 0) { return FALSE; } //allocate a private scrollbar structure which we //will use to keep track of the scrollbar data sw = (SCROLLWND *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SCROLLWND)); si = &sw->sbarHorz.scrollInfo; si->cbSize = sizeof(SCROLLINFO); si->fMask = SIF_ALL; GetScrollInfo(hwnd, SB_HORZ, si); si = &sw->sbarVert.scrollInfo; si->cbSize = sizeof(SCROLLINFO); si->fMask = SIF_ALL; GetScrollInfo(hwnd, SB_VERT, si); //check to see if the window has left-aligned scrollbars if(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR) sw->fLeftScrollbar = TRUE; else sw->fLeftScrollbar = FALSE; dwCurStyle = GetWindowLong(hwnd, GWL_STYLE); SetProp(hwnd, szPropStr, (HANDLE)sw); if(dwCurStyle & WS_HSCROLL) sw->sbarHorz.fScrollFlags = CSBS_VISIBLE; if(dwCurStyle & WS_VSCROLL) sw->sbarVert.fScrollFlags = CSBS_VISIBLE; //need to be able to distinguish between horizontal and vertical //scrollbars in some instances sw->sbarHorz.nBarType = SB_HORZ; sw->sbarVert.nBarType = SB_VERT; //set the default arrow sizes for the scrollbars sw->sbarHorz.nArrowLength = 0; sw->sbarHorz.nArrowWidth = 0; sw->sbarVert.nArrowLength = 0; sw->sbarVert.nArrowWidth = 0; sw->bPreventStyleChange = FALSE; return TRUE; } HRESULT CSkinWnd::UninitializeSB(HWND hwnd) { int i = 0; SCROLLWND *sw = GetScrollWndFromHwnd(hwnd); if(!sw) return E_FAIL; //restore the window procedure with the original one SetWindowLong(hwnd, GWL_WNDPROC, (LONG)sw->oldproc); RemoveProp(hwnd, szPropStr); //SetWindowLong(hwnd, GWL_USERDATA, 0); //finally, release the memory needed for the cool scrollbars HeapFree(GetProcessHeap(), 0, sw); //Force WM_NCCALCSIZE and WM_NCPAINT so the original scrollbars can kick in // RedrawNonClient(hwnd, TRUE); return S_OK; } /****************************************** * 函数名 : GetScroolThumbVal * 功能 : 根据thumb的位置计算滚动条值 *******************************************/ UINT CSkinWnd::GetScroolThumbVal( SCROLLINFO *infoPtr, RECT *rect, BOOL vertical, INT pos ) { INT thumbSize; INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left; if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0) return infoPtr->nMin; if (infoPtr->nPage) { thumbSize = MulDiv(pixels,infoPtr->nPage,(infoPtr->nMax-infoPtr->nMin+1)); if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB; } else thumbSize = GetSystemMetrics(SM_CXVSCROLL); if ((pixels -= thumbSize) <= 0) return infoPtr->nMin; pos = max( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) ); if (pos > pixels) pos = pixels; if (!infoPtr->nPage) pos *= infoPtr->nMax - infoPtr->nMin; else pos *= infoPtr->nMax - infoPtr->nMin - infoPtr->nPage + 1; return infoPtr->nMin + ((pos + pixels / 2) / pixels); } /*********************************************************************** * HandleScrollEvent * * Handle a mouse or timer event for the scrollbar. * 'pt' is the location of the mouse event in client (for SB_CTL) or * windows coordinates. * ************************************************************************/ void CSkinWnd::HandleScrollEvent(int nBar,UINT msg,CPoint pt) { /* Previous mouse position for timer events */ static POINT prevPt; /* Thumb position when tracking started. */ static UINT trackThumbPos; /* Position in the scroll-bar of the last button-down event. */ static INT lastClickPos; /* Position in the scroll-bar of the last mouse event. */ static INT lastMousePos; enum SCROLL_HITTEST hittest; HWND hwndOwner, hwndCtl; BOOL vertical; INT arrowSize, thumbSize, thumbPos; RECT rect; HDC hdc; SCROLLINFO info; info.cbSize = sizeof(info); info.fMask = SIF_ALL; GetScrollInfo( m_hWnd, nBar, &info); if ((m_nScrollHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) return; if (nBar == SB_CTL && (GetWindowLong( m_hWnd, GWL_STYLE ) & (SBS_SIZEGRIP | SBS_SIZEBOX))) { switch(msg) { case WM_LBUTTONDOWN: /* Initialise mouse tracking */ SetCapture( m_hWnd ); prevPt = pt; m_nScrollHitTest = hittest = SCROLL_THUMB; break; case WM_MOUSEMOVE: ::GetClientRect(::GetParent(::GetParent(m_hWnd)),&rect); prevPt = pt; break; case WM_LBUTTONUP: ReleaseCapture(); m_nScrollHitTest = hittest = SCROLL_NOWHERE; // if (m_hWnd==GetFocus()) ShowCaret(m_hWnd); break; case WM_TIMER: pt = prevPt; break; } return; } hdc = GetDCEx( m_hWnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW)); CDC *pDC = CDC::FromHandle(hdc); vertical = GetScrollRect( nBar, &rect,&arrowSize, &thumbSize, &thumbPos ); hwndOwner = (nBar == SB_CTL) ?:: GetParent(m_hWnd) : m_hWnd; hwndCtl = (nBar == SB_CTL) ? m_hWnd : 0; switch(msg) { case WM_LBUTTONDOWN: /* Initialise mouse tracking */ m_bScrollVertical = vertical; m_nScrollHitTest = hittest = ScrollHitTest(nBar, pt, FALSE ); lastClickPos = vertical ? (pt.y - rect.top) : (pt.x - rect.left); lastMousePos = lastClickPos; trackThumbPos = thumbPos; prevPt = pt; if (nBar == SB_CTL && (GetWindowLong(m_hWnd, GWL_STYLE) & WS_TABSTOP)) SetFocus( m_hWnd ); SetCapture( m_hWnd ); break; case WM_MOUSEMOVE: hittest = ScrollHitTest( nBar, pt, TRUE ); prevPt = pt; break; case WM_LBUTTONUP: hittest = SCROLL_NOWHERE; ReleaseCapture(); break; case WM_TIMER: pt = prevPt; hittest = ScrollHitTest(nBar, pt, FALSE ); break; default: return; /* Should never happen */ } switch(m_nScrollHitTest) { case SCROLL_NOWHERE: /* No tracking in progress */ break; case SCROLL_TOP_ARROW: if (hittest == m_nScrollHitTest) { if(m_bScrollVertical) { m_nVArrowTopState = keScrollPressed; m_nVArrowBottomState = keScrollNormal; m_nVThumbState = keScrollNormal; // DrawVScrollBar(pDC); m_pSkinScrollBar->DrawVArrowTop(pDC,CRect(rect.left,rect.top,rect.right,rect.top + arrowSize),m_nVArrowTopState); } else { m_nHArrowLeftState = keScrollPressed; m_nHArrowRightState = keScrollNormal; m_nHThumbState = keScrollNormal; // DrawHScrollBar(pDC); m_pSkinScrollBar->DrawHArrowLeft(pDC,CRect(rect.left,rect.top,rect.left + arrowSize,rect.bottom),m_nHArrowLeftState); } if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER)) { ::SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_LINEUP, (LPARAM)hwndCtl ); } SetTimer( m_hWnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC)0 ); } else { if(m_bScrollVertical) { m_nVArrowTopState = keScrollNormal; m_nVArrowBottomState = keScrollNormal; m_nVThumbState = keScrollNormal; DrawVScrollBar(pDC); } else { m_nHArrowLeftState = keScrollNormal; m_nHArrowRightState = keScrollNormal; m_nHThumbState = keScrollNormal; DrawHScrollBar(pDC); } KillTimer( m_hWnd, SCROLL_TIMER ); } break; case SCROLL_TOP_RECT: if(m_bScrollVertical) DrawVScrollBar(pDC); else DrawHScrollBar(pDC); if (hittest == m_nScrollHitTest) { if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER)) { SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_PAGEUP, (LPARAM)hwndCtl ); } SetTimer( m_hWnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC)0 ); } else KillTimer( m_hWnd, SCROLL_TIMER ); break; case SCROLL_THUMB: if (msg == WM_LBUTTONDOWN) { if(m_pScrollWnd) { m_pScrollWnd->fThumbTracking = TRUE; if(vertical) m_pScrollWnd->sbarVert.scrollInfo.nTrackPos = m_pScrollWnd->sbarVert.scrollInfo.nPos; else m_pScrollWnd->sbarHorz.scrollInfo.nTrackPos = m_pScrollWnd->sbarHorz.scrollInfo.nPos; } m_hScrollTracking = m_hWnd; m_nTrackingBar = nBar; m_nTrackingPos = trackThumbPos + lastMousePos - lastClickPos; m_nTrackingVal = GetScroolThumbVal( &info, &rect,vertical,m_nTrackingPos ); if(m_pScrollWnd) { if(vertical) m_pScrollWnd->sbarVert.scrollInfo.nTrackPos = m_nTrackingVal; else m_pScrollWnd->sbarHorz.scrollInfo.nTrackPos = m_nTrackingVal; } if(m_bScrollVertical) { m_nVArrowTopState = keScrollNormal; m_nVArrowBottomState = keScrollNormal; m_nVThumbState = keScrollPressed; DrawVScrollBar(pDC); } else { m_nHArrowLeftState = keScrollNormal; m_nHArrowRightState = keScrollNormal; m_nHThumbState = keScrollPressed; DrawHScrollBar(pDC); } if (!m_nTrackingBar) DrawMovingThumb(pDC, vertical,rect, arrowSize, thumbSize); } else if (msg == WM_LBUTTONUP) { if(m_pScrollWnd) m_pScrollWnd->fThumbTracking = FALSE; if (m_nTrackingBar) DrawMovingThumb(pDC, vertical,rect, arrowSize, thumbSize); } else /* WM_MOUSEMOVE */ { UINT pos; //if (!PtInRect( &rect, pt )) //{ //// pos = lastClickPos; //} //else { pos = vertical ? (pt.y - rect.top) : (pt.x - rect.left); } if ( (pos != lastMousePos) || (!m_nTrackingBar) ) { if (m_nTrackingBar) DrawMovingThumb( pDC,vertical, rect, arrowSize, thumbSize ); lastMousePos = pos; m_nTrackingPos = trackThumbPos + pos - lastClickPos; m_nTrackingVal = GetScroolThumbVal( &info, &rect, vertical, m_nTrackingPos ); if(m_pScrollWnd) { if(vertical) m_pScrollWnd->sbarVert.scrollInfo.nTrackPos = m_nTrackingVal; else m_pScrollWnd->sbarHorz.scrollInfo.nTrackPos = m_nTrackingVal; } SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM( SB_THUMBTRACK, m_nTrackingVal), (LPARAM)hwndCtl ); if (!m_nTrackingBar) DrawMovingThumb( pDC,vertical, rect,arrowSize, thumbSize ); } } break; case SCROLL_BOTTOM_RECT: if(m_bScrollVertical) DrawVScrollBar(pDC); else DrawHScrollBar(pDC); if (hittest == m_nScrollHitTest) { if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER)) { SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_PAGEDOWN, (LPARAM)hwndCtl ); } SetTimer( m_hWnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC)0 ); } else KillTimer( m_hWnd, SCROLL_TIMER ); break; case SCROLL_BOTTOM_ARROW: if (hittest == m_nScrollHitTest) { if(m_bScrollVertical) { m_nVArrowTopState = keScrollPressed; m_nVArrowBottomState = keScrollNormal; m_nVThumbState = keScrollNormal; m_pSkinScrollBar->DrawVArrowBottom(pDC,CRect(rect.left,rect.bottom - arrowSize,rect.right,rect.bottom),m_nVArrowTopState); } else { m_nHArrowLeftState = keScrollNormal; m_nHArrowRightState = keScrollPressed; m_nHThumbState = keScrollNormal; m_pSkinScrollBar->DrawHArrowRight(pDC,CRect(rect.right - arrowSize,rect.top,rect.right,rect.bottom),m_nHArrowLeftState); } if ((msg == WM_LBUTTONDOWN) || (msg == WM_TIMER)) { SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_LINEDOWN, (LPARAM)hwndCtl ); } SetTimer( m_hWnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC)0 ); } else { if(m_bScrollVertical) { m_nVArrowTopState = keScrollNormal; m_nVArrowBottomState = keScrollNormal; m_nVThumbState = keScrollNormal; DrawVScrollBar(pDC); } else { m_nHArrowLeftState = keScrollNormal; m_nHArrowRightState = keScrollNormal; m_nHThumbState = keScrollNormal; DrawHScrollBar(pDC); } KillTimer( m_hWnd, SCROLL_TIMER ); } break; } if (msg == WM_LBUTTONDOWN) { if (hittest == SCROLL_THUMB) { UINT val = GetScroolThumbVal( &info, &rect, vertical, trackThumbPos + lastMousePos - lastClickPos ); SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)hwndCtl ); if(m_bScrollVertical) { m_nVArrowTopState = keScrollNormal; m_nVArrowBottomState = keScrollNormal; m_nVThumbState = keScrollPressed; DrawVScrollBar(pDC); } else { m_nHArrowLeftState = keScrollNormal; m_nHArrowRightState = keScrollNormal; m_nHThumbState = keScrollPressed; DrawHScrollBar(pDC); } } } if (msg == WM_LBUTTONUP) { hittest =(SCROLL_HITTEST) m_nScrollHitTest; m_nScrollHitTest = SCROLL_NOWHERE; /* Terminate tracking */ if (hittest == SCROLL_THUMB) { UINT val = GetScroolThumbVal( &info, &rect, vertical, trackThumbPos + lastMousePos - lastClickPos ); SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl ); } SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_ENDSCROLL, (LPARAM)hwndCtl ); /* Terminate tracking */ m_hScrollTracking = NULL; } ReleaseDC( m_hWnd, hdc ); } void CSkinWnd::TrackScrollBar(int nBar,CPoint pt) { MSG msg; INT xoffset = 0, yoffset = 0; CRect rtClient,rtWindow; GetClientRect(&rtClient); ClientToScreen(&rtClient); GetWindowRect(&rtWindow); if (nBar != SB_CTL) { xoffset = rtClient.left - rtWindow.left; yoffset = rtClient.top - rtWindow.top; ::ScreenToClient(m_hWnd, &pt ); pt.x += xoffset; pt.y += yoffset; } HandleScrollEvent( nBar, WM_LBUTTONDOWN, pt ); do { if (!GetMessage( &msg, 0, 0, 0 )) break; if (CallMsgFilter( &msg, MSGF_SCROLLBAR )) continue; if (msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE || (msg.message == WM_TIMER && msg.wParam == SCROLL_TIMER)) { pt.x = (short)LOWORD(msg.lParam) + xoffset; pt.y = (short)HIWORD(msg.lParam) + yoffset; HandleScrollEvent( nBar, msg.message, pt ); } else { TranslateMessage( &msg ); DispatchMessage( &msg ); } if (!IsWindow( m_hWnd )) { ReleaseCapture(); break; } } while (msg.message != WM_LBUTTONUP); } void CSkinWnd::DrawMovingThumb(CDC *pDC,BOOL bVertical,CRect rtPos,int nArrowSize,int nThumbSize) { int pos = m_nTrackingPos; int max_size; if( bVertical ) max_size = rtPos.bottom - rtPos.top; else max_size = rtPos.right - rtPos.left; max_size -= (nArrowSize-SCROLL_ARROW_THUMB_OVERLAP) + nThumbSize; if( pos < (nArrowSize-SCROLL_ARROW_THUMB_OVERLAP) ) pos = (nArrowSize-SCROLL_ARROW_THUMB_OVERLAP); else if( pos > max_size ) pos = max_size; CMemDC memDC(pDC,rtPos); if(!bVertical) { m_pSkinScrollBar->DrawHBackground(&memDC,rtPos); m_pSkinScrollBar->DrawHArrowLeft(&memDC,CRect(rtPos.left,rtPos.top,rtPos.left + nArrowSize,rtPos.bottom),m_nHArrowLeftState); m_pSkinScrollBar->DrawHArrowRight(&memDC,CRect(rtPos.right - nArrowSize,rtPos.top,rtPos.right,rtPos.bottom),m_nHArrowRightState); m_pSkinScrollBar->DrawHThumb(&memDC,CRect(rtPos.left + pos,rtPos.top+1,rtPos.left +pos + nThumbSize,rtPos.bottom-1),m_nHThumbState); } else { m_pSkinScrollBar->DrawVBackground(&memDC,rtPos); m_pSkinScrollBar->DrawVArrowTop(&memDC,CRect(rtPos.left,rtPos.top,rtPos.right,rtPos.top + nArrowSize),m_nVArrowTopState); m_pSkinScrollBar->DrawVArrowBottom(&memDC,CRect(rtPos.left,rtPos.bottom - nArrowSize,rtPos.right,rtPos.bottom),m_nVArrowBottomState); m_pSkinScrollBar->DrawVThumb(&memDC,CRect(rtPos.left+1,rtPos.top + pos,rtPos.right-1 ,rtPos.top +pos + nThumbSize),m_nVThumbState); } m_nTrackingBar = !m_nTrackingBar; } void CSkinWnd::DrawSeparator(CRect& rc, CDC& dc) { if(!m_pPopupMenu->DrawImageSection(&dc,rc,m_pPopupMenu->m_itemPopup.imageActive)) { CBrush brush; brush.CreateSolidBrush(m_pPopupMenu->m_colorBackground); dc.FillRect(rc,&brush); } rc.top += rc.Height() >> 1; rc.bottom = rc.top + 1; rc.left += 5; rc.right -= 5; if(!m_pPopupMenu->DrawImageSection(&dc,rc,m_pPopupMenu->m_itemPopup.imageSeparator)) { dc.DrawEdge(rc, EDGE_ETCHED, BF_TOP); } } void CSkinWnd::DrawMenuText(CDC& dc, CRect rc, CString text, COLORREF color) { CString left = text; CString right; int iTabPos = left.Find(_T('\t')); if (iTabPos >= 0) { right = left.Right(left.GetLength() - iTabPos - 1); left = left.Left(iTabPos); } dc.SetTextColor(color); dc.DrawText(left, &rc, DT_SINGLELINE|DT_LEFT|DT_VCENTER); if (iTabPos > 0) dc.DrawText(right, &rc, DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_RIGHT); } void CSkinWnd::PLSelectRect(CDC& dc, const CRect& rc) { if(!m_pPopupMenu->DrawImageSection(&dc,rc,m_pPopupMenu->m_itemPopup.imageActive)) { CBrush brush; brush.CreateSolidBrush(m_pPopupMenu->m_itemPopup.colorActive); dc.FillRect(rc,&brush); brush.DeleteObject( ); } } void CSkinWnd::PLNormalRect(CDC& dc, const CRect& rc) { if(!m_pPopupMenu->DrawImageSection(&dc,rc,m_pPopupMenu->m_itemPopup.imageActive)) { CBrush brush; brush.CreateSolidBrush(m_pPopupMenu->m_colorBackground); dc.FillRect(rc,&brush); brush.DeleteObject( ); } } void CSkinWnd::ConvertMenu(CMenu* pMenu, UINT nIndex, BOOL bSysMenu, BOOL bShowButtons) { ASSERT_VALID(pMenu); CString sItemName; UINT nItem = pMenu->GetMenuItemCount(); for (UINT i = 0; i < nItem; i++) { // loop over each item in menu // get menu item info TCHAR itemname[256] = {0}; CMenuItemInfo info; info.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_ID | MIIM_TYPE; info.dwTypeData = itemname; info.cch = sizeof(itemname); ::GetMenuItemInfo(*pMenu, i, TRUE, (MENUITEMINFO *)&info); CMyItemData* pmd = (CMyItemData*)(info.dwItemData); if (pmd && !pmd->IsMyItemData()) continue; // owner-draw menu item isn't mine--leave it alone // Koji MATSUNAMI 1999.2.23 if (bSysMenu && info.wID >= 0xF000) { continue; // don't do for system menu commands } // now that I have the info, I will modify it info.fMask = 0; // assume nothing to change if (bShowButtons) { if (!(info.fType & MFT_OWNERDRAW)) { info.fType |= MFT_OWNERDRAW; info.fMask |= MIIM_TYPE; if (!pmd) { // if no item data: pmd = new CMyItemData; // create one ASSERT(pmd); // (I hope) pmd->fType = info.fType; // handy when drawing info.dwItemData = (DWORD)pmd; // set in menu item data info.fMask |= MIIM_DATA; // set item data } pmd->text = info.dwTypeData; // copy menu item string } // now add the menu to list of "converted" menus HMENU hmenu = pMenu->GetSafeHmenu(); ASSERT(hmenu); if (!m_menuList.Find(hmenu)) m_menuList.AddHead(hmenu); } else { // no buttons -- I'm converting to strings if (info.fType & MFT_OWNERDRAW) { info.fType &= ~MFT_OWNERDRAW; // turn it off info.fMask |= MIIM_TYPE; // change item type ASSERT(pmd); // sanity check sItemName = pmd->text; // save name before deleting pmd } else // otherwise: sItemName = info.dwTypeData; // use name from MENUITEMINFO_LOCAL if (pmd) { info.dwItemData = NULL; // item data is NULL info.fMask |= MIIM_DATA; // change it safe_delete(pmd); // and item data too } if (info.fMask & MIIM_TYPE) { // if setting name, copy name from CString to buffer and set cch _tcsncpy(itemname, sItemName, sizeof(itemname)); info.dwTypeData = itemname; info.cch = sItemName.GetLength(); } } // if after all the above, there is anything to change, change it if (info.fMask) { SetMenuItemInfo(*pMenu, i, TRUE, (MENUITEMINFO *)&info); } } }