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

📄 platwin.cxx

📁 最强源代码编辑控件
💻 CXX
📖 第 1 页 / 共 5 页
字号:
	if (paletteOld) {
		// Fonts are not deleted as they are owned by a Palette object
		::SelectPalette(reinterpret_cast<HDC>(hdc),
			reinterpret_cast<HPALETTE>(paletteOld), TRUE);
		paletteOld = 0;
	}
	if (hdcOwned) {
		::DeleteDC(reinterpret_cast<HDC>(hdc));
		hdc = 0;
		hdcOwned = false;
	}
}

bool SurfaceImpl::Initialised() {
	return hdc != 0;
}

void SurfaceImpl::Init(WindowID) {
	Release();
	hdc = ::CreateCompatibleDC(NULL);
	hdcOwned = true;
	::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}

void SurfaceImpl::Init(SurfaceID sid, WindowID) {
	Release();
	hdc = reinterpret_cast<HDC>(sid);
	::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}

void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) {
	Release();
	hdc = ::CreateCompatibleDC(static_cast<SurfaceImpl *>(surface_)->hdc);
	hdcOwned = true;
	bitmap = ::CreateCompatibleBitmap(static_cast<SurfaceImpl *>(surface_)->hdc, width, height);
	bitmapOld = static_cast<HBITMAP>(::SelectObject(hdc, bitmap));
	::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}

void SurfaceImpl::PenColour(ColourAllocated fore) {
	if (pen) {
		::SelectObject(hdc, penOld);
		::DeleteObject(pen);
		pen = 0;
		penOld = 0;
	}
	pen = ::CreatePen(0,1,fore.AsLong());
	penOld = static_cast<HPEN>(::SelectObject(reinterpret_cast<HDC>(hdc), pen));
}

void SurfaceImpl::BrushColor(ColourAllocated back) {
	if (brush) {
		::SelectObject(hdc, brushOld);
		::DeleteObject(brush);
		brush = 0;
		brushOld = 0;
	}
	// Only ever want pure, non-dithered brushes
	ColourAllocated colourNearest = ::GetNearestColor(hdc, back.AsLong());
	brush = ::CreateSolidBrush(colourNearest.AsLong());
	brushOld = static_cast<HBRUSH>(::SelectObject(hdc, brush));
}

void SurfaceImpl::SetFont(Font &font_) {
	if (font_.GetID() != font) {
		if (fontOld) {
			::SelectObject(hdc, font_.GetID());
		} else {
			fontOld = static_cast<HFONT>(::SelectObject(hdc, font_.GetID()));
		}
		font = reinterpret_cast<HFONT>(font_.GetID());
	}
}

int SurfaceImpl::LogPixelsY() {
	return ::GetDeviceCaps(hdc, LOGPIXELSY);
}

int SurfaceImpl::DeviceHeightFont(int points) {
	return ::MulDiv(points, LogPixelsY(), 72);
}

void SurfaceImpl::MoveTo(int x_, int y_) {
	::MoveToEx(hdc, x_, y_, 0);
}

void SurfaceImpl::LineTo(int x_, int y_) {
	::LineTo(hdc, x_, y_);
}

void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
	PenColour(fore);
	BrushColor(back);
	::Polygon(hdc, reinterpret_cast<POINT *>(pts), npts);
}

void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
	PenColour(fore);
	BrushColor(back);
	::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
}

void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
	// Using ExtTextOut rather than a FillRect ensures that no dithering occurs.
	// There is no need to allocate a brush either.
	RECT rcw = RectFromPRectangle(rc);
	::SetBkColor(hdc, back.AsLong());
	::ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rcw, TEXT(""), 0, NULL);
}

void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
	HBRUSH br;
	if (static_cast<SurfaceImpl &>(surfacePattern).bitmap)
		br = ::CreatePatternBrush(static_cast<SurfaceImpl &>(surfacePattern).bitmap);
	else	// Something is wrong so display in red
		br = ::CreateSolidBrush(RGB(0xff, 0, 0));
	RECT rcw = RectFromPRectangle(rc);
	::FillRect(hdc, &rcw, br);
	::DeleteObject(br);
}

void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
	PenColour(fore);
	BrushColor(back);
	::RoundRect(hdc,
		rc.left + 1, rc.top,
		rc.right - 1, rc.bottom,
		8, 8);
}

// Plot a point into a DWORD buffer symetrically to all 4 qudrants
static void AllFour(DWORD *pixels, int width, int height, int x, int y, DWORD val) {
	pixels[y*width+x] = val;
	pixels[y*width+width-1-x] = val;
	pixels[(height-1-y)*width+x] = val;
	pixels[(height-1-y)*width+width-1-x] = val;
}

#ifndef AC_SRC_OVER
#define AC_SRC_OVER                 0x00
#endif
#ifndef AC_SRC_ALPHA
#define AC_SRC_ALPHA		0x01
#endif

void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
		ColourAllocated outline, int alphaOutline, int /* flags*/ ) {
	if (AlphaBlendFn) {
		HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
		int width = rc.Width();
		int height = rc.Height();
		// Ensure not distorted too much by corners when small
		cornerSize = Platform::Minimum(cornerSize, (Platform::Minimum(width, height) / 2) - 2);
		BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0};
		void *image = 0;
		HBITMAP hbmMem = CreateDIBSection(reinterpret_cast<HDC>(hMemDC), &bpih,
			DIB_RGB_COLORS, &image, NULL, 0);

		HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem);

		byte pixVal[4] = {0};
		DWORD valEmpty = *(reinterpret_cast<DWORD *>(pixVal));
		pixVal[0] = static_cast<byte>(GetBValue(fill.AsLong()) * alphaFill / 255);
		pixVal[1] = static_cast<byte>(GetGValue(fill.AsLong()) * alphaFill / 255);
		pixVal[2] = static_cast<byte>(GetRValue(fill.AsLong()) * alphaFill / 255);
		pixVal[3] = static_cast<byte>(alphaFill);
		DWORD valFill = *(reinterpret_cast<DWORD *>(pixVal));
		pixVal[0] = static_cast<byte>(GetBValue(outline.AsLong()) * alphaOutline / 255);
		pixVal[1] = static_cast<byte>(GetGValue(outline.AsLong()) * alphaOutline / 255);
		pixVal[2] = static_cast<byte>(GetRValue(outline.AsLong()) * alphaOutline / 255);
		pixVal[3] = static_cast<byte>(alphaOutline);
		DWORD valOutline = *(reinterpret_cast<DWORD *>(pixVal));
		DWORD *pixels = reinterpret_cast<DWORD *>(image);
		for (int y=0; y<height; y++) {
			for (int x=0; x<width; x++) {
				if ((x==0) || (x==width-1) || (y == 0) || (y == height-1)) {
					pixels[y*width+x] = valOutline;
				} else {
					pixels[y*width+x] = valFill;
				}
			}
		}
		for (int c=0;c<cornerSize; c++) {
			for (int x=0;x<c+1; x++) {
				AllFour(pixels, width, height, x, c-x, valEmpty);
			}
		}
		for (int x=1;x<cornerSize; x++) {
			AllFour(pixels, width, height, x, cornerSize-x, valOutline);
		}

		BLENDFUNCTION merge = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };

		AlphaBlendFn(reinterpret_cast<HDC>(hdc), rc.left, rc.top, width, height, hMemDC, 0, 0, width, height, merge);

		SelectBitmap(hMemDC, hbmOld);
		::DeleteObject(hbmMem);
		::DeleteObject(hMemDC);
	} else {
		RectangleDraw(rc, outline, fill);
	}
}

void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
	PenColour(fore);
	BrushColor(back);
	::Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
}

void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
	::BitBlt(hdc,
		rc.left, rc.top, rc.Width(), rc.Height(),
		static_cast<SurfaceImpl &>(surfaceSource).hdc, from.x, from.y, SRCCOPY);
}

const int MAX_US_LEN = 10000;

void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions) {
	SetFont(font_);
	RECT rcw = RectFromPRectangle(rc);
	SIZE sz={0,0};
	int pos = 0;
	int x = rc.left;

	// Text drawing may fail if the text is too big.
	// If it does fail, slice up into segments and draw each segment.
	const int maxSegmentLength = 0x200;

	if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
		// Use ANSI calls
		int lenDraw = Platform::Minimum(len, maxLenText);
		if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s, lenDraw, NULL)) {
			while (lenDraw > pos) {
				int seglen = Platform::Minimum(maxSegmentLength, lenDraw - pos);
				if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s+pos, seglen, NULL)) {
					PLATFORM_ASSERT(false);
					return;
				}
				::GetTextExtentPoint32A(hdc, s+pos, seglen, &sz);
				x += sz.cx;
				pos += seglen;
			}
		}
	} else {
		// Use Unicode calls
		wchar_t tbuf[MAX_US_LEN];
		int tlen;
		if (unicodeMode) {
			tlen = UCS2FromUTF8(s, len, tbuf, MAX_US_LEN);
		} else {
			// Support Asian string display in 9x English
			tlen = ::MultiByteToWideChar(codePage, 0, s, len, NULL, 0);
			if (tlen > MAX_US_LEN)
				tlen = MAX_US_LEN;
			::MultiByteToWideChar(codePage, 0, s, len, tbuf, tlen);
		}
		if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf, tlen, NULL)) {
			while (tlen > pos) {
				int seglen = Platform::Minimum(maxSegmentLength, tlen - pos);
				if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf+pos, seglen, NULL)) {
					PLATFORM_ASSERT(false);
					return;
				}
				::GetTextExtentPoint32W(hdc, tbuf+pos, seglen, &sz);
				x += sz.cx;
				pos += seglen;
			}
		}
	}
}

void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
	ColourAllocated fore, ColourAllocated back) {
	::SetTextColor(hdc, fore.AsLong());
	::SetBkColor(hdc, back.AsLong());
	DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE);
}

void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
	ColourAllocated fore, ColourAllocated back) {
	::SetTextColor(hdc, fore.AsLong());
	::SetBkColor(hdc, back.AsLong());
	DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED);
}

void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
	ColourAllocated fore) {
	// Avoid drawing spaces in transparent mode
	for (int i=0;i<len;i++) {
		if (s[i] != ' ') {
			::SetTextColor(hdc, fore.AsLong());
			::SetBkMode(hdc, TRANSPARENT);
			DrawTextCommon(rc, font_, ybase, s, len, 0);
			::SetBkMode(hdc, OPAQUE);
			return;
		}
	}
}

int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
	SetFont(font_);
	SIZE sz={0,0};
	if (unicodeMode) {
		wchar_t tbuf[MAX_US_LEN];
		int tlen = UCS2FromUTF8(s, len, tbuf, MAX_US_LEN);
		::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz);
	} else if (IsNT() || (codePage==0) || win9xACPSame) {
		::GetTextExtentPoint32A(hdc, s, Platform::Minimum(len, maxLenText), &sz);
	} else {
		// Support Asian string display in 9x English
		wchar_t tbuf[MAX_US_LEN];
		int tlen = ::MultiByteToWideChar(codePage, 0, s, len, NULL, 0);
		::MultiByteToWideChar(codePage, 0, s, len, tbuf, tlen);
		::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz);
	}
	return sz.cx;
}

void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
	SetFont(font_);
	SIZE sz={0,0};
	int fit = 0;
	if (unicodeMode) {
		wchar_t tbuf[MAX_US_LEN];
		int tlen = UCS2FromUTF8(s, len, tbuf, MAX_US_LEN);
		int poses[MAX_US_LEN];
		fit = tlen;
		if (!::GetTextExtentExPointW(hdc, tbuf, tlen, maxWidthMeasure, &fit, poses, &sz)) {
			// Likely to have failed because on Windows 9x where function not available
			// So measure the character widths by measuring each initial substring
			// Turns a linear operation into a qudratic but seems fast enough on test files
			for (int widthSS=0; widthSS < tlen; widthSS++) {
				::GetTextExtentPoint32W(hdc, tbuf, widthSS+1, &sz);
				poses[widthSS] = sz.cx;
			}
		}
		// Map the widths given for UCS-2 characters back onto the UTF-8 input string
		int ui=0;
		const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
		int i=0;
		while (ui<fit) {
			unsigned char uch = us[i];
			positions[i++] = poses[ui];
			if (uch >= 0x80) {
				if (uch < (0x80 + 0x40 + 0x20)) {
					positions[i++] = poses[ui];
				} else {
					positions[i++] = poses[ui];
					positions[i++] = poses[ui];
				}
			}
			ui++;
		}
		int lastPos = 0;
		if (i > 0)
			lastPos = positions[i-1];
		while (i<len) {
			positions[i++] = lastPos;
		}
	} else if (IsNT() || (codePage==0) || win9xACPSame) {
		if (!::GetTextExtentExPoint(hdc, s, Platform::Minimum(len, maxLenText),
			maxWidthMeasure, &fit, positions, &sz)) {
			// Eeek - a NULL DC or other foolishness could cause this.
			// The least we can do is set the positions to zero!
			memset(positions, 0, len * sizeof(*positions));
		} else if (fit < len) {
			// For some reason, such as an incomplete DBCS character
			// Not all the positions are filled in so make them equal to end.
			for (int i=fit;i<len;i++)
				positions[i] = positions[fit-1];
		}
	} else {
		// Support Asian string display in 9x English
		wchar_t tbuf[MAX_US_LEN];
		int tlen = ::MultiByteToWideChar(codePage, 0, s, len, NULL, 0);
		::MultiByteToWideChar(codePage, 0, s, len, tbuf, tlen);

		int poses[MAX_US_LEN];
		for (int widthSS=0; widthSS<tlen; widthSS++) {
			::GetTextExtentPoint32W(hdc, tbuf, widthSS+1, &sz);
			poses[widthSS] = sz.cx;
		}

		int ui = 0;
		for (int i=0;i<len;) {
			if (::IsDBCSLeadByteEx(codePage, s[i])) {
				positions[i] = poses[ui];
				positions[i+1] = poses[ui];
				i += 2;
			} else {
				positions[i] = poses[ui];
				i++;
			}

			ui++;
		}
	}
}

int SurfaceImpl::WidthChar(Font &font_, char ch) {
	SetFont(font_);
	SIZE sz;
	::GetTextExtentPoint32(hdc, &ch, 1, &sz);
	return sz.cx;
}

int SurfaceImpl::Ascent(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmAscent;
}

int SurfaceImpl::Descent(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmDescent;
}

int SurfaceImpl::InternalLeading(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmInternalLeading;
}

int SurfaceImpl::ExternalLeading(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmExternalLeading;
}

int SurfaceImpl::Height(Font &font_) {
	SetFont(font_);

⌨️ 快捷键说明

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