📄 platwin.cxx
字号:
// 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, "", 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 );
}
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);
}
#define MAX_US_LEN 10000
void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back) {
SetFont(font_);
::SetTextColor(hdc, fore.AsLong());
::SetBkColor(hdc, back.AsLong());
RECT rcw = RectFromPRectangle(rc);
if (unicodeMode) {
wchar_t tbuf[MAX_US_LEN];
int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)-1);
tbuf[tlen] = L'\0';
::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, tbuf, tlen, NULL);
} else {
::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, s,
Platform::Minimum(len, maxLenText), NULL);
}
}
void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
ColourAllocated fore, ColourAllocated back) {
SetFont(font_);
::SetTextColor(hdc, fore.AsLong());
::SetBkColor(hdc, back.AsLong());
RECT rcw = RectFromPRectangle(rc);
if (unicodeMode) {
wchar_t tbuf[MAX_US_LEN];
int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)-1);
tbuf[tlen] = L'\0';
::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, tbuf, tlen, NULL);
} else {
::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, s,
Platform::Minimum(len, maxLenText), NULL);
}
}
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] != ' ') {
SetFont(font_);
::SetTextColor(hdc, fore.AsLong());
::SetBkMode(hdc, TRANSPARENT);
RECT rcw = RectFromPRectangle(rc);
if (unicodeMode) {
wchar_t tbuf[MAX_US_LEN];
int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)-1);
tbuf[tlen] = L'\0';
::ExtTextOutW(hdc, rc.left, ybase, 0, &rcw, tbuf, tlen, NULL);
} else {
::ExtTextOut(hdc, rc.left, ybase, 0, &rcw, s,
Platform::Minimum(len,maxLenText), NULL);
}
::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, sizeof(tbuf)/sizeof(wchar_t)-1);
tbuf[tlen] = L'\0';
::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz);
} else {
::GetTextExtentPoint32(hdc, s, Platform::Minimum(len, maxLenText), &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, sizeof(tbuf)/sizeof(wchar_t)-1);
tbuf[tlen] = L'\0';
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 (!::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];
}
}
}
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_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmHeight;
}
int SurfaceImpl::AverageCharWidth(Font &font_) {
SetFont(font_);
TEXTMETRIC tm;
::GetTextMetrics(hdc, &tm);
return tm.tmAveCharWidth;
}
int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
if (paletteOld) {
::SelectPalette(hdc, paletteOld, TRUE);
}
paletteOld = 0;
int changes = 0;
if (pal->allowRealization) {
paletteOld = ::SelectPalette(hdc,
reinterpret_cast<HPALETTE>(pal->hpal), inBackGround);
changes = ::RealizePalette(hdc);
}
return changes;
}
void SurfaceImpl::SetClip(PRectangle rc) {
::IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
void SurfaceImpl::FlushCachedState() {
pen = 0;
brush = 0;
font = 0;
}
void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
unicodeMode=unicodeMode_;
}
void SurfaceImpl::SetDBCSMode(int) {
// No action on window as automatically handled by system.
}
Surface *Surface::Allocate() {
return new SurfaceImpl;
}
Window::~Window() {
}
void Window::Destroy() {
if (id)
::DestroyWindow(reinterpret_cast<HWND>(id));
id = 0;
}
bool Window::HasFocus() {
return ::GetFocus() == id;
}
PRectangle Window::GetPosition() {
RECT rc;
::GetWindowRect(reinterpret_cast<HWND>(id), &rc);
return PRectangle(rc.left, rc.top, rc.right, rc.bottom);
}
void Window::SetPosition(PRectangle rc) {
::SetWindowPos(reinterpret_cast<HWND>(id),
0, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER|SWP_NOACTIVATE);
}
void Window::SetPositionRelative(PRectangle rc, Window w) {
LONG style = ::GetWindowLong(reinterpret_cast<HWND>(id), GWL_STYLE);
if (style & WS_POPUP) {
RECT rcOther;
::GetWindowRect(reinterpret_cast<HWND>(w.GetID()), &rcOther);
rc.Move(rcOther.left, rcOther.top);
if (rc.left < 0) {
rc.Move(-rc.left,0);
}
if (rc.top < 0) {
rc.Move(0,-rc.top);
}
}
SetPosition(rc);
}
PRectangle Window::GetClientPosition() {
RECT rc={0,0,0,0};
if (id)
::GetClientRect(reinterpret_cast<HWND>(id), &rc);
return PRectangle(rc.left, rc.top, rc.right, rc.bottom);
}
void Window::Show(bool show) {
if (show)
::ShowWindow(reinterpret_cast<HWND>(id), SW_SHOWNOACTIVATE);
else
::ShowWindow(reinterpret_cast<HWND>(id), SW_HIDE);
}
void Window::InvalidateAll() {
::InvalidateRect(reinterpret_cast<HWND>(id), NULL, FALSE);
}
void Window::InvalidateRectangle(PRectangle rc) {
RECT rcw = RectFromPRectangle(rc);
::InvalidateRect(reinterpret_cast<HWND>(id), &rcw, FALSE);
}
static LRESULT Window_SendMessage(Window *w, UINT msg, WPARAM wParam=0, LPARAM lParam=0) {
return ::SendMessage(reinterpret_cast<HWND>(w->GetID()), msg, wParam, lParam);
}
void Window::SetFont(Font &font) {
Window_SendMessage(this, WM_SETFONT,
reinterpret_cast<WPARAM>(font.GetID()), 0);
}
void Window::SetCursor(Cursor curs) {
switch (curs) {
case cursorText:
::SetCursor(::LoadCursor(NULL,IDC_IBEAM));
break;
case cursorUp:
::SetCursor(::LoadCursor(NULL,IDC_UPARROW));
break;
case cursorWait:
::SetCursor(::LoadCursor(NULL,IDC_WAIT));
break;
case cursorHoriz:
::SetCursor(::LoadCursor(NULL,IDC_SIZEWE));
break;
case cursorVert:
::SetCursor(::LoadCursor(NULL,IDC_SIZENS));
break;
case cursorHand:
::SetCursor(::LoadCursor(NULL,IDC_HAND));
break;
case cursorReverseArrow: {
if (!hinstPlatformRes)
hinstPlatformRes = ::GetModuleHandle("Scintilla");
if (!hinstPlatformRes)
hinstPlatformRes = ::GetModuleHandle("SciLexer");
if (!hinstPlatformRes)
hinstPlatformRes = ::GetModuleHandle(NULL);
HCURSOR hcursor = ::LoadCursor(hinstPlatformRes, MAKEINTRESOURCE(IDC_MARGIN));
if (hcursor)
::SetCursor(hcursor);
else
::SetCursor(::LoadCursor(NULL,IDC_ARROW));
}
break;
case cursorArrow:
case cursorInvalid: // Should not occur, but just in case.
::SetCursor(::LoadCursor(NULL,IDC_ARROW));
break;
}
}
void Window::SetTitle(const char *s) {
::SetWindowText(reinterpret_cast<HWND>(id), s);
}
class LineToType {
int *data;
int len;
int maximum;
public:
LineToType() :data(0), len(0), maximum(0) {
}
~LineToType() {
Clear();
}
void Clear() {
delete []data;
data = 0;
len = 0;
maximum = 0;
}
void Add(int index, int value) {
if (index >= maximum) {
if (index >= len) {
int lenNew = (index+1) * 2;
int *dataNew = new int[lenNew];
for (int i=0; i<maximum; i++) {
dataNew[i] = data[i];
}
delete []data;
data = dataNew;
len = lenNew;
}
while (maximum < index) {
data[maximum] = 0;
maximum++;
}
}
data[index] = value;
if (index == maximum) {
maximum++;
}
}
int Get(int index) {
if (index < maximum) {
return data[index];
} else {
return 0;
}
}
};
const char ListBoxX_ClassName[] = "ListBoxX";
ListBox::ListBox() {
}
ListBox::~ListBox() {
}
class ListBoxX : public ListBox {
int lineHeight;
FontID fontCopy;
XPMSet xset;
LineToType ltt;
HWND lb;
bool unicodeMode;
int desiredVisibleRows;
unsigned int maxItemCharacters;
unsigned int aveCharWidth;
public:
ListBoxX() : lineHeight(10), fontCopy(0), lb(0), unicodeMode(false),
desiredVisibleRows(5), maxItemCharacters(0), aveCharWidth(8){
}
virtual ~ListBoxX() {
if (fontCopy) {
::DeleteObject(fontCopy);
fontCopy = 0;
}
}
virtual void SetFont(Font &font);
virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_);
virtual void SetAverageCharWidth(int width);
virtual void SetVisibleRows(int rows);
virtual PRectangle GetDesiredRect();
int IconWidth();
virtual int CaretFromEdge();
virtual void Clear();
virtual void Append(char *s, int type = -1);
virtual int Length();
virtual void Select(int n);
virtual int GetSelection();
virtual int Find(const char *prefix);
virtual void GetValue(int n, char *value, int len);
virtual void Sort();
virtual void RegisterImage(int type, const char *xpm_data);
virtual void ClearRegisteredImages();
virtual void SetDoubleClickAction(CallBackAction, void *) {
}
void Draw(DRAWITEMSTRUCT *pDrawItem);
long WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
static long PASCAL StaticWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
};
ListBox *ListBox::Allocate() {
ListBoxX *lb = new ListBoxX();
return lb;
}
void ListBoxX::Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_) {
lineHeight = lineHeight_;
unicodeMode = unicodeMode_;
HINSTANCE hinstanceParent = GetWindowInstance(reinterpret_cast<HWND>(parent.GetID()));
id = ::CreateWindowEx(
WS_EX_WINDOWEDGE, ListBoxX_ClassName, "",
WS_CHILD | WS_THICKFRAME,
100,100, 150,80, reinterpret_cast<HWND>(parent.GetID()),
reinterpret_cast<HMENU>(ctrlID),
hinstanceParent,
this);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -