📄 skinbase.cpp
字号:
{
BYTE btRed = (BYTE)min(255, (int)(GetRValue(crA) * fAmountA + GetRValue(crB) * (1.0f - fAmountA)));
BYTE btGreen = (BYTE)min(255, (int)(GetGValue(crA) * fAmountA + GetGValue(crB) * (1.0f - fAmountA)));
BYTE btBlue = (BYTE)min(255, (int)(GetBValue(crA) * fAmountA + GetBValue(crB) * (1.0f - fAmountA)));
return RGB(btRed, btGreen, btBlue);
}
COLORREF CSkinBase::VaryColor(COLORREF crColor, float fFactor)
{
BYTE btRed = (BYTE)min(255, (int)(GetRValue(crColor) * fFactor));
BYTE btGreen = (BYTE)min(255, (int)(GetGValue(crColor) * fFactor));
BYTE btBlue = (BYTE)min(255, (int)(GetBValue(crColor) * fFactor));
return RGB(btRed, btGreen, btBlue);
}
HRGN CSkinBase::BitmapToRegion(CBitmap* pBmp, COLORREF color)
{
const DWORD RGNDATAHEADER_SIZE = sizeof(RGNDATAHEADER);
const DWORD ADD_RECTS_COUNT = 40; // number of rects to be appended
// get image properties
BITMAP BM = { 0 };
pBmp->GetBitmap(&BM);
// create temporary dc
CBitmap bmpMem;
CDC dc, dcMem1, dcMem2;
CDC* pDC = CWnd::GetDesktopWindow()->GetDC();
dcMem1.CreateCompatibleDC(pDC);
dcMem2.CreateCompatibleDC(pDC);
bmpMem.CreateCompatibleBitmap(pDC, BM.bmWidth, BM.bmHeight);
CWnd::GetDesktopWindow()->ReleaseDC(pDC);
CBitmap* pOldBM1 = dcMem1.SelectObject(pBmp);
CBitmap* pOldBM2 = dcMem2.SelectObject(&bmpMem);
// verify that the mask color is correct for the current bit depth
color = dcMem2.SetPixel(0, 0, color);
dcMem2.BitBlt(0, 0, BM.bmWidth, BM.bmHeight, &dcMem1, 0, 0, SRCCOPY);
dcMem1.SelectObject(pOldBM1);
dcMem1.DeleteDC();
DWORD dwRectsCount = BM.bmHeight; // number of rects in allocated buffer
int nY, nX; // current position in mask image
// where mask was found
bool bWasMask; // set when mask has been found in current scan line
bool bIsMask; // set when current color is mask color
CRect rLine;
// allocate memory for region data
// region data here is set of regions that are rectangles with height 1 pixel (scan line)
// that's why nRgnStart allocation is <bm.biHeight> RECTs - number of scan lines in image
RGNDATAHEADER* pRgnData = (RGNDATAHEADER*)new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
// get pointer to RECT table
LPRECT pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
// zero region data header memory (header part only)
memset( pRgnData, 0, RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) );
// fill it by default
pRgnData->dwSize = RGNDATAHEADER_SIZE;
pRgnData->iType = RDH_RECTANGLES;
for ( nY = 0; nY < BM.bmHeight; nY++ )
{
bWasMask = true;
rLine.SetRect(0, nY, 0, nY + 1);
for ( nX = 0; nX < BM.bmWidth; nX++ )
{
// get color
COLORREF crPixel = dcMem2.GetPixel(nX, nY);
bIsMask = (crPixel == color);
if (!bIsMask && bWasMask) // start of the rgn
{
rLine.left = nX;
bWasMask = FALSE;
}
if (!bWasMask && (bIsMask || nX == BM.bmWidth - 1)) // end of rgn
{
bWasMask = true;
rLine.right = bIsMask ? nX : nX + 1;
// save current RECT
// if this was a full line append to the last if it was full too
BOOL bAdded = FALSE;
if (pRgnData->nCount)
{
LPRECT pLastRect = &pRects[ pRgnData->nCount - 1];
if (!pLastRect->left && !rLine.left &&
pLastRect->right == BM.bmWidth - 1 && rLine.right == BM.bmWidth - 1)
{
pLastRect->bottom = rLine.bottom;
bAdded = TRUE;
}
}
// else add as a new line
if (!bAdded)
{
pRects[ pRgnData->nCount++ ] = rLine;
// if buffer full reallocate it with more room
if ( pRgnData->nCount >= dwRectsCount )
{
dwRectsCount += ADD_RECTS_COUNT;
// allocate new buffer
LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
// copy current region data to it
memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
// delte old region data buffer
delete pRgnData;
// set pointer to new regiondata buffer to current
pRgnData = (RGNDATAHEADER*)pRgnDataNew;
// correct pointer to RECT table
pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
}
}
}
}
}
// create region
HRGN hRgn = ExtCreateRegion( NULL, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData );
CRect rBox;
::GetRgnBox(hRgn, rBox);
// release region data
delete pRgnData;
dcMem2.SelectObject(pOldBM2);
dcMem2.DeleteDC();
bmpMem.DeleteObject();
return hRgn;
}
HMENU CSkinBase::MakeMenuCopy(const CMenu* pSrc)
{
if (!pSrc)
return NULL;
CMenu menu;
VERIFY (menu.CreatePopupMenu());
ASSERT (::IsMenu(menu.m_hMenu));
int nNumItems = pSrc->GetMenuItemCount();
CString sLabel;
MENUITEMINFO mii;
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii); // must fill up this field
mii.fMask = MIIM_STATE | MIIM_DATA; // get the state of the menu item
for (int nItem = 0; nItem < nNumItems; nItem++)
{
UINT uIDItem = pSrc->GetMenuItemID(nItem);
pSrc->GetMenuString(nItem, sLabel, MF_BYPOSITION);
UINT uFlags = (uIDItem == 0) ? MF_SEPARATOR : (uIDItem == (UINT)-1) ? MF_POPUP : MF_STRING;
// special case: if a popup menu we must copy it too
if (uFlags == MF_POPUP)
{
HMENU hPopup = MakeMenuCopy(pSrc->GetSubMenu(nItem));
ASSERT (hPopup);
uIDItem = (UINT)hPopup;
}
menu.AppendMenu(uFlags, uIDItem, sLabel);
// make sure we copy the state too
::GetMenuItemInfo(*pSrc, nItem, TRUE, &mii);
::SetMenuItemInfo(menu, nItem, TRUE, &mii);
}
return menu.Detach();
}
// this one copies the menu without deleting the root
BOOL CSkinBase::CopyMenu(const CMenu* pSrc, CMenu* pDest)
{
ASSERT (::IsMenu(pDest->m_hMenu));
if (!::IsMenu(pDest->m_hMenu))
return FALSE;
ASSERT (::IsMenu(pSrc->m_hMenu));
if (!::IsMenu(pSrc->m_hMenu))
return FALSE;
// delete all the existing items
while (pDest->GetMenuItemCount())
pDest->DeleteMenu(0, MF_BYPOSITION);
// copy across
int nNumItems = pSrc->GetMenuItemCount();
CString sLabel;
MENUITEMINFO mii;
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii); // must fill up this field
mii.fMask = MIIM_STATE | MIIM_DATA; // get the state of the menu item
for (int nItem = 0; nItem < nNumItems; nItem++)
{
UINT uIDItem = pSrc->GetMenuItemID(nItem);
pSrc->GetMenuString(nItem, sLabel, MF_BYPOSITION);
UINT uFlags = (uIDItem == 0) ? MF_SEPARATOR : (uIDItem == (UINT)-1) ? MF_POPUP : MF_STRING;
// special case: if a popup menu we must copy it too
if (uFlags == MF_POPUP)
{
HMENU hPopup = MakeMenuCopy(pSrc->GetSubMenu(nItem));
ASSERT (hPopup);
uIDItem = (UINT)hPopup;
}
pDest->AppendMenu(uFlags, uIDItem, sLabel);
// make sure we copy the state too
::GetMenuItemInfo(*pSrc, nItem, TRUE, &mii);
::SetMenuItemInfo(*pDest, nItem, TRUE, &mii);
}
return TRUE;
}
BOOL CSkinBase::CopyBitmap(const CBitmap* pSrc, CBitmap* pDest)
{
ASSERT (pDest);
if (!pDest)
return FALSE;
pDest->DeleteObject();
if (!pSrc || !pSrc->GetSafeHandle())
return FALSE;
CDC* pDC = CWnd::GetDesktopWindow()->GetDC();
CDC dcMem1, dcMem2;
BOOL bRes = FALSE;
if (dcMem1.CreateCompatibleDC(pDC) && dcMem2.CreateCompatibleDC(pDC))
{
BITMAP bm;
((CBitmap*)pSrc)->GetBitmap(&bm);
if (pDest->CreateCompatibleBitmap(pDC, bm.bmWidth, bm.bmHeight))
{
ASSERT (CBitmap::FromHandle((HBITMAP)pDest->GetSafeHandle()) == pDest);
CBitmap* pOldBM1 = dcMem1.SelectObject((CBitmap*)pSrc);
CBitmap* pOldBM2 = dcMem2.SelectObject(pDest);
dcMem2.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcMem1, 0, 0, SRCCOPY);
bRes = TRUE;
dcMem1.SelectObject(pOldBM1);
dcMem2.SelectObject(pOldBM2);
}
}
dcMem1.DeleteDC();
dcMem2.DeleteDC();
CWnd::GetDesktopWindow()->ReleaseDC(pDC);
ASSERT (CBitmap::FromHandle((HBITMAP)pDest->GetSafeHandle()) == pDest);
HANDLE* ph = (HANDLE*)((BYTE*)pDest + 4); // after CObject
ASSERT (ph[0] == pDest->GetSafeHandle());
return bRes;
}
BOOL CSkinBase::ExtractResource(UINT nID, LPCTSTR szType, CString& sTempFilePath, HINSTANCE hInst)
{
if (!hInst)
hInst = AfxFindResourceHandle(MAKEINTRESOURCE(nID), szType);
if (!hInst)
return FALSE;
// compare time with that of module from which it was loaded
CString sTempPath;
CFileStatus fsRes, fsModule;
CString sModulePath;
::GetModuleFileName(hInst, sModulePath.GetBuffer(MAX_PATH + 1), MAX_PATH);
sModulePath.ReleaseBuffer();
if (!CFile::GetStatus(sModulePath, fsModule))
return FALSE;
// create temp filename
::GetTempPath(MAX_PATH, sTempPath.GetBuffer(MAX_PATH));
sTempPath.ReleaseBuffer();
sTempFilePath.Format("%s%s_skin_%d.tmp", sTempPath, szType, nID);
// see if the file has been created before
if (!CFile::GetStatus(sTempFilePath, fsRes) || fsRes.m_mtime < fsModule.m_mtime)
{
// Load the resource into memory
HRSRC hRes = FindResource(hInst, (LPCSTR)nID, szType);
if (!hRes)
{
TRACE("Couldn't find %s resource %d!\n", szType, nID);
return FALSE;
}
DWORD len = SizeofResource(hInst, hRes);
BYTE* lpRes = (BYTE*)LoadResource(hInst, hRes);
ASSERT(lpRes);
CFile file;
if (file.Open(sTempFilePath, CFile::modeCreate | CFile::modeWrite))
{
file.Write(lpRes, len);
file.Close();
FreeResource((HANDLE)lpRes);
}
else
{
FreeResource((HANDLE)lpRes);
return FALSE;
}
}
return TRUE;
}
CWnd* CSkinBase::GetChildWnd(CWnd* pParent, LPCTSTR szClass, int nID)
{
CWnd* pChild = pParent->GetWindow(GW_CHILD);
while (pChild)
{
if (CWinClasses::IsClass(*pChild, szClass))
{
if (nID == -1 || pChild->GetDlgCtrlID() == nID)
return pChild;
}
pChild = pChild->GetNextWindow();
}
return NULL;
}
BOOL CSkinBase::BitBlt(CDC* pDCDest,
int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
CDC* pDCSrc, int nXOriginSrc, int nYOriginSrc,
UINT uROP,
COLORREF crTransparent)
{
if (crTransparent != (COLORREF)-1)
{
return TransparentBlt(pDCDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
pDCSrc, nXOriginSrc, nYOriginSrc, nWidthDest, nHeightDest, crTransparent);
}
else
{
return pDCDest->BitBlt(nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
pDCSrc, nXOriginSrc, nYOriginSrc, uROP);
}
return TRUE;
}
BOOL CSkinBase::StretchBlt(CDC* pDCDest,
int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
CDC* pDCSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
UINT uROP,
COLORREF crTransparent)
{
// check to see if this is really just a BitBlt
if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
{
return BitBlt(pDCDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
pDCSrc, nXOriginSrc, nYOriginSrc, uROP, crTransparent);
}
// else pick whether its transparent or not
if (crTransparent != (COLORREF)-1)
{
return TransparentBlt(pDCDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
pDCSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, crTransparent);
}
else
{
return pDCDest->StretchBlt(nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
pDCSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, uROP);
}
return TRUE;
}
CString CSkinBase::GetTipText(LPCTSTR szText, BOOL bToolbar)
{
CString sText(szText), sTip;
if (sText.IsEmpty())
return "";
// tip text starts at '\n'
int nStartTip = bToolbar ? sText.Find('\n') : -1;
if (bToolbar && nStartTip == -1) // no tip
return "";
sText = sText.Right(sText.GetLength() - nStartTip - 1);
// strip '&' and '...' if present
int nLen = sText.GetLength();
sTip.Empty();
for (int nPos = 0; nPos < nLen; nPos++)
{
if (sText[nPos] != '&' && sText[nPos] != '.')
sTip += sText[nPos];
}
return sTip;
}
BOOL CSkinBase::ConvertToGrayScale(CBitmap* pBitmap, COLORREF crMask)
{
CDC dcTemp;
dcTemp.CreateCompatibleDC(NULL);
BITMAP BM;
pBitmap->GetBitmap(&BM);
CBitmap* pBMOld = dcTemp.SelectObject(pBitmap);
// now iterate all the pixels, converting each to grayscale
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -