// XTPFunctions.cpp : global functions. // // This file is a part of the XTREME CONTROLS MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Common/XTPColorManager.h" #include "Common/XTPImageManager.h" #include "Common/XTPHookManager.h" #include "Common/XTPSystemHelpers.h" #ifdef _XTP_INCLUDE_COMMANDBARS #include "CommandBars/XTPCommandBarsDefines.h" #include "CommandBars/XTPCommandBars.h" #include "CommandBars/XTPCommandBar.h" #include "CommandBars/XTPPopupBar.h" #include "CommandBars/XTPPaintManager.h" #endif #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //----------------------------------------------------------------------------- // helper function which sets the font for a window and all its children // and also resizes everything according to the new font //----------------------------------------------------------------------------- _XTP_EXT_CLASS void AFXAPI XTPChangeWindowFont(CWnd* pWnd, CFont* pFont) { CRect windowRect; // grab old and new text metrics TEXTMETRIC tmOld, tmNew; CDC * pDC = pWnd->GetDC(); CFont * pSavedFont = pDC->SelectObject(pWnd->GetFont()); pDC->GetTextMetrics(&tmOld); pDC->SelectObject(pFont); pDC->GetTextMetrics(&tmNew); pDC->SelectObject(pSavedFont); pWnd->ReleaseDC(pDC); long oldHeight = tmOld.tmHeight + tmOld.tmExternalLeading; long newHeight = tmNew.tmHeight + tmNew.tmExternalLeading; // calculate new dialog window rectangle CRect clientRect, newClientRect, newWindowRect; pWnd->GetWindowRect(windowRect); pWnd->GetClientRect(clientRect); long xDiff = windowRect.Width() - clientRect.Width(); long yDiff = windowRect.Height() - clientRect.Height(); newClientRect.left = newClientRect.top = 0; newClientRect.right = clientRect.right * tmNew.tmAveCharWidth / tmOld.tmAveCharWidth; newClientRect.bottom = clientRect.bottom * newHeight / oldHeight; newWindowRect.left = windowRect.left - (newClientRect.right - clientRect.right)/2; newWindowRect.top = windowRect.top - (newClientRect.bottom - clientRect.bottom)/2; newWindowRect.right = newWindowRect.left + newClientRect.right + xDiff; newWindowRect.bottom = newWindowRect.top + newClientRect.bottom + yDiff; pWnd->MoveWindow(newWindowRect); pWnd->SetFont(pFont); // iterate through and move all child windows and change their font. CWnd* pChildWnd = pWnd->GetWindow(GW_CHILD); while (pChildWnd) { pChildWnd->SetFont(pFont); pChildWnd->GetWindowRect(windowRect); CString strClass; ::GetClassName(pChildWnd->m_hWnd, strClass.GetBufferSetLength(32), 31); strClass.MakeUpper(); if (strClass == _T("COMBOBOX")) { CRect rect; pChildWnd->SendMessage(CB_GETDROPPEDCONTROLRECT, 0, (LPARAM) &rect); windowRect.right = rect.right; windowRect.bottom = rect.bottom; } pWnd->ScreenToClient(windowRect); windowRect.left = windowRect.left * tmNew.tmAveCharWidth / tmOld.tmAveCharWidth; windowRect.right = windowRect.right * tmNew.tmAveCharWidth / tmOld.tmAveCharWidth; windowRect.top = windowRect.top * newHeight / oldHeight; windowRect.bottom = windowRect.bottom * newHeight / oldHeight; pChildWnd->MoveWindow(windowRect); pChildWnd = pChildWnd->GetWindow(GW_HWNDNEXT); } } //----------------------------------------------------------------------------- // FUNCTION: XTPDrawEmbossed //----------------------------------------------------------------------------- _XTP_EXT_CLASS void AFXAPI XTPDrawEmbossed(CDC* pDC, CImageList& imageList, int nIndex, CPoint point, BOOL bInColor) { IMAGEINFO imgInfo; VERIFY(imageList.GetImageInfo(0, &imgInfo)); CRect rcImage = imgInfo.rcImage; // create memory dc CDC memDC; memDC.CreateCompatibleDC(pDC); // create mono or color bitmap CBitmap bitmap; if (bInColor) { bitmap.CreateCompatibleBitmap(pDC, rcImage.Width(), rcImage.Height()); } else { bitmap.CreateBitmap(rcImage.Width(), rcImage.Height(), 1, 1, NULL); } // draw image into memory DC--fill BG white first CBitmap* pOldBitmap = memDC.SelectObject(&bitmap); memDC.PatBlt(0, 0, rcImage.Width(), rcImage.Height(), WHITENESS); imageList.Draw(&memDC, nIndex, CPoint(0, 0), ILD_TRANSPARENT); // Draw using highlight offset by (1, 1), then shadow CBrush brShadow(GetXtremeColor(COLOR_3DSHADOW)); CBrush brHilite(GetXtremeColor(COLOR_3DHIGHLIGHT)); CBrush* pOldBrush = pDC->SelectObject(&brHilite); pDC->BitBlt(point.x + 1, point.y + 1, rcImage.Width(), rcImage.Height(), &memDC, 0, 0, 0xB8074A); pDC->SelectObject(&brShadow); pDC->BitBlt(point.x, point.y, rcImage.Width(), rcImage.Height(), &memDC, 0, 0, 0xB8074A); pDC->SelectObject(pOldBrush); memDC.SelectObject(pOldBitmap); bitmap.DeleteObject(); } //----------------------------------------------------------------------------- // FUNCTION: XTPDrawShadedRect //----------------------------------------------------------------------------- _XTP_EXT_CLASS void AFXAPI XTPDrawShadedRect(CDC *pDC, CRect& rect) { // Bit pattern for a monochrome brush with every // other pixel turned off WORD bits[] = { 0x0055, 0x00AA, 0x0055, 0x00AA, 0x0055, 0x00AA, 0x0055, 0x00AA }; // Need a monochrome pattern bitmap CBitmap bitmap; bitmap.CreateBitmap(8, 8, 1, 1, &bits); // Create the pattern brush CBrush brush; brush.CreatePatternBrush(&bitmap); CBrush* pOldBrush = pDC->SelectObject(&brush); COLORREF crBack = pDC->SetBkColor(GetXtremeColor(COLOR_3DFACE)); COLORREF crText = pDC->SetTextColor(GetXtremeColor(COLOR_3DHIGHLIGHT)); pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); // Restore the device context pDC->SelectObject(pOldBrush); pDC->SetBkColor(crBack); pDC->SetTextColor(crText); brush.DeleteObject(); } //----------------------------------------------------------------------------- // DIBs use RGBQUAD format: // 0xbb 0xgg 0xrr 0x00 // // Reasonably efficient code to convert a COLORREF into an // RGBQUAD is byte-order-dependent, so we need different // code depending on the byte order we're targeting. //----------------------------------------------------------------------------- #define RGB_TO_RGBQUAD(r, g, b) (RGB(b, g, r)) #define RGBQUAD_INIT(r, g, b) (RGB_TO_RGBQUAD(r, g, b)), (RGB(r, g, b)) #define CLR_TO_RGBQUAD(clr) (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr))) //----------------------------------------------------------------------------- // CXTPReplaceColorHandler - Helper object to replace color in a given DC //----------------------------------------------------------------------------- class CXTPReplaceColorHandler { public: // Input: pTargetDC - DC in which to replace colors // nWidth - width of the rectangle to replace (starting from (0, 0)) // nHeight - height of the rectangle to replace the color (starting from (0, 0)) // Summary: Constructor takes parameters common for the operation. CXTPReplaceColorHandler(CDC* pTargetDC, int nWidth, int nHeight); // Summary: virtual ~CXTPReplaceColorHandler(); // Summary: Initialization, returns false if fails to initialize bool Init(); // Summary: Replaces one color with another bool ReplaceColor(COLORREF clrFrom, COLORREF clrTo); protected: int m_nWidth; int m_nHeight; bool m_bOldBitmap; // true if m_pOldBitmap was initialized CDC m_dcMask; // CDC* m_pTargetDC; // a DC to replace colors in place CBitmap m_bitmapMask; // monochrome bitmap to work with CBitmap* m_pOldBitmap; // previously selected bitmap COLORREF m_clrOldText; COLORREF m_clrOldBk; }; CXTPReplaceColorHandler::CXTPReplaceColorHandler(CDC* pTargetDC, int nWidth, int nHeight) : m_pOldBitmap(NULL) , m_bOldBitmap(false) , m_pTargetDC(pTargetDC) , m_clrOldBk(pTargetDC->GetBkColor()) , m_clrOldText(pTargetDC->GetTextColor()) , m_nWidth(nWidth) , m_nHeight(nHeight) { } CXTPReplaceColorHandler::~CXTPReplaceColorHandler() { if (m_bOldBitmap) { m_dcMask.SelectObject(m_pOldBitmap); } m_pTargetDC->SetBkColor(m_clrOldBk); m_pTargetDC->SetTextColor(m_clrOldText); } bool CXTPReplaceColorHandler::Init() { if (!m_dcMask.CreateCompatibleDC(m_pTargetDC)) { return false; } if (!m_bitmapMask.CreateBitmap(m_nWidth, m_nHeight, 1, 1, NULL)) { return false; } m_pOldBitmap = m_dcMask.SelectObject(&m_bitmapMask); m_bOldBitmap = true; return true; } bool CXTPReplaceColorHandler::ReplaceColor(COLORREF clrFrom, COLORREF clrTo) { // filter out trivial case if (clrFrom == clrTo) { return true; } // Initialize the mask: // 1. Set the background color of the source DC to the color to translate. // so 1s would be the bits where color match has been found // 2. Create the object mask for the bitmap by performing a BitBlt // from the source bitmap to a monochrome bitmap. m_pTargetDC->SetBkColor(clrFrom); if (!m_dcMask.BitBlt(0, 0, m_nWidth, m_nHeight, m_pTargetDC, 0, 0, SRCCOPY)) { return false; } // zero out destination pixels we would want to replace with another color m_pTargetDC->SetTextColor(RGB(255, 255, 255)); m_pTargetDC->SetBkColor(RGB(0, 0, 0)); if (!m_pTargetDC->BitBlt(0, 0, m_nWidth, m_nHeight, &m_dcMask, 0, 0, SRCAND)) { return false; } // now, replace zeroed pixels with destination color if (clrTo != RGB(0, 0, 0)) { m_pTargetDC->SetBkColor(clrTo); m_pTargetDC->SetTextColor(RGB(0, 0, 0)); if (!m_pTargetDC->BitBlt(0, 0, m_nWidth, m_nHeight, &m_dcMask, 0, 0, SRCPAINT)) { return false; } } // done return true; } //----------------------------------------------------------------------------- // FUNCTION: XTPChildWindowFromPoint() //----------------------------------------------------------------------------- _XTP_EXT_CLASS HWND AFXAPI XTPChildWindowFromPoint(HWND hWnd, POINT point) { ASSERT(hWnd != NULL); if (!hWnd) return 0; // check child windows ::ClientToScreen(hWnd, &point); HWND hWndChild = ::GetWindow(hWnd, GW_CHILD); for (; hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT)) { if ((UINT)(WORD)::GetDlgCtrlID(hWndChild) != (WORD)-1 && (::GetWindowLong(hWndChild, GWL_STYLE) & WS_VISIBLE)) { // see if point hits the child window CRect rect; ::GetWindowRect(hWndChild, rect); if (rect.PtInRect(point)) return hWndChild; } } return NULL; // not found } //----------------------------------------------------------------------------- // FUNCTION: XTPPathExists() //----------------------------------------------------------------------------- _XTP_EXT_CLASS BOOL AFXAPI XTPPathExists(LPCTSTR lpszFileName) { WIN32_FIND_DATA fd; HANDLE hFind = ::FindFirstFile(lpszFileName, &fd); if (hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); return TRUE; } return FALSE; } //----------------------------------------------------------------------------- // FUNCTION: XTPCreateView() //----------------------------------------------------------------------------- _XTP_EXT_CLASS CWnd* AFXAPI XTPCreateView(CWnd* pParentWnd, CRuntimeClass *pViewClass, CDocument *pDocument/*= NULL*/, CCreateContext *pContext/*= NULL*/, DWORD dwStyle/*= AFX_WS_DEFAULT_VIEW*/, CWnd* pOwnerWnd/*= NULL*/, UINT nID/*= AFX_IDW_PANE_FIRST*/) { if (!pContext && !pViewClass) return NULL; #ifdef _DEBUG ASSERT(pContext != NULL || pViewClass != NULL); ASSERT(pContext != NULL || pViewClass->IsDerivedFrom(RUNTIME_CLASS(CWnd))); ASSERT(pContext != NULL || AfxIsValidAddress(pViewClass, sizeof(CRuntimeClass), FALSE)); #endif if (pOwnerWnd == NULL) pOwnerWnd = pParentWnd; CCreateContext contextT; if (pContext == NULL) { // if no context specified, generate one from the // currently selected client if possible. contextT.m_pLastView = NULL; contextT.m_pCurrentFrame = NULL; contextT.m_pNewDocTemplate = NULL; contextT.m_pCurrentDoc = pDocument; contextT.m_pNewViewClass = pViewClass; if (pDocument != NULL) contextT.m_pNewDocTemplate = pDocument->GetDocTemplate(); pContext = &contextT; } if (!pContext->m_pNewViewClass) return NULL; CWnd* pWnd = NULL; TRY { pWnd = (CWnd*)pContext->m_pNewViewClass->CreateObject(); if (pWnd == NULL) AfxThrowMemoryException(); } CATCH_ALL(e) { TRACE0("Out of memory creating a view.\n"); // Note: DELETE_EXCEPTION(e) not required return NULL; } END_CATCH_ALL ASSERT_KINDOF(CWnd, pWnd); ASSERT(pWnd->m_hWnd == NULL); // not yet created. // Create with the right size (wrong position) CRect rect(0, 0, 0, 0); if (!pWnd->Create(NULL, NULL, dwStyle, rect, pParentWnd, nID, pContext)) { TRACE0("Failed to create docking window view.\n"); return NULL; } pWnd->SetOwner(pOwnerWnd); return pWnd; } _XTP_EXT_CLASS BOOL AFXAPI XTPContextMenu(CMenu* pPopup, UINT nFlags, int x, int y, CWnd* pWnd, int nIDBitmap, BOOL bNoNotify) { BOOL bResult = FALSE; nIDBitmap; bNoNotify; #ifdef _XTP_INCLUDE_COMMANDBARS if (XTPPaintManager()) { CXTPPopupBar* pPopupBar = CXTPPopupBar::CreatePopupBar(NULL); if (nIDBitmap > 0) { CXTPImageManager* pImageManager = new CXTPImageManager(); pImageManager->SetIcons(nIDBitmap); pPopupBar->SetImageManager(pImageManager); } if (!pPopupBar->LoadMenu(pPopup)) { pPopupBar->InternalRelease(); return bResult; } bResult = CXTPCommandBars::TrackPopupMenu(pPopupBar, nFlags | (bNoNotify ? TPM_NONOTIFY : 0), x, y, pWnd); pPopupBar->InternalRelease(); } else { bResult = pPopup->TrackPopupMenu(nFlags, x, y, pWnd); } #else // Toolkit Standard bResult = pPopup->TrackPopupMenu(nFlags, x, y, pWnd); #endif return bResult; }