⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skinbase.cpp

📁 WMI接口测试Demo程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// a bit daggy, but....
	int nXPixel = BM.bmWidth;
	COLORREF crPixel;
	
	while (nXPixel--)
	{
		int nYPixel = BM.bmHeight;
		
		while (nYPixel--)
		{
			crPixel = dcTemp.GetPixel(nXPixel, nYPixel);
			
			// leave the mask color as-is
			if (crPixel == crMask)
				continue;
			
			const BYTE btRed = GetRValue(crPixel);
			const BYTE btGreen = GetGValue(crPixel);
			const BYTE btBlue = GetBValue(crPixel);
			
			// if gray already goto next
			if (btRed == btGreen && btGreen == btBlue)
				continue;
			
			const BYTE btGray = (BYTE)((btRed / 3) + (btGreen / 2) + (btBlue / 4));
			
			// note: SetPixelV() quicker than SetPixel()
			dcTemp.SetPixelV(nXPixel, nYPixel, RGB(btGray, btGray, btGray));
		}
	}
	
	dcTemp.SelectObject(pBMOld);
	dcTemp.DeleteDC();
	
	return TRUE;
}

BOOL CSkinBase::DoSysMenu(CWnd* pWnd, CPoint ptCursor, LPRECT prExclude, BOOL bCopy)
{
	CMenu* pMenu = pWnd->GetSystemMenu(FALSE);
	ASSERT (pMenu);
	
	if (pMenu)
	{
		TPMPARAMS tpmp;
		tpmp.cbSize = sizeof(tpmp);

		if (prExclude)
			tpmp.rcExclude = *prExclude;
		else
			SetRectEmpty(&tpmp.rcExclude);

		UINT uAlignFlags = TPM_LEFTALIGN | TPM_TOPALIGN | TPM_VERTICAL | TPM_RIGHTBUTTON | TPM_RETURNCMD;
		UINT uID = 0;
		
		if (bCopy) // skinning
		{
			HMENU hSysMenu = CSkinBase::MakeMenuCopy(pMenu);
			ASSERT (hSysMenu);
			
			if (hSysMenu)
			{
				InitSysMenu(CMenu::FromHandle(hSysMenu), pWnd);
				uID = ::TrackPopupMenuEx(hSysMenu, uAlignFlags, 
										ptCursor.x, ptCursor.y, *pWnd, &tpmp);
				
				::DestroyMenu(hSysMenu); // cleanup
			}
		}
		else
		{
			InitSysMenu(pMenu, pWnd);
			uID = ::TrackPopupMenuEx(pMenu->GetSafeHmenu(), uAlignFlags, 
									ptCursor.x, ptCursor.y, *pWnd, &tpmp);
		}
		
		if (uID & 0xf000) // syscommand
		{
			MSG& curMsg = AfxGetThreadState()->m_lastSentMsg;
			
			pWnd->PostMessage(WM_SYSCOMMAND, (uID & 0xfff0), MAKELPARAM(curMsg.pt.x, curMsg.pt.y));
		}
	}
	
	return TRUE;
}

void CSkinBase::InitSysMenu(CMenu* pMenu, CWnd* pWnd)
{
	// iterate all the menu items looking for something resembling a sys menu item
	int nItem = pMenu->GetMenuItemCount();
	
	while (nItem--)
	{
		UINT uID = pMenu->GetMenuItemID(nItem);
		
		if (uID >= 0xF000)
		{
			BOOL bEnable = TRUE;
			
			switch (uID & 0xFFF0)
			{
			case SC_MINIMIZE:
				bEnable = (pWnd->GetStyle() & WS_MINIMIZEBOX) && !pWnd->IsIconic();
				break;
				
			case SC_MAXIMIZE:
				bEnable = (pWnd->GetStyle() & WS_MAXIMIZEBOX) && !pWnd->IsZoomed();
				break;
				
			case SC_RESTORE:
				bEnable = pWnd->IsIconic() || pWnd->IsZoomed();
				break;
				
			case SC_MOVE:
			case SC_SIZE:
				bEnable = !pWnd->IsIconic() && !pWnd->IsZoomed();
				break;
			}
			
			pMenu->EnableMenuItem(uID, bEnable ? MF_ENABLED : MF_GRAYED);
		}
	}
	
	// set close as default item
	pMenu->SetDefaultItem(SC_CLOSE);
}

CSize CSkinBase::GetTextExtent(CDC* pDC, LPCTSTR szText)
{
	ASSERT (pDC && szText);

	if (pDC && szText)
	{
		CRect rText(0, 0, 0, SHRT_MAX);
		pDC->DrawText(szText, rText, DT_SINGLELINE | DT_CALCRECT);
		return rText.Size();
	}

	// else
	return 0;
}

const LPCTSTR WORDBREAK = "_-+=,.:;";
const int CHUNK = 32;

int CSkinBase::FormatText(CDC* pDC, CString& sText, CRect& rect, UINT uDTFlags)
{
	CString sOrgText(sText);
	sText.Empty();

	int nPos = 0, nLinePos = 0, nLen = sOrgText.GetLength();
	int nLastWhiteSpace = -1;
	int nHeight = 0;
	const int LINEHEIGHT = pDC->GetTextExtent("W").cy;
	int nLongestLine = 0;

	// we always allow at least one line of text
	BOOL bSingleLine = (uDTFlags & DT_SINGLELINE);
	BOOL bCalcRect = (uDTFlags & DT_CALCRECT);
	BOOL bEllipsis = (uDTFlags & DT_END_ELLIPSIS);
	BOOL bModString = (uDTFlags & DT_MODIFYSTRING);

	BOOL bFinished = FALSE;
	const int CHUNK = 32;

	char* pBuffer = sOrgText.GetBuffer(sOrgText.GetLength() + 1);

	while (!bFinished)
	{
		int nChunk = CHUNK;
		BOOL bLonger = TRUE;

		int nLinePos = 0;
		int nPrevPos = 0;

		char* pLine = pBuffer + nPos;

		// add chunks till we go over 
		BOOL bContinue = TRUE;
		int nWidth = 0;

		while (bContinue)
		{
			nChunk = min(nChunk, nLen - (nPos + nLinePos));
			nLinePos += nChunk;

			nWidth = pDC->GetTextExtent(pLine, nLinePos).cx;
			bContinue = (nChunk == CHUNK && nWidth < rect.Width());
		}

		// then iterate back and forth with sub chunks till we are just under
		for (int i = 0; i < 5; i++)
		{
			nChunk /= 2;

			if (nWidth == rect.Width())
				break;
			else if (nWidth > rect.Width())
				nLinePos -= nChunk;
			else
				nLinePos += nChunk;

			nWidth = pDC->GetTextExtent(pLine, nLinePos).cx;
		}

		// one final check to see we haven't ended up over 
		if (nWidth > rect.Width())
			nLinePos--;

		// then work back to the previous word break
		int nSavePos = nLinePos;

		while (nLinePos)
		{
			// we word break either if the current character is whitespace or
			// if the preceding character is a wordbreak character
			// or we've reached the end of the string
			BOOL bWordBreak = nLinePos == nLen || _istspace(pLine[nLinePos]) ||
								(strchr(WORDBREAK, pLine[nLinePos - 1]) != NULL);

			if (bWordBreak)
				break;

			nLinePos--;
		}

		if (!nLinePos)
			nLinePos = nSavePos; // single word spans entire line

		nWidth = pDC->GetTextExtent(pLine, nLinePos).cx;

		// check for last line and add ellipsis if required
		nHeight += LINEHEIGHT;
		BOOL bAddEllipsis = FALSE;

		if (nHeight + LINEHEIGHT > rect.Height() || bSingleLine)
		{
			if (bEllipsis && nPos + nLinePos < nLen - 1)
			{
				const int LEN_ELLIPSIS = pDC->GetTextExtent("...", 3).cx;
				
				// modify the last line to add ellipsis
				while (nLinePos)
				{
					nWidth = pDC->GetTextExtent(pLine, nLinePos).cx + LEN_ELLIPSIS;

					if (nWidth > rect.Width())
						nLinePos--;
					else
						break;
				}
				
				bAddEllipsis = TRUE;
			}

			sText += sOrgText.Mid(nPos, nLinePos);

			if (bAddEllipsis)
				sText += "...";

			nLongestLine = max(nLongestLine, nWidth);
			break;
		}

		sText += sOrgText.Mid(nPos, nLinePos);
		sText += '\n';

		nPos += nLinePos;

		bFinished = (nPos >= nLen - 1 || nHeight + LINEHEIGHT > rect.Height());
		nLongestLine = max(nLongestLine, nWidth);

		// jump white space at the start of the next line
		if (!bFinished)
		{
			while (nPos < nLen - 1)
			{
				if (!_istspace(pBuffer[nPos]))
					break;

				// else
				nPos++;
			}
		}
	}

	sOrgText.ReleaseBuffer();

	if (!bModString)
		sText = sOrgText;

	if (bCalcRect)
	{
		rect.right = rect.left + nLongestLine;
		rect.bottom = rect.top + nHeight;
	}

	return nHeight;
}

//////////////////////////////

//////////////////////////////

int CALLBACK CheckFontProc(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, DWORD FontType, LPARAM lParam)
{
	BOOL* pPresent = (BOOL*)lParam;
	ASSERT (pPresent);

	if (pPresent && FontType == TRUETYPE_FONTTYPE) // only TT accepted for now
		*pPresent = TRUE; // at least one font found to match facename

	return 0;
}

BOOL CSkinBase::FontIsPresent(LPCTSTR szFaceName)
{
	LOGFONT lf;

	HDC hdc = ::GetDC(NULL);
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfPitchAndFamily = 0;

	lstrcpy(lf.lfFaceName, szFaceName);

	BOOL bPresent = FALSE;
	EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)CheckFontProc, (LPARAM)&bPresent, 0);
	
	::ReleaseDC(NULL, hdc);

	return bPresent;
}

//////////////////////////////////
// theming

#ifndef STAP_ALLOW_NONCLIENT
	#define STAP_ALLOW_NONCLIENT    (1 << 0)
	#define STAP_ALLOW_CONTROLS     (1 << 1)
	#define STAP_ALLOW_WEBCONTENT   (1 << 2)
#endif


typedef void (STDAPICALLTYPE* SETTHEMEAPPPROPERTIES)(DWORD);

void CSkinBase::EnableTheming(BOOL bEnable)
{
	if (GetOS() < SBOS_XP || bEnable == s_bThemingEnabled)
		return;

	static HMODULE hUXTheme = ::LoadLibrary("UXTheme.dll");

	if (hUXTheme)
	{
		SETTHEMEAPPPROPERTIES SetThemeAppProperties = 
						(SETTHEMEAPPPROPERTIES)GetProcAddress(hUXTheme, "SetThemeAppProperties");

		if (SetThemeAppProperties)
		{
			SetThemeAppProperties(bEnable ? 
								STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS | STAP_ALLOW_WEBCONTENT :
								0);
			s_bThemingEnabled = bEnable;
		}
	}
}

BOOL CSkinBase::CreateThemeManifest(LPCTSTR szName, LPCTSTR szDescription)
{
//	if (GetOS() < SBOS_XP)
//		return FALSE;

	// create the manifest only if one does not exist
	CString sFilePath;
	::GetModuleFileName(NULL, sFilePath.GetBuffer(MAX_PATH + 1), MAX_PATH);
	sFilePath.ReleaseBuffer();

	sFilePath += ".Manifest";

	CFileStatus fs;

	if (CFile::GetStatus(sFilePath, fs))
		return TRUE; // already exists

	ASSERT (szName && strlen(szName) && szDescription && strlen(szDescription));

	if (!(szName && strlen(szName) && szDescription && strlen(szDescription)))
		return FALSE;

	LPCTSTR szManifestFmt = " \
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> \
<assembly \
    xmlns='urn:schemas-microsoft-com:asm.v1' \
    manifestVersion='1.0'> \
\
    <assemblyIdentity \
        version='1.0.0.0' \
        processorArchitecture='X86' \
        name='%s' \
        type='win32' \
    /> \
    <description>%s</description> \
    <dependency> \
        <dependentAssembly> \
            <assemblyIdentity \
                type='win32' \
                name='Microsoft.Windows.Common-Controls' \
                version='6.0.0.0' \
                processorArchitecture='X86' \
                publicKeyToken='6595b64144ccf1df' \
                language='*' \
            /> \
        </dependentAssembly> \
    </dependency> \
</assembly> ";

	CString sManifest;
	sManifest.Format(szManifestFmt, szName, szDescription);

	CStdioFile file;

	if (!file.Open(sFilePath, CFile::modeCreate | CFile::modeWrite | CFile::typeText))
		return FALSE;

	file.WriteString(sManifest);
	file.Close();

	return TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////

HICON CSkinBase::GetWindowIcon(CWnd* pWnd)
{
	ASSERT (pWnd);

	if (!pWnd)
		return NULL;

	HICON hIcon = pWnd->GetIcon(FALSE); // small icon
				
	if (!hIcon)
		hIcon = pWnd->GetIcon(TRUE); // large icon

	if (!hIcon)
	{
		WNDCLASS wndcls;
		CString sClass(CWinClasses::GetClass(*pWnd));

		if (GetClassInfo(AfxGetInstanceHandle(), sClass, &wndcls))
			hIcon = wndcls.hIcon;
	}

	return hIcon;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -