예제 #1
0
파일: NppShell.cpp 프로젝트: Tanjas5/npp
STDMETHODIMP CShellExt::Extract(LPCTSTR /*pszFile*/, UINT /*nIconIndex*/, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize) {
	WORD sizeSmall = HIWORD(nIconSize);
	WORD sizeLarge = LOWORD(nIconSize);
	ICONINFO iconinfo;
	BOOL res;
	HRESULT hrSmall = S_OK, hrLarge = S_OK;

	if (phiconSmall)
		hrSmall = LoadShellIcon(sizeSmall, sizeSmall, phiconSmall);
	if (phiconLarge)
		hrLarge = LoadShellIcon(sizeLarge, sizeLarge, phiconLarge);

	if (FAILED(hrSmall) || FAILED(hrLarge)) {
		InvalidateIcon(phiconSmall, phiconLarge);
		return S_FALSE;
	}

	if (!m_isDynamic || !phiconLarge || sizeLarge < 32)	//No modifications required
		return S_OK;

	HDC dcEditColor, dcEditMask, dcEditTemp;
	HFONT font;
	HBRUSH brush;
	HPEN pen;
	BITMAPINFO bmi;
    HBITMAP hbm;
    LPDWORD pPix;

	res = GetIconInfo(*phiconLarge, &iconinfo);
	if (!res)
		return S_OK;	//abort, the icon is still valid

	res = DestroyIcon(*phiconLarge);
	if (!res)
		return S_OK;
	else
		*phiconLarge = NULL;

	dcEditColor = CreateCompatibleDC(GetDC(0));
	dcEditMask = CreateCompatibleDC(GetDC(0));
	dcEditTemp = CreateCompatibleDC(GetDC(0));

    // Create temp bitmap to render rectangle to
    ZeroMemory(&bmi, sizeof(bmi));
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = sizeLarge;
    bmi.bmiHeader.biHeight = sizeLarge;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    hbm = CreateDIBSection(dcEditTemp, &bmi, DIB_RGB_COLORS, (VOID**)&pPix, NULL, 0);
    memset(pPix, 0x00FFFFFF, sizeof(DWORD)*sizeLarge*sizeLarge);	//initialize to white pixels, no alpha

	SelectObject(dcEditColor, iconinfo.hbmColor);
	SelectObject(dcEditMask, iconinfo.hbmMask);
	SelectObject(dcEditTemp, hbm);

	LONG calSize = (LONG)(sizeLarge*2/5);

	LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}};
	lf.lfHeight = calSize;
	lf.lfWeight = FW_NORMAL;
	lf.lfCharSet = DEFAULT_CHARSET;
	lstrcpyn(lf.lfFaceName, TEXT("Courier New"), LF_FACESIZE);
	RECT rectText = {0, 0, 0, 0};
	RECT rectBox = {0, 0, 0, 0};
	COLORREF backGround = RGB(1, 1, 60);
	COLORREF textColor = RGB(250,250,250);

	font = CreateFontIndirect(&lf);
	brush = CreateSolidBrush(backGround);
	pen = CreatePen(PS_NULL, 0, backGround);
	SelectObject(dcEditTemp, font);
	SelectObject(dcEditTemp, brush);
	SelectObject(dcEditTemp, pen);
	SetBkMode(dcEditTemp, TRANSPARENT);	//dont clear background when drawing text
	SetBkColor(dcEditTemp,  backGround);
	SetTextColor(dcEditTemp, textColor);

	//Calculate size of the displayed string
	SIZE stringSize;
	GetTextExtentPoint32(dcEditTemp, m_szFilePath, m_nameLength, &stringSize);
	stringSize.cx = std::min(stringSize.cx, (LONG)sizeLarge-2);
	stringSize.cy = std::min(stringSize.cy, (LONG)sizeLarge-2);

	rectText.top = sizeLarge - stringSize.cy - 1;
	rectText.left = sizeLarge - stringSize.cx - 1;
	rectText.bottom = sizeLarge - 1;
	rectText.right = sizeLarge - 1;

	rectBox.top = sizeLarge - stringSize.cy - 2;
	rectBox.left = sizeLarge - stringSize.cx - 2;
	rectBox.bottom = sizeLarge;
	rectBox.right = sizeLarge;

	//Draw the background (rounded) rectangle
	int elipsSize = calSize/3;
	RoundRect(dcEditTemp, rectBox.left, rectBox.top, rectBox.right, rectBox.bottom, elipsSize, elipsSize);
	//Draw text in the rectangle
	DrawText(dcEditTemp, m_szFilePath, m_nameLength, &rectText, DT_BOTTOM|DT_SINGLELINE|DT_LEFT);

	//set alpha of non white pixels back to 255
	//premultiply alpha
	//Fill in the mask bitmap (anything not 100% alpha is transparent)
	int red, green, blue, alpha;
	for(int y = 0; y < sizeLarge; y++) {
		for(int x = 0; x < sizeLarge; x++) {
			DWORD * pix = pPix+(y*sizeLarge+x);
			red = *pix & 0xFF;
			green = *pix >> 8 & 0xFF;
			blue = *pix >> 16 & 0xFF;
			alpha = *pix >> 24 & 0xFF;
			if ((*pix << 8) == 0xFFFFFF00)
				alpha = 0x00;
			else
				alpha = 0xFF;
			red = (red*alpha)/0xFF;
			green = (green*alpha)/0xFF;
			blue = (blue*alpha)/0xFF;
			*pix = RGBA(red, green, blue, alpha);
		}
	}

	BLENDFUNCTION ftn = { AC_SRC_OVER, 0, 0xFF, AC_SRC_ALPHA };
	int width = rectBox.right - rectBox.left;
	int height = rectBox.bottom - rectBox.top;
	AlphaBlend(dcEditColor, rectBox.left, rectBox.top, stringSize.cx, stringSize.cy, dcEditTemp, rectBox.left, rectBox.top, width, height, ftn);

	//Adjust the mask image: simply draw the rectangle to it
	backGround = RGB(0, 0, 0);
	DeleteBrush(brush);
	DeletePen(pen);
	brush = CreateSolidBrush(backGround);
	pen = CreatePen(PS_NULL, 0, backGround);
	SelectObject(dcEditMask, brush);
	SelectObject(dcEditMask, pen);
	RoundRect(dcEditMask, rectBox.left, rectBox.top, rectBox.right, rectBox.bottom, elipsSize, elipsSize);


	DeleteDC(dcEditColor);
	DeleteDC(dcEditMask);
	DeleteDC(dcEditTemp);
	DeleteBrush(brush);
	DeletePen(pen);
	DeleteFont(font);
	DeleteBitmap(hbm);

	*phiconLarge = CreateIconIndirect(&iconinfo);
	DeleteBitmap(iconinfo.hbmColor);
	DeleteBitmap(iconinfo.hbmMask);

	if (*phiconLarge == NULL) {
		InvalidateIcon(phiconSmall, phiconLarge);
		return S_FALSE;
	}

	return S_OK;
}
예제 #2
0
STDMETHODIMP CShellExt::Extract(LPCTSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize) {
	WORD sizeSmall = HIWORD(nIconSize);
	WORD sizeLarge = LOWORD(nIconSize);
	ICONINFO iconinfo;
	BOOL res;
	HRESULT hrSmall = S_OK, hrLarge = S_OK;

	if (phiconSmall)
		hrSmall = LoadShellIcon(sizeSmall, sizeSmall, phiconSmall);
	if (phiconLarge)
		hrLarge = LoadShellIcon(sizeLarge, sizeLarge, phiconLarge);

	if (FAILED(hrSmall) || FAILED(hrLarge)) {
		InvalidateIcon(phiconSmall, phiconLarge);
		return S_FALSE;
	}

	if (!m_isDynamic || !phiconLarge)	//No modifications required
		return S_OK;

	HDC dcEditColor, dcEditMask;
	HGDIOBJ oldBitmapColor, oldBitmapMask, oldFontColor;
	HFONT font;
	HBRUSH brush;

	res = GetIconInfo(*phiconLarge, &iconinfo);
	if (!res)
		return S_OK;	//abort, the icon is still valid

	res = DestroyIcon(*phiconLarge);
	if (!res)
		return S_OK;
	else
		*phiconLarge = NULL;

	dcEditColor = CreateCompatibleDC(GetDC(0));
	dcEditMask = CreateCompatibleDC(GetDC(0));
	oldBitmapColor = SelectObject(dcEditColor, iconinfo.hbmColor);
	oldBitmapMask = SelectObject(dcEditMask, iconinfo.hbmMask);

	LONG calSize = (LONG)(sizeLarge*2/5);
	LOGFONT lf = {0};
	lf.lfHeight = std::min(calSize, (LONG)15);	//this is in pixels. Make no larger than 15 pixels (but smaller is allowed for small icons)
	lf.lfWeight = FW_NORMAL;
	lf.lfCharSet = DEFAULT_CHARSET;
	lstrcpyn(lf.lfFaceName, TEXT("Bitstream Vera Sans Mono"), LF_FACESIZE);
	LOGBRUSH lbrush;
	lbrush.lbStyle = BS_SOLID;
	lbrush.lbHatch = 0;
	RECT rect = {0};
	COLORREF backGround = RGB(1, 1, 1);
	COLORREF textColor = RGB(255,255,255);
	//Grab the topleft pixel as the background color
	COLORREF maskBack = GetPixel(dcEditColor, 0, 0);
	if (backGround == maskBack)
		backGround++;	//add one, shouldn't be very visible

	font = CreateFontIndirect(&lf);
	lbrush.lbColor = backGround;
	brush = CreateBrushIndirect(&lbrush);
	oldFontColor = SelectObject(dcEditColor, font);

	SetBkMode(dcEditColor, TRANSPARENT);	//dont clear background when drawing text (doesnt change much, colors are the same)
	SetBkColor(dcEditColor,  backGround);
	SetTextColor(dcEditColor, textColor);

	SIZE stringSize;
	GetTextExtentPoint32(dcEditColor, m_szFilePath, m_nameLength, &stringSize);
	stringSize.cx = std::min(stringSize.cx, (LONG)sizeLarge-2);
	stringSize.cy = std::min(stringSize.cy, (LONG)sizeLarge-2);

	rect.top = sizeLarge - stringSize.cy - 2;
	rect.left = sizeLarge - stringSize.cx - 1;
	rect.bottom = sizeLarge;
	rect.right = sizeLarge-1;
	FillRect(dcEditColor, &rect, brush);
	FillRect(dcEditMask, &rect, brush);

	rect.top += 1;
	rect.left -= 1;
	rect.bottom -= 1;
	rect.right += 1;
	FillRect(dcEditColor, &rect, brush);
	FillRect(dcEditMask, &rect, brush);

	rect.left += 1;
	DrawText(dcEditColor, m_szFilePath, m_nameLength, &rect, DT_BOTTOM|DT_SINGLELINE|DT_LEFT);

	SetBkColor(dcEditColor,  maskBack);
	//BitBlt(dcEditMask, 0, 0, sizeLarge, sizeLarge, dcEditColor, 0, 0, SRCCOPY);

	SelectObject(dcEditColor, oldFontColor);
	SelectObject(dcEditColor, oldBitmapColor);
	SelectObject(dcEditMask, oldBitmapMask);
	DeleteDC(dcEditColor);
	DeleteDC(dcEditMask);
	DeleteBrush(brush);


	*phiconLarge = CreateIconIndirect(&iconinfo);
	res = DeleteBitmap(iconinfo.hbmColor);
	res = DeleteBitmap(iconinfo.hbmMask);

	if (*phiconLarge == NULL) {
		InvalidateIcon(phiconSmall, phiconLarge);
		return S_FALSE;
	}

	return S_OK;
}