diff --git a/rainbow/WinAlt/ChSysInit.cpp b/rainbow/WinAlt/ChSysInit.cpp new file mode 100644 index 000000000..66a6401fe --- /dev/null +++ b/rainbow/WinAlt/ChSysInit.cpp @@ -0,0 +1,16 @@ +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +void ChSysInit() +{ + CtrlImg::Reset(); + CtrlsImg::Reset(); + ChReset(); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/DrawOpWinAlt.cpp b/rainbow/WinAlt/DrawOpWinAlt.cpp new file mode 100644 index 000000000..1f40c84ba --- /dev/null +++ b/rainbow/WinAlt/DrawOpWinAlt.cpp @@ -0,0 +1,296 @@ +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) +#define LTIMING(x) // RTIMING(x) + +void SystemDraw::BeginOp() +{ + LTIMING("Begin"); + GuiLock __; + Cloff& w = cloff.Add(); + w.org = actual_offset; + w.drawingclip = drawingclip; + w.hrgn = CreateRectRgn(0, 0, 0, 0); + ASSERT(w.hrgn); + int q = ::GetClipRgn(handle, w.hrgn); + ASSERT(q >= 0); + if(q == 0) { + DeleteObject(w.hrgn); + w.hrgn = NULL; + } +} + +void SystemDraw::OffsetOp(Point p) +{ + GuiLock __; + Begin(); + actual_offset += p; + drawingclip -= p; + LTIMING("Offset"); + SetOrg(); +} + +bool SystemDraw::ClipOp(const Rect& r) +{ + GuiLock __; + Begin(); + LTIMING("Clip"); + return IntersectClip(r); +} + +bool SystemDraw::ClipoffOp(const Rect& r) +{ + GuiLock __; + Begin(); + LTIMING("Clipoff"); + LLOG("ClipoffOp " << r << ", GetClip() = " << GetClip() << ", actual_offset = " << actual_offset); + actual_offset += r.TopLeft(); + bool q = IntersectClip(r); + drawingclip -= r.TopLeft(); + SetOrg(); + LLOG("//ClipoffOp, GetClip() = " << GetClip() << ", actual_offset = " << actual_offset); + return q; +} + +void SystemDraw::EndOp() +{ + GuiLock __; + LTIMING("End"); + ASSERT(cloff.GetCount()); + Cloff& w = cloff.Top(); + actual_offset = w.org; + drawingclip = w.drawingclip; + ::SelectClipRgn(handle, w.hrgn); + SetOrg(); + if(w.hrgn) + ::DeleteObject(w.hrgn); + cloff.Drop(); +} + +bool SystemDraw::ExcludeClipOp(const Rect& r) +{ + GuiLock __; +#ifdef PLATFORM_WINCE + int q = ExcludeClipRect(handle, r.left, r.top, r.right, r.bottom); +#else + LTIMING("ExcludeClip"); + if(r.Contains(drawingclip)) + drawingclip = Rect(0, 0, 0, 0); + Rect rr = LPtoDP(r); + HRGN hrgn = ::CreateRectRgnIndirect(rr); + int q = ::ExtSelectClipRgn(handle, hrgn, RGN_DIFF); + ASSERT(q != ERROR); + ::DeleteObject(hrgn); +#endif + return q == SIMPLEREGION || q == COMPLEXREGION; +} + +bool SystemDraw::IntersectClipOp(const Rect& r) +{ + GuiLock __; +#ifdef PLATFORM_WINCE + int q = IntersectClipRect(handle, r.left, r.top, r.right, r.bottom); +#else + LTIMING("Intersect"); + drawingclip &= r; + Rect rr = LPtoDP(r); + HRGN hrgn = ::CreateRectRgnIndirect(rr); + int q = ::ExtSelectClipRgn(handle, hrgn, RGN_AND); + ASSERT(q != ERROR); + ::DeleteObject(hrgn); +#endif + return q == SIMPLEREGION || q == COMPLEXREGION; +} + +bool SystemDraw::IsPaintingOp(const Rect& r) const +{ + GuiLock __; + LTIMING("IsPainting"); + LLOG("SystemDraw::IsPaintingOp r: " << r); + return ::RectVisible(handle, r); +} + +Rect SystemDraw::GetPaintRect() const +{ + GuiLock __; + LTIMING("GetPaintRect"); + return drawingclip; +} + +void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color) +{ + GuiLock __; + LTIMING("DrawRect"); + LLOG("DrawRect " << RectC(x, y, cx, cy) << ": " << color); + if(IsNull(color)) return; + if(cx <= 0 || cy <= 0) return; + if(color == InvertColor) + ::PatBlt(handle, x, y, cx, cy, DSTINVERT); + else { + SetColor(color); + ::PatBlt(handle, x, y, cx, cy, PATCOPY); + } +} + +void SystemDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color) +{ + GuiLock __; + if(IsNull(width) || IsNull(color)) return; + SetDrawPen(width, color); + ::MoveToEx(handle, x1, y1, NULL); + ::LineTo(handle, x2, y2); +} + +#ifndef PLATFORM_WINCE + +void SystemDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count, + const int *counts, int count_count, + int width, Color color, Color doxor) +{ + GuiLock __; + ASSERT(count_count > 0 && vertex_count > 0); + if(vertex_count < 2 || IsNull(color)) + return; + bool is_xor = !IsNull(doxor); + if(is_xor) + color = Color(color.GetR() ^ doxor.GetR(), color.GetG() ^ doxor.GetG(), color.GetB() ^ doxor.GetB()); + if(is_xor) + SetROP2(GetHandle(), R2_XORPEN); + SetDrawPen(width, color); + if(count_count == 1) + ::Polyline(GetHandle(), (const POINT *)vertices, vertex_count); + else + ::PolyPolyline(GetHandle(), (const POINT *)vertices, + (const dword *)counts, count_count); + if(is_xor) + SetROP2(GetHandle(), R2_COPYPEN); +} + +static void DrawPolyPolyPolygonRaw( + SystemDraw& draw, const Point *vertices, int vertex_count, + const int *subpolygon_counts, int subpolygon_count_count, + const int *disjunct_polygon_counts, int disjunct_polygon_count_count) +{ + GuiLock __; + for(int i = 0; i < disjunct_polygon_count_count; i++, disjunct_polygon_counts++) + { + int poly = *disjunct_polygon_counts; + int sub = 1; + if(*subpolygon_counts < poly) + if(disjunct_polygon_count_count > 1) + { + const int *se = subpolygon_counts; + int total = 0; + while(total < poly) + total += *se++; + sub = (int)(se - subpolygon_counts); + } + else + sub = subpolygon_count_count; + ASSERT(sizeof(POINT) == sizeof(Point)); // modify algorithm when not + if(sub == 1) + Polygon(draw, (const POINT *)vertices, poly); + else + PolyPolygon(draw, (const POINT *)vertices, subpolygon_counts, sub); + vertices += poly; + subpolygon_counts += sub; + } +} + +void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int subpolygon_count_count, + const int *disjunct_polygon_counts, int disjunct_polygon_count_count, + Color color, int width, Color outline, uint64 pattern, Color doxor) +{ + GuiLock __; + if(vertex_count == 0) + return; + bool is_xor = !IsNull(doxor); + HDC hdc = GetHandle(); + if(pattern) { + int old_rop = GetROP2(hdc); + HGDIOBJ old_brush = GetCurrentObject(hdc, OBJ_BRUSH); + word wpat[8] = { + (byte)(pattern >> 56), (byte)(pattern >> 48), (byte)(pattern >> 40), (byte)(pattern >> 32), + (byte)(pattern >> 24), (byte)(pattern >> 16), (byte)(pattern >> 8), (byte)(pattern >> 0), + }; + HBITMAP bitmap = CreateBitmap(8, 8, 1, 1, wpat); + HBRUSH brush = ::CreatePatternBrush(bitmap); + COLORREF old_bk = GetBkColor(hdc); + COLORREF old_fg = GetTextColor(hdc); + if(!is_xor) { + SetROP2(hdc, R2_MASKPEN); + SelectObject(hdc, brush); + SetTextColor(hdc, Black()); + SetBkColor(hdc, White()); + SetDrawPen(PEN_NULL, Black); + DrawPolyPolyPolygonRaw(*this, vertices, vertex_count, + subpolygon_counts, subpolygon_count_count, + disjunct_polygon_counts, disjunct_polygon_count_count); + SetROP2(hdc, R2_MERGEPEN); + SetTextColor(hdc, color); + SetBkColor(hdc, Black()); + } + else { + SetROP2(hdc, R2_XORPEN); + SetTextColor(hdc, COLORREF(color) ^ COLORREF(doxor)); + SelectObject(hdc, brush); + } + DrawPolyPolyPolygonRaw(*this, vertices, vertex_count, + subpolygon_counts, subpolygon_count_count, + disjunct_polygon_counts, disjunct_polygon_count_count); + SelectObject(hdc, old_brush); + SetTextColor(hdc, old_fg); + SetBkColor(hdc, old_bk); + SetROP2(hdc, old_rop); + DeleteObject(brush); + DeleteObject(bitmap); + if(!IsNull(outline)) { + SetColor(Null); + SetDrawPen(width, outline); + ASSERT(sizeof(POINT) == sizeof(Point)); + DrawPolyPolyPolygonRaw(*this, vertices, vertex_count, + subpolygon_counts, subpolygon_count_count, + disjunct_polygon_counts, disjunct_polygon_count_count); + } + } + else { // simple fill + SetDrawPen(IsNull(outline) ? PEN_NULL : width, Nvl(outline, Black)); + int old_rop2; + if(is_xor) { + color = Color(color.GetR() ^ doxor.GetR(), color.GetG() ^ doxor.GetG(), color.GetB() ^ doxor.GetB()); + old_rop2 = SetROP2(hdc, R2_XORPEN); + } + SetColor(color); + DrawPolyPolyPolygonRaw(*this, vertices, vertex_count, + subpolygon_counts, subpolygon_count_count, + disjunct_polygon_counts, disjunct_polygon_count_count); + if(is_xor) + SetROP2(hdc, old_rop2); + } +} + +void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color) +{ + GuiLock __; + SetDrawPen(width, color); + ::Arc(GetHandle(), rc.left, rc.top, rc.right, rc.bottom, start.x, start.y, end.x, end.y); +} + +#endif + +void SystemDraw::DrawEllipseOp(const Rect& r, Color color, int width, Color pencolor) +{ + GuiLock __; + SetColor(color); + SetDrawPen(width, pencolor); + ::Ellipse(GetHandle(), r.left, r.top, r.right, r.bottom); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/DrawTextWinAlt.cpp b/rainbow/WinAlt/DrawTextWinAlt.cpp new file mode 100644 index 000000000..e0517125e --- /dev/null +++ b/rainbow/WinAlt/DrawTextWinAlt.cpp @@ -0,0 +1,46 @@ +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +#define LLOG(x) + +HFONT GetWin32Font(Font fnt, int angle); + +void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, + int n, const int *dx) { + Std(font); + while(n > 30000) { + DrawTextOp(x, y, angle, text, font, ink, 30000, dx); + if(dx) + for(int i = 0; i < 30000; i++) + x += *dx++; + else + x += GetTextSize(text, font, 30000).cx; + n -= 30000; + text += 30000; + } + GuiLock __; + COLORREF cr = GetColor(ink); + if(cr != lastTextColor) { + LLOG("Setting text color: " << ink); + ::SetTextColor(handle, lastTextColor = cr); + } + HGDIOBJ orgfont = ::SelectObject(handle, GetWin32Font(font, angle)); + int ascent = font.Info().GetAscent(); + if(angle) { + double sina, cosa; + Draw::SinCos(angle, sina, cosa); + Size offset; + ::ExtTextOutW(handle, x + fround(ascent * sina), y + fround(ascent * cosa), 0, NULL, (const WCHAR *)text, n, dx); + } + else + ::ExtTextOutW(handle, x, y + ascent, 0, NULL, (const WCHAR *)text, + n, dx); + ::SelectObject(handle, orgfont); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/DrawWinAlt.cpp b/rainbow/WinAlt/DrawWinAlt.cpp new file mode 100644 index 000000000..0345edde7 --- /dev/null +++ b/rainbow/WinAlt/DrawWinAlt.cpp @@ -0,0 +1,467 @@ +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) +#define LTIMING(x) // RTIMING(x) + +static COLORREF sLightGray; + +Rect SystemDraw::GetVirtualScreenArea() +{ + GuiLock __; + return RectC(GetSystemMetrics(SM_XVIRTUALSCREEN), + GetSystemMetrics(SM_YVIRTUALSCREEN), + GetSystemMetrics(SM_CXVIRTUALSCREEN), + GetSystemMetrics(SM_CYVIRTUALSCREEN)); +} + +dword SystemDraw::GetInfo() const +{ + return DATABANDS|(native || !(style & DOTS) ? style|NATIVE : style); +} + +Size SystemDraw::GetPageSize() const +{ + return native && Dots() ? nativeSize : pageSize; +} + +Size SystemDraw::GetNativeDpi() const +{ + return Dots() ? nativeDpi : Size(96, 96); +} + +#ifndef PLATFORM_WINCE +void Add(LOGPALETTE *pal, int r, int g, int b) +{ + pal->palPalEntry[pal->palNumEntries].peRed = min(r, 255); + pal->palPalEntry[pal->palNumEntries].peGreen = min(g, 255); + pal->palPalEntry[pal->palNumEntries].peBlue = min(b, 255); + pal->palPalEntry[pal->palNumEntries++].peFlags = PC_NOCOLLAPSE; +} + +HPALETTE GetQlibPalette() +{ + static HPALETTE hQlibPalette; + if(hQlibPalette) return hQlibPalette; + SystemDraw::InitColors(); + LOGPALETTE *pal = (LOGPALETTE *) new byte[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)]; + pal->palNumEntries = 0; + pal->palVersion = 0x300; + for(int r = 0; r < 6; r++) + for(int g = 0; g < 6; g++) + for(int b = 0; b < 6; b++) + Add(pal, 255 * r / 5, 255 * g / 5, 255 * b / 5); + for(int q = 0; q <= 16; q++) + Add(pal, 16 * q, 16 * q, 16 * q); + Add(pal, GetRValue(sLightGray), GetGValue(sLightGray), GetBValue(sLightGray)); + hQlibPalette = CreatePalette(pal); + delete[] pal; + return hQlibPalette; +} +#endif + +SystemDraw& GLOBAL_VP(ScreenDraw, ScreenInfo, (true)) + +HDC ScreenHDC() +{ + static HDC hdc; + ONCELOCK { + hdc = CreateDC("DISPLAY", NULL, NULL, NULL); + } + return hdc; +} + +static bool _AutoPalette = true; +bool SystemDraw::AutoPalette() { return _AutoPalette; } +void SystemDraw::SetAutoPalette(bool ap) { _AutoPalette = ap; } + +COLORREF SystemDraw::GetColor(Color c) const { + COLORREF color = c; +#ifdef PLATFORM_WINCE + return color; +#else + if(!palette) + return color; + static Index *SColor; + ONCELOCK { + static Index StaticColor; + StaticColor << RGB(0x00, 0x00, 0x00) << RGB(0x80, 0x00, 0x00) << RGB(0x00, 0x80, 0x00) + << RGB(0x80, 0x80, 0x00) << RGB(0x00, 0x00, 0x80) << RGB(0x80, 0x00, 0x80) + << RGB(0x00, 0x80, 0x80) << RGB(0xC0, 0xC0, 0xC0) << RGB(0xC0, 0xDC, 0xC0) + << RGB(0xA6, 0xCA, 0xF0) << RGB(0xFF, 0xFB, 0xF0) << RGB(0xA0, 0xA0, 0xA4) + << RGB(0x80, 0x80, 0x80) << RGB(0xFF, 0x00, 0x00) << RGB(0x00, 0xFF, 0x00) + << RGB(0xFF, 0xFF, 0x00) << RGB(0x00, 0x00, 0xFF) << RGB(0xFF, 0x00, 0xFF) + << RGB(0x00, 0xFF, 0xFF) << RGB(0xFF, 0xFF, 0xFF); + SColor = &StaticColor; + } + if(color16 || !AutoPalette()) + return GetNearestColor(handle, color); + if(SColor->Find(color) >= 0) + return color; + if(color == sLightGray) + return PALETTEINDEX(216 + 17); + int r = GetRValue(color); + int g = GetGValue(color); + int b = GetBValue(color); + return PALETTEINDEX(r == g && g == b ? (r + 8) / 16 + 216 + : (r + 25) / 51 * 36 + + (g + 25) / 51 * 6 + + (b + 25) / 51); +#endif +} + +void SystemDraw::InitColors() +{ +} + +void SystemDraw::SetColor(Color color) +{ + GuiLock __; + LLOG("SetColor " << color); + if(color != lastColor) { + LLOG("Setting, lastColor:" << FormatIntHex(lastColor.GetRaw()) + << " color:" << FormatIntHex(color.GetRaw()) << + " GetColor:" << FormatIntHex(GetColor(color)) << " palette:" << palette); + HBRUSH oldBrush = actBrush; + HBRUSH h; + if(!IsNull(color)) + h = (HBRUSH) SelectObject(handle, actBrush = CreateSolidBrush(GetColor(color))); + else { + HGDIOBJ empty = GetStockObject(HOLLOW_BRUSH); + h = (HBRUSH) SelectObject(handle, empty); + actBrush = NULL; + } + ASSERT(h); + if(!orgBrush) orgBrush = h; + if(oldBrush) DeleteObject(oldBrush); + lastColor = color; + } +} + +void SystemDraw::SetDrawPen(int width, Color color) { + GuiLock __; + if(IsNull(width)) + width = PEN_NULL; + if(width != lastPen || color != lastPenColor) { + static int penstyle[] = { + PS_NULL, PS_SOLID, PS_DASH, + #ifndef PLATFORM_WINCE + PS_DOT, PS_DASHDOT, PS_DASHDOTDOT + #endif + }; + HPEN oldPen = actPen; + actPen = CreatePen(width < 0 ? penstyle[-width - 1] : PS_SOLID, + width < 0 ? 0 : width, GetColor(color)); + HPEN h = (HPEN) SelectObject(handle, actPen); + if(!orgPen) orgPen = h; + if(oldPen) DeleteObject(oldPen); + lastPen = width; + lastPenColor = color; + } +} + +void SystemDraw::SetOrg() { + GuiLock __; +#ifdef PLATFORM_WINCE + ::SetViewportOrgEx(handle, actual_offset.x, actual_offset.y, 0); +#else + LLOG("SystemDraw::SetOrg: clip = " << GetClip() << ", offset = " << actual_offset); + ::SetWindowOrgEx(handle, -actual_offset.x, -actual_offset.y, 0); + LLOG("//SystemDraw::SetOrg: clip = " << GetClip()); +#endif +} + +#ifndef PLATFORM_WINCE +Point SystemDraw::LPtoDP(Point p) const { + GuiLock __; + ::LPtoDP(handle, p, 1); + return p; +} + +Point SystemDraw::DPtoLP(Point p) const { + GuiLock __; + ::DPtoLP(handle, p, 1); + return p; +} + +Rect SystemDraw::LPtoDP(const Rect& r) const { + GuiLock __; + Rect w = r; + ::LPtoDP(handle, reinterpret_cast(&w), 2); + return w; +} + +Rect SystemDraw::DPtoLP(const Rect& r) const { + GuiLock __; + Rect w = r; + ::LPtoDP(handle, reinterpret_cast(&w), 2); + return w; +} +#endif + +Size SystemDraw::GetSizeCaps(int i, int j) const { + GuiLock __; + return Size(GetDeviceCaps(handle, i), GetDeviceCaps(handle, j)); +} + +void SystemDraw::DotsMode() +{ + ::SetMapMode(handle, MM_ANISOTROPIC); + ::SetViewportExtEx(handle, nativeDpi.cx, nativeDpi.cy, NULL); + ::SetViewportOrgEx(handle, 0, 0, NULL); + ::SetWindowExtEx(handle, 600, 600, NULL); + ::SetWindowOrgEx(handle, 0, 0, NULL); +} + +void SystemDraw::BeginNative() +{ + if(GetPixelsPerInch() != nativeDpi && ++native == 1) { + ::SetMapMode(handle, MM_TEXT); + actual_offset_bak = actual_offset; + Native(actual_offset); + SetOrg(); + } +} + +void SystemDraw::EndNative() +{ + if(GetPixelsPerInch() == nativeDpi && --native == 0) { + DotsMode(); + actual_offset = actual_offset_bak; + SetOrg(); + } +} + +int SystemDraw::GetCloffLevel() const +{ + return cloff.GetCount(); +} + +void SystemDraw::LoadCaps() { + GuiLock __; + color16 = false; + palette = (GetDeviceCaps(handle, RASTERCAPS) & RC_PALETTE); + if(palette) + color16 = GetDeviceCaps(handle, SIZEPALETTE) != 256; + nativeSize = pageSize = GetSizeCaps(HORZRES, VERTRES); + nativeDpi = GetSizeCaps(LOGPIXELSX, LOGPIXELSY); + is_mono = GetDeviceCaps(handle, BITSPIXEL) == 1 && GetDeviceCaps(handle, PLANES) == 1; +} + +void SystemDraw::Cinit() { + GuiLock __; + lastColor = Color::FromCR(COLORREF(-5)); + lastPenColor = Color::FromCR(COLORREF(-5)); + lastTextColor = COLORREF(-1); + lastPen = Null; + actBrush = orgBrush = NULL; + actPen = orgPen = NULL; +} + +void SystemDraw::Init() { + GuiLock __; + drawingclip = Rect(-(INT_MAX >> 1), -(INT_MAX >> 1), +(INT_MAX >> 1), +(INT_MAX >> 1)); + Cinit(); + SetBkMode(handle, TRANSPARENT); + ::SetTextAlign(handle, TA_BASELINE); +#ifdef PLATFORM_WINCE + actual_offset = Point(0, 0); +#else + ::GetViewportOrgEx(handle, actual_offset); +#endif + LoadCaps(); +} + +void SystemDraw::InitClip(const Rect& clip) +{ + drawingclip = clip; +} + +void SystemDraw::Reset() { + GuiLock __; + style = GUI; +} + +SystemDraw::SystemDraw() { + GuiLock __; + native = 0; + InitColors(); + actual_offset = Point(0, 0); + Reset(); + handle = NULL; +} + +SystemDraw::SystemDraw(HDC hdc) { + GuiLock __; + native = 0; + InitColors(); + Reset(); + Attach(hdc); +} + +void SystemDraw::Unselect0() { + GuiLock __; + if(orgPen) SelectObject(handle, orgPen); + if(orgBrush) SelectObject(handle, orgBrush); + if(actPen) DeleteObject(actPen); + if(actBrush) DeleteObject(actBrush); + Cinit(); +} + +void SystemDraw::Unselect() { + GuiLock __; + while(cloff.GetCount()) + End(); + Unselect0(); +} + +SystemDraw::~SystemDraw() { + GuiLock __; + if(handle) + Unselect(); +} + +HDC SystemDraw::BeginGdi() { + GuiLock __; + Begin(); + return handle; +} + +void SystemDraw::EndGdi() { + GuiLock __; + Unselect0(); + End(); +} + +void BackDraw::Create(SystemDraw& w, int cx, int cy) { + ASSERT(w.GetHandle()); + GuiLock __; + Destroy(); + size.cx = cx; + size.cy = cy; + hbmp = ::CreateCompatibleBitmap(w.GetHandle(), cx, cy); + handle = ::CreateCompatibleDC(w.GetHandle()); + ASSERT(hbmp); + ASSERT(handle); +#ifndef PLATFORM_WINCE + if(AutoPalette()) { + ::SelectPalette(handle, GetQlibPalette(), FALSE); + ::RealizePalette(handle); + } +#endif + hbmpold = (HBITMAP) ::SelectObject(handle, hbmp); + Init(); + InitClip(size); +} + +void BackDraw::Put(SystemDraw& w, int x, int y) { + GuiLock __; + ASSERT(handle); + LTIMING("BackDraw::Put"); +#ifdef PLATFORM_WINCE + ::SetViewportOrgEx(handle, 0, 0, 0); +#else + ::SetWindowOrgEx(handle, 0, 0, NULL); +#endif + ::BitBlt(w, x, y, size.cx, size.cy, *this, 0, 0, SRCCOPY); +} + +void BackDraw::Destroy() { + GuiLock __; + if(handle) { + Unselect(); + ::SelectObject(handle, hbmpold); + ::DeleteDC(handle); + ::DeleteObject(hbmp); + handle = NULL; + } +} + +ScreenDraw::ScreenDraw(bool ic) { + GuiLock __; +#ifdef PLATFORM_WINCE + Attach(CreateDC(NULL, NULL, NULL, NULL)); +#else + Attach(ic ? CreateIC("DISPLAY", NULL, NULL, NULL) : CreateDC("DISPLAY", NULL, NULL, NULL)); + InitClip(GetVirtualScreenArea()); + if(AutoPalette()) { + SelectPalette(handle, GetQlibPalette(), TRUE); + RealizePalette(handle); + } +#endif +} + +ScreenDraw::~ScreenDraw() { + GuiLock __; + Unselect(); + DeleteDC(handle); +} + +#ifndef PLATFORM_WINCE + +void PrintDraw::InitPrinter() +{ + GuiLock __; + Init(); + style = PRINTER|DOTS; + DotsMode(); + native = 0; + actual_offset = Point(0, 0); + aborted = false; + pageSize.cx = 600 * nativeSize.cx / nativeDpi.cx; + pageSize.cy = 600 * nativeSize.cy / nativeDpi.cy; + InitClip(pageSize); +} + +void PrintDraw::StartPage() +{ + GuiLock __; + if(aborted) return; + Unselect(); + if(::StartPage(handle) <= 0) + aborted = true; + else + InitPrinter(); +} + +void PrintDraw::EndPage() +{ + GuiLock __; + if(aborted) return; + Unselect(); + if(::EndPage(handle) <= 0) + aborted = true; +} + +PrintDraw::PrintDraw(HDC hdc, const char *docname) + : SystemDraw(hdc) +{ + GuiLock __; + DOCINFO di; + memset(&di, 0, sizeof(di)); + di.cbSize = sizeof(di); + String sys_docname = ToSystemCharset(docname); + di.lpszDocName = ~sys_docname; + if(::StartDoc(hdc, &di) <= 0) + aborted = true; + else + InitPrinter(); +} + +PrintDraw::~PrintDraw() { + GuiLock __; + if(aborted) + ::AbortDoc(handle); + else + ::EndDoc(handle); + DeleteDC(handle); + handle = NULL; +} +#endif + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/ImageWinAlt.cpp b/rainbow/WinAlt/ImageWinAlt.cpp new file mode 100644 index 000000000..329418d34 --- /dev/null +++ b/rainbow/WinAlt/ImageWinAlt.cpp @@ -0,0 +1,657 @@ +#include + +#ifdef GUI_WINALT + +#include + +NAMESPACE_UPP + +#define LTIMING(x) // RTIMING(x) + +bool ImageFallBack +// = true +; + +struct Image::Data::SystemData { + LPCSTR cursor_cheat; + HBITMAP hbmp; + HBITMAP hmask; + HBITMAP himg; + RGBA *section; +}; + +class BitmapInfo32__ { + Buffer data; + +public: + operator BITMAPINFO *() { return (BITMAPINFO *)~data; } + operator BITMAPINFOHEADER *() { return (BITMAPINFOHEADER *)~data; } + BITMAPINFOHEADER *operator->() { return (BITMAPINFOHEADER *)~data; } + + BitmapInfo32__(int cx, int cy); +}; + +BitmapInfo32__::BitmapInfo32__(int cx, int cy) +{ + data.Alloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); + BITMAPINFOHEADER *hi = (BITMAPINFOHEADER *) ~data;; + memset(hi, 0, sizeof(BITMAPINFOHEADER)); + hi->biSize = sizeof(BITMAPINFOHEADER); + hi->biPlanes = 1; +#ifdef PLATFORM_WINCE + hi->biBitCount = 32; + hi->biCompression = BI_BITFIELDS; + dword *x = (dword *)(~data + sizeof(BITMAPINFOHEADER)); + x[2] = 0xff; + x[1] = 0xff00; + x[0] = 0xff0000; +#else + hi->biBitCount = 32; + hi->biCompression = BI_RGB; +#endif + hi->biSizeImage = 0; + hi->biClrUsed = 0; + hi->biClrImportant = 0; + hi->biWidth = cx; + hi->biHeight = -cy; +} + +HBITMAP CreateBitMask(const RGBA *data, Size sz, Size tsz, Size csz, RGBA *ct) +{ + GuiLock __; + memset(ct, 0, tsz.cx * tsz.cy * sizeof(RGBA)); + int linelen = (tsz.cx + 15) >> 4 << 1; + Buffer mask(tsz.cy * linelen, 0xff); + byte *m = mask; + RGBA *ty = ct; + const RGBA *sy = data; + for(int y = 0; y < csz.cy; y++) { + const RGBA *s = sy; + RGBA *t = ty; + for(int x = 0; x < csz.cx; x++) { + if(s->a > 128) { + *t = *s; + m[x >> 3] &= ~(0x80 >> (x & 7)); + } + else + t->r = t->g = t->b = 0; + t->a = 0; + t++; + s++; + } + m += linelen; + sy += sz.cx; + ty += tsz.cx; + } + return ::CreateBitmap(tsz.cx, tsz.cy, 1, 1, mask); +} + +void SetSurface(HDC dc, const Rect& dest, const RGBA *pixels, Size srcsz, Point srcoff) +{ + GuiLock __; + BitmapInfo32__ bi(srcsz.cx, srcsz.cy); + ::SetDIBitsToDevice(dc, dest.left, dest.top, dest.GetWidth(), dest.GetHeight(), + srcoff.x, -srcoff.y - dest.Height() + srcsz.cy, 0, srcsz.cy, pixels, bi, + DIB_RGB_COLORS); +} + +void SetSurface(HDC dc, int x, int y, int cx, int cy, const RGBA *pixels) +{ + SetSurface(dc, RectC(x, y, cx, cy), pixels, Size(cx, cy), Point(0, 0)); +} + +void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels) +{ + SetSurface(w.GetHandle(), x, y, cx, cy, pixels); +} + +void SetSurface(SystemDraw& w, const Rect& dest, const RGBA *pixels, Size psz, Point poff) +{ + SetSurface(w.GetHandle(), dest, pixels, psz, poff); +} + +class DrawSurface : NoCopy { + int x, y; + Size size; + RGBA *pixels; + HDC dc, dcMem; + HBITMAP hbmp, hbmpOld; + + void Init(SystemDraw& w, int x, int y, int cx, int cy); + RGBA* Line(int i) const { ASSERT(i >= 0 && i < size.cy); return (RGBA *)pixels + size.cx * (size.cy - i - 1); } + +public: + operator RGBA *() { return pixels; } + Size GetSize() const { return size; } + RGBA *operator[](int i) { return Line(i); } + const RGBA *operator[](int i) const { return Line(i); } + int GetLineDelta() const { return -size.cx; } + + DrawSurface(SystemDraw& w, const Rect& r); + DrawSurface(SystemDraw& w, int x, int y, int cx, int cy); + ~DrawSurface(); +}; + +void DrawSurface::Init(SystemDraw& w, int _x, int _y, int cx, int cy) +{ + GuiLock __; + dc = w.GetHandle(); + size = Size(cx, cy); + x = _x; + y = _y; + dcMem = ::CreateCompatibleDC(dc); + BitmapInfo32__ bi(cx, cy); + hbmp = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (void **)&pixels, NULL, 0); + hbmpOld = (HBITMAP) ::SelectObject(dcMem, hbmp); + ::BitBlt(dcMem, 0, 0, cx, cy, dc, x, y, SRCCOPY); +} + +DrawSurface::DrawSurface(SystemDraw& w, const Rect& r) +{ + Init(w, r.left, r.top, r.Width(), r.Height()); +} + +DrawSurface::DrawSurface(SystemDraw& w, int x, int y, int cx, int cy) +{ + Init(w, x, y, cx, cy); +} + +DrawSurface::~DrawSurface() +{ + GuiLock __; + ::BitBlt(dc, x, y, size.cx, size.cy, dcMem, 0, 0, SRCCOPY); + ::DeleteObject(::SelectObject(dcMem, hbmpOld)); + ::DeleteDC(dcMem); +} + +void Image::Data::SysInitImp() +{ + SystemData& sd = Sys(); + sd.hbmp = sd.hmask = sd.himg = NULL; + sd.cursor_cheat = NULL; +} + +void Image::Data::SysReleaseImp() +{ + SystemData& sd = Sys(); + if(sd.hbmp) { + GuiLock __; + DeleteObject(sd.hbmp); + ResCount -= !paintonly; + } + if(sd.hmask) { + GuiLock __; + DeleteObject(sd.hmask); + ResCount -= !paintonly; + } + if(sd.himg) { + GuiLock __; + DeleteObject(sd.himg); + ResCount -= !paintonly; + } + sd.himg = sd.hbmp = sd.hmask = NULL; +} + +#ifndef PLATFORM_WINCE +typedef BOOL (WINAPI *tAlphaBlend)(HDC hdcDest, int nXOriginDest, int nYOriginDest, + int nWidthDest, int nHeightDest, + HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, + int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction); + +static tAlphaBlend fnAlphaBlend() +{ + GuiLock __; + static tAlphaBlend pSet; + static bool inited = false; + if(!inited) { + inited = true; + if(HMODULE hDLL = LoadLibrary("msimg32.dll")) + pSet = (tAlphaBlend) GetProcAddress(hDLL, "AlphaBlend"); + } + return pSet; +} +#endif + +void Image::SetCursorCheat(LPCSTR id) +{ + data->Sys().cursor_cheat = id; +} + +LPCSTR Image::GetCursorCheat() const +{ + return data ? data->Sys().cursor_cheat : NULL; +} + +Image::Data::SystemData& Image::Data::Sys() const +{ + ASSERT(sizeof(system_buffer) >= sizeof(SystemData)); + return *(SystemData *)system_buffer; +} + +int Image::Data::GetResCountImp() const +{ + SystemData& sd = Sys(); + return !!sd.hbmp + !!sd.hmask + !!sd.himg; +} + +void Image::Data::CreateHBMP(HDC dc, const RGBA *data) +{ + GuiLock __; + SystemData& sd = Sys(); + Size sz = buffer.GetSize(); + BitmapInfo32__ bi(sz.cx, sz.cy); + HDC dcMem = ::CreateCompatibleDC(dc); + RGBA *pixels; + HBITMAP hbmp32 = CreateDIBSection(dcMem, bi, DIB_RGB_COLORS, (void **)&pixels, NULL, 0); + HDC hbmpOld = (HDC) ::SelectObject(dcMem, hbmp32); + memcpy(pixels, data, buffer.GetLength() * sizeof(RGBA)); + HDC dcMem2 = ::CreateCompatibleDC(dc); + sd.hbmp = ::CreateCompatibleBitmap(dc, sz.cx, sz.cy); + HBITMAP o2 = (HBITMAP)::SelectObject(dcMem2, sd.hbmp); + ::BitBlt(dcMem2, 0, 0, sz.cx, sz.cy, dcMem, 0, 0, SRCCOPY); + ::SelectObject(dcMem2, o2); + ::DeleteDC(dcMem2); + ::SelectObject(dcMem, hbmpOld); + ::DeleteObject(hbmp32); + ::DeleteDC(dcMem); + ResCount++; +} + +void Image::Data::PaintImp(SystemDraw& w, int x, int y, const Rect& src, Color c) +{ + GuiLock __; + SystemData& sd = Sys(); + ASSERT(!paintonly || IsNull(c)); + int max = IsWinNT() ? 250 : 100; + while(ResCount > max) { + Image::Data *l = ResData->GetPrev(); + l->SysRelease(); + l->Unlink(); + } + HDC dc = w.GetHandle(); + Size sz = buffer.GetSize(); + int len = sz.cx * sz.cy; + Rect sr = src & sz; + Size ssz = sr.Size(); + if(sr.IsEmpty()) + return; + if(GetKind() == IMAGE_EMPTY) + return; + if(GetKind() == IMAGE_OPAQUE && !IsNull(c)) { + w.DrawRect(x, y, sz.cx, sz.cy, c); + return; + } + if(GetKind() == IMAGE_OPAQUE && paintcount == 0 && sr == Rect(sz) && IsWinNT() && w.IsGui()) { + LTIMING("Image Opaque direct set"); + SetSurface(w, x, y, sz.cx, sz.cy, buffer); + paintcount++; + return; + } + Unlink(); + LinkAfter(ResData); + if(GetKind() == IMAGE_OPAQUE) { + if(!sd.hbmp) { + LTIMING("Image Opaque create"); + CreateHBMP(dc, buffer); + } + LTIMING("Image Opaque blit"); + HDC dcMem = ::CreateCompatibleDC(dc); + HBITMAP o = (HBITMAP)::SelectObject(dcMem, sd.hbmp); + ::BitBlt(dc, x, y, ssz.cx, ssz.cy, dcMem, sr.left, sr.top, SRCCOPY); + ::SelectObject(dcMem, o); + ::DeleteDC(dcMem); + PaintOnlyShrink(); + return; + } + if(GetKind() == IMAGE_MASK/* || GetKind() == IMAGE_OPAQUE*/) { + HDC dcMem = ::CreateCompatibleDC(dc); + if(!sd.hmask) { + LTIMING("Image Mask create"); + Buffer bmp(len); + sd.hmask = CreateBitMask(buffer, sz, sz, sz, bmp); + ResCount++; + if(!sd.hbmp) + CreateHBMP(dc, bmp); + } + LTIMING("Image Mask blt"); + HBITMAP o = (HBITMAP)::SelectObject(dcMem, ::CreateCompatibleBitmap(dc, sz.cx, sz.cy)); + ::BitBlt(dcMem, 0, 0, ssz.cx, ssz.cy, dc, x, y, SRCCOPY); + HDC dcMem2 = ::CreateCompatibleDC(dc); + ::SelectObject(dcMem2, sd.hmask); + ::BitBlt(dcMem, 0, 0, ssz.cx, ssz.cy, dcMem2, sr.left, sr.top, SRCAND); + if(IsNull(c)) { + ::SelectObject(dcMem2, sd.hbmp); + ::BitBlt(dcMem, 0, 0, ssz.cx, ssz.cy, dcMem2, sr.left, sr.top, SRCPAINT); + } + else { + HBRUSH ho = (HBRUSH) SelectObject(dcMem, CreateSolidBrush(c)); + ::BitBlt(dcMem, 0, 0, ssz.cx, ssz.cy, dcMem2, sr.left, sr.top, 0xba0b09); + ::DeleteObject(::SelectObject(dcMem, ho)); + } + ::BitBlt(dc, x, y, ssz.cx, ssz.cy, dcMem, 0, 0, SRCCOPY); + ::DeleteObject(::SelectObject(dcMem, o)); + ::DeleteDC(dcMem2); + ::DeleteDC(dcMem); + PaintOnlyShrink(); + return; + } +#ifndef PLATFORM_WINCE + if(fnAlphaBlend() && IsNull(c) && !ImageFallBack) { + if(!sd.himg) { + LTIMING("Image Alpha create"); + BitmapInfo32__ bi(sz.cx, sz.cy); + sd.himg = CreateDIBSection(ScreenHDC(), bi, DIB_RGB_COLORS, (void **)&sd.section, NULL, 0); + ResCount++; + memcpy(sd.section, ~buffer, buffer.GetLength() * sizeof(RGBA)); + } + LTIMING("Image Alpha blit"); + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = AC_SRC_ALPHA; + HDC dcMem = ::CreateCompatibleDC(dc); + ::SelectObject(dcMem, sd.himg); + fnAlphaBlend()(dc, x, y, ssz.cx, ssz.cy, dcMem, sr.left, sr.top, ssz.cx, ssz.cy, bf); + ::DeleteDC(dcMem); + PaintOnlyShrink(); + } + else +#endif + { + LTIMING("Image Alpha sw"); + DrawSurface sf(w, x, y, ssz.cx, ssz.cy); + RGBA *t = sf; + for(int i = sr.top; i < sr.bottom; i++) { + if(IsNull(c)) + AlphaBlendOpaque(t, buffer[i] + sr.left, ssz.cx); + else + AlphaBlendOpaque(t, buffer[i] + sr.left, ssz.cx, c); + t += ssz.cx; + } + } +} + +void ImageDraw::Section::Init(int cx, int cy) +{ + GuiLock __; + dc = ::CreateCompatibleDC(ScreenHDC()); + BitmapInfo32__ bi(cx, cy); + hbmp = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (void **)&pixels, NULL, 0); + hbmpOld = (HBITMAP) ::SelectObject(dc, hbmp); +} + +ImageDraw::Section::~Section() +{ + GuiLock __; + ::DeleteObject(::SelectObject(dc, hbmpOld)); + ::DeleteDC(dc); +} + +void ImageDraw::Init() +{ + GuiLock __; + rgb.Init(size.cx, size.cy); + a.Init(size.cx, size.cy); + Attach(rgb.dc); + InitClip(size); + alpha.Attach(a.dc); + alpha.InitClip(size); + has_alpha = false; +} + +Image ImageDraw::Get(bool pm) const +{ + ImageBuffer b(size); + int n = size.cx * size.cy; + memcpy(~b, rgb.pixels, n * sizeof(RGBA)); + const RGBA *s = a.pixels; + const RGBA *e = a.pixels + n; + RGBA *t = b; + if(has_alpha) { + while(s < e) { + t->a = s->r; + t++; + s++; + } + if(pm) + Premultiply(b); + b.SetKind(IMAGE_ALPHA); + } + else { + while(s < e) { + t->a = 255; + t++; + s++; + } + b.SetKind(IMAGE_OPAQUE); + } + return b; +} + +ImageDraw::operator Image() const +{ + return Get(true); +} + +Image ImageDraw::GetStraight() const +{ + return Get(false); +} + +ImageDraw::ImageDraw(Size sz) +{ + size = sz; + Init(); +} + +ImageDraw::ImageDraw(int cx, int cy) +{ + size = Size(cx, cy); + Init(); +} + +ImageDraw::~ImageDraw() +{ + Detach(); + alpha.Detach(); +} + +#ifdef PLATFORM_WINCE + +Image Image::Arrow() { return Null; } +Image Image::Wait() { return Null; } +Image Image::IBeam() { return Null; } +Image Image::No() { return Null; } +Image Image::SizeAll() { return Null; } +Image Image::SizeHorz() { return Null; } +Image Image::SizeVert() { return Null; } +Image Image::SizeTopLeft() { return Null; } +Image Image::SizeTop() { return Null; } +Image Image::SizeTopRight() { return Null; } +Image Image::SizeLeft() { return Null; } +Image Image::SizeRight() { return Null; } +Image Image::SizeBottomLeft() { return Null; } +Image Image::SizeBottom() { return Null; } +Image Image::SizeBottomRight() { return Null; } + +#else + +static Image sWin32Icon(HICON icon, bool cursor) +{ + GuiLock __; + ICONINFO iconinfo; + if(!icon || !GetIconInfo(icon, &iconinfo)) + return Image(); + BITMAP bm; + ::GetObject((HGDIOBJ)iconinfo.hbmMask, sizeof(BITMAP), (LPVOID)&bm); + HDC dcMem = ::CreateCompatibleDC(NULL); + Size sz(bm.bmWidth, bm.bmHeight); + BitmapInfo32__ bi(sz.cx, sz.cy); + int len = sz.cx * sz.cy; + Buffer mask(len); + ::SelectObject(dcMem, iconinfo.hbmColor); + ::GetDIBits(dcMem, iconinfo.hbmMask, 0, sz.cy, ~mask, bi, DIB_RGB_COLORS); + ImageBuffer b(sz.cx, iconinfo.hbmColor ? sz.cy : sz.cy / 2); + b.SetHotSpot(Point(iconinfo.xHotspot, iconinfo.yHotspot)); + if(iconinfo.hbmColor) { + ::SelectObject(dcMem, iconinfo.hbmColor); + ::GetDIBits(dcMem, iconinfo.hbmColor, 0, sz.cy, ~b, bi, DIB_RGB_COLORS); + RGBA *s = ~b; + RGBA *e = s + len; + RGBA *m = mask; + while(s < e) { + if(s->a != 255 && s->a != 0) { + Premultiply(b); + goto alpha; + } + s++; + } + s = ~b; + while(s < e) { + s->a = m->r ? 0 : 255; + s++; + m++; + } + } + else { + len /= 2; + RGBA *s = ~b; + RGBA *e = s + len; + RGBA *c = mask + len; + RGBA *m = mask; + while(s < e) { + s->a = (m->r & ~c->r) ? 0 : 255; + s->r = s->g = s->b = (c->r & ~m->r) ? 255 : 0; + s++; + m++; + c++; + } + } +alpha: + ::DeleteDC(dcMem); + ::DeleteObject(iconinfo.hbmColor); + ::DeleteObject(iconinfo.hbmMask); + Image img(b); + ::DestroyIcon(icon); + return img; +} + +Image Win32IconCursor(LPCSTR id, int iconsize, bool cursor) +{ + HICON icon; + if(cursor) + icon = (HICON)LoadCursor(0, id); + else + if(iconsize) + icon = (HICON)LoadImage(GetModuleHandle(NULL), id, + IMAGE_ICON, iconsize, iconsize, LR_DEFAULTCOLOR); + else + icon = LoadIcon(0, id); + Image img = sWin32Icon(icon, cursor); + if(cursor) + img.SetCursorCheat(id); + return img; +} + +Image Win32DllIcon(const char *dll, int ii, bool large) +{ + HICON icon; + if(ExtractIconEx(dll, ii, large ? &icon : NULL, large ? NULL : &icon, 1) == 1) + return sWin32Icon(icon, false); + return Null; +} + +Image Win32Icon(LPCSTR id, int iconsize) +{ + return Win32IconCursor(id, iconsize, false); +} + +Image Win32Icon(int id, int iconsize) +{ + return Win32Icon(MAKEINTRESOURCE(id), iconsize); +} + +Image Win32Cursor(LPCSTR id) +{ + return Win32IconCursor(id, 0, true); +} + +Image Win32Cursor(int id) +{ + return Win32Cursor(MAKEINTRESOURCE(id)); +} + +HICON IconWin32(const Image& img, bool cursor) +{ + GuiLock __; + if(img.IsEmpty()) + return NULL; + if(cursor) { + LPCSTR id = img.GetCursorCheat(); + if(id) + return (HICON)LoadCursor(0, id); + } + Size sz = img.GetSize(); + ICONINFO iconinfo; + iconinfo.fIcon = !cursor; + Point p = img.GetHotSpot(); + iconinfo.xHotspot = p.x; + iconinfo.yHotspot = p.y; + static Size cursor_size(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); + Size tsz = sz; + if(!IsWin2K() && cursor) + tsz = cursor_size; + Size csz = Size(min(tsz.cx, sz.cx), min(tsz.cy, sz.cy)); + if(IsWinXP() && !ImageFallBack) { + RGBA *pixels; + BitmapInfo32__ bi(tsz.cx, tsz.cy); + HDC dcMem = ::CreateCompatibleDC(NULL); + iconinfo.hbmColor = ::CreateDIBSection(dcMem, bi, DIB_RGB_COLORS, (void **)&pixels, NULL, 0); + iconinfo.hbmMask = ::CreateBitmap(tsz.cx, tsz.cy, 1, 1, NULL); + memset(pixels, 0, tsz.cx * tsz.cy * sizeof(RGBA)); + for(int y = 0; y < csz.cy; y++) + memcpy(pixels + y * tsz.cx, img[y], csz.cx * sizeof(RGBA)); + ::DeleteDC(dcMem); + } + else { + Buffer h(tsz.cx * tsz.cy); + HDC dc = ::GetDC(NULL); + BitmapInfo32__ bi(tsz.cx, tsz.cy); + iconinfo.hbmMask = CreateBitMask(~img, sz, tsz, csz, h); + iconinfo.hbmColor = ::CreateDIBitmap(dc, bi, CBM_INIT, h, bi, DIB_RGB_COLORS); + ::ReleaseDC(NULL, dc); + } + + HICON icon = ::CreateIconIndirect(&iconinfo); + ::DeleteObject(iconinfo.hbmColor); + ::DeleteObject(iconinfo.hbmMask); + return icon; +} + +#define WCURSOR_(x)\ +{ Image m; INTERLOCKED { static Image img = Win32Cursor(x); m = img; } return m; } + +Image Image::Arrow() WCURSOR_(IDC_ARROW) +Image Image::Wait() WCURSOR_(IDC_WAIT) +Image Image::IBeam() WCURSOR_(IDC_IBEAM) +Image Image::No() WCURSOR_(IDC_NO) +Image Image::SizeAll() WCURSOR_(IDC_SIZEALL) +Image Image::SizeHorz() WCURSOR_(IDC_SIZEWE) +Image Image::SizeVert() WCURSOR_(IDC_SIZENS) +Image Image::SizeTopLeft() WCURSOR_(IDC_SIZENWSE) +Image Image::SizeTop() WCURSOR_(IDC_SIZENS) +Image Image::SizeTopRight() WCURSOR_(IDC_SIZENESW) +Image Image::SizeLeft() WCURSOR_(IDC_SIZEWE) +Image Image::SizeRight() WCURSOR_(IDC_SIZEWE) +Image Image::SizeBottomLeft() WCURSOR_(IDC_SIZENESW) +Image Image::SizeBottom() WCURSOR_(IDC_SIZENS) +Image Image::SizeBottomRight() WCURSOR_(IDC_SIZENWSE) +Image Image::Cross() WCURSOR_(IDC_CROSS) +Image Image::Hand() WCURSOR_(IDC_HAND) + +#endif + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/TopWinAlt.cpp b/rainbow/WinAlt/TopWinAlt.cpp new file mode 100644 index 000000000..bcbe27ff7 --- /dev/null +++ b/rainbow/WinAlt/TopWinAlt.cpp @@ -0,0 +1,398 @@ +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) + +#if defined(COMPILER_MINGW) && !defined(FLASHW_ALL) + // MINGW headers don't include this in (some versions of) windows + extern "C"{ + struct FLASHWINFO { + UINT cbSize; + HWND hwnd; + DWORD dwFlags; + UINT uCount; + DWORD dwTimeout; + }; + WINUSERAPI BOOL WINAPI FlashWindowEx(FLASHWINFO*); + } + #define FLASHW_STOP 0 + #define FLASHW_CAPTION 0x00000001 + #define FLASHW_TRAY 0x00000002 + #define FLASHW_ALL (FLASHW_CAPTION | FLASHW_TRAY) + #define FLASHW_TIMER 0x00000004 + #define FLASHW_TIMERNOFG 0x0000000C +#endif + +void TopWindow::SyncSizeHints() {} + +LRESULT TopWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + GuiLock __; + HWND hwnd = GetHWND(); +#ifndef PLATFORM_WINCE + bool inloop; +#endif + switch(message) { +#ifndef PLATFORM_WINCE + case WM_QUERYENDSESSION: + inloop = InLoop(); + WhenClose(); + return inloop ? !InLoop() : !IsOpen(); + case WM_ENDSESSION: + EndSession() = true; + PostQuitMessage(0); + return 0; +#endif + case WM_CLOSE: + if(IsEnabled()) { + IgnoreMouseUp(); + WhenClose(); + } + return 0; + case WM_WINDOWPOSCHANGED: +#ifndef PLATFORM_WINCE + if(IsIconic(hwnd)) + state = MINIMIZED; + else + if(IsZoomed(hwnd)) + state = MAXIMIZED; + else +#endif + { + state = OVERLAPPED; + overlapped = GetScreenClient(hwnd); + } + Layout(); + break; + } + return Ctrl::WindowProc(message, wParam, lParam); +} + +void TopWindow::SyncTitle0() +{ + GuiLock __; + HWND hwnd = GetHWND(); +#ifndef PLATFORM_WINCE + if(hwnd) + if(IsWindowUnicode(hwnd)) + ::SetWindowTextW(hwnd, (const WCHAR*)~title); + else +#endif + ::SetWindowText(hwnd, ToSystemCharset(title.ToString())); +} + +void TopWindow::DeleteIco0() +{ + GuiLock __; + if(ico) + DestroyIcon(ico); + if(lico) + DestroyIcon(lico); + ico = lico = NULL; +} + +void TopWindow::DeleteIco() +{ + ICall(THISBACK(DeleteIco0)); +} + +void TopWindow::SyncCaption0() +{ + GuiLock __; + LLOG("SyncCaption"); + if(fullscreen) + return; + HWND hwnd = GetHWND(); + if(hwnd) { + style = ::GetWindowLong(hwnd, GWL_STYLE); + exstyle = ::GetWindowLong(hwnd, GWL_EXSTYLE); + } + style &= ~(WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU|WS_POPUP|WS_DLGFRAME); + exstyle &= ~(WS_EX_TOOLWINDOW|WS_EX_DLGMODALFRAME); + style |= WS_CAPTION; + if(hasdhctrl) + style |= WS_CLIPSIBLINGS|WS_CLIPCHILDREN; + if(minimizebox) + style |= WS_MINIMIZEBOX; + if(maximizebox) + style |= WS_MAXIMIZEBOX; + if(sizeable) + style |= WS_THICKFRAME; +#ifndef PLATFORM_WINCE + if(frameless) + style = (style & ~WS_CAPTION) | WS_POPUP; + else + if(IsNull(icon) && !maximizebox && !minimizebox || noclosebox) { + style |= WS_POPUPWINDOW|WS_DLGFRAME; + exstyle |= WS_EX_DLGMODALFRAME; + if(noclosebox) + style &= ~WS_SYSMENU; + } + else +#endif + style |= WS_SYSMENU; + if(tool) + exstyle |= WS_EX_TOOLWINDOW; + if(fullscreen) + style = WS_POPUP; + if(hwnd) { + ::SetWindowLong(hwnd, GWL_STYLE, style); + ::SetWindowLong(hwnd, GWL_EXSTYLE, exstyle); + SyncTitle(); + if(urgent) { + if(IsForeground()) urgent = false; + FLASHWINFO fi; + memset(&fi, 0, sizeof(fi)); + fi.cbSize = sizeof(fi); + fi.hwnd = hwnd; + fi.dwFlags = urgent ? FLASHW_TIMER|FLASHW_ALL : FLASHW_STOP; + FlashWindowEx(&fi); + } + } + DeleteIco(); +#ifndef PLATFORM_WINCE //TODO!!! + if(hwnd) { + ::SendMessage(hwnd, WM_SETICON, false, (LPARAM)(ico = IconWin32(icon))); + ::SendMessage(hwnd, WM_SETICON, true, (LPARAM)(lico = IconWin32(largeicon))); + } +#endif +} + +void TopWindow::CenterRect(HWND hwnd, int center) +{ + GuiLock __; + SetupRect(); + if(hwnd && center == 1 || center == 2) { + Size sz = GetRect().Size(); + Rect frmrc(sz); + #ifndef PLATFORM_WINCE + ::AdjustWindowRect(frmrc, WS_OVERLAPPEDWINDOW, FALSE); + #endif + Rect r, wr; + wr = Ctrl::GetWorkArea().Deflated(-frmrc.left, -frmrc.top, + frmrc.right - sz.cx, frmrc.bottom - sz.cy); + sz.cx = min(sz.cx, wr.Width()); + sz.cy = min(sz.cy, wr.Height()); + if(center == 1) { + ::GetClientRect(hwnd, r); + if(r.IsEmpty()) + r = wr; + else { + Point p = r.TopLeft(); + ::ClientToScreen(hwnd, p); + r.Offset(p); + } + } + else + r = wr; + Point p = r.CenterPos(sz); + if(p.x + sz.cx > wr.right) p.x = wr.right - sz.cx; + if(p.y + sz.cy > wr.bottom) p.y = wr.bottom - sz.cy; + if(p.x < wr.left) p.x = wr.left; + if(p.y < wr.top) p.y = wr.top; + SetRect(p.x, p.y, sz.cx, sz.cy); + } +} + +static HWND trayHWND__; +HWND GetTrayHWND__() { return trayHWND__; } +void SetTrayHWND__(HWND hwnd) { trayHWND__ = hwnd; } + +void TopWindow::Open(HWND hwnd) +{ + GuiLock __; + if(dokeys && (!GUI_AKD_Conservative() || GetAccessKeysDeep() <= 1)) + DistributeAccessKeys(); + UsrLogT(3, "OPEN " + Desc(this)); + LLOG("TopWindow::Open, owner HWND = " << FormatIntHex((int)hwnd, 8) << ", Active = " << FormatIntHex((int)::GetActiveWindow(), 8)); + IgnoreMouseUp(); + SyncCaption(); +#ifdef PLATFORM_WINCE + if(!GetRect().IsEmpty()) +#endif + if(fullscreen) { + SetRect(GetScreenSize()); + Create(hwnd, WS_POPUP, 0, false, SW_SHOWMAXIMIZED, false); + } + else { + CenterRect(hwnd, hwnd && hwnd == GetTrayHWND__() ? center ? 2 : 0 : center); + Create(hwnd, style, exstyle, false, state == OVERLAPPED ? SW_SHOWNORMAL : + state == MINIMIZED ? SW_MINIMIZE : + SW_MAXIMIZE, false); + } + PlaceFocus(); + SyncCaption(); + FixIcons(); +} + +void TopWindow::Open(Ctrl *owner) +{ + GuiLock __; + LLOG("TopWindow::Open(Ctrl) -> " << UPP::Name(owner)); + Open(owner ? owner->GetTopCtrl()->GetHWND() : NULL); + if(IsOpen() && top) + top->owner = owner; +} + +void TopWindow::Open() +{ + Open(::GetActiveWindow()); // :: needed because of ActiveX controls (to create modal dlgs owned by a HWND) +} + +void TopWindow::OpenMain() +{ + Open((HWND) NULL); +} + +void TopWindow::Minimize(bool effect) +{ + state = MINIMIZED; + if(IsOpen()) +#ifdef PLATFORM_WINCE + ::ShowWindow(GetHWND(), SW_MINIMIZE); +#else + ::ShowWindow(GetHWND(), effect ? SW_MINIMIZE : SW_SHOWMINIMIZED); +#endif +} + +TopWindow& TopWindow::FullScreen(bool b) +{ + fullscreen = b; + HWND hwnd = GetOwnerHWND(); + bool pinloop = inloop; + WndDestroy(); + Overlap(); + SetRect(GetDefaultWindowRect()); + Open(hwnd); + inloop = pinloop; + return *this; +} + +void TopWindow::Maximize(bool effect) +{ + state = MAXIMIZED; + if(IsOpen()) { + ::ShowWindow(GetHWND(), effect ? SW_MAXIMIZE : SW_SHOWMAXIMIZED); + SyncCaption(); + } +} + +void TopWindow::Overlap(bool effect) +{ + GuiLock __; + state = OVERLAPPED; + if(IsOpen()) { + ::ShowWindow(GetHWND(), effect ? SW_SHOWNORMAL : SW_RESTORE); + SyncCaption(); + } +} + +TopWindow& TopWindow::Style(dword _style) +{ + GuiLock __; + style = _style; + if(GetHWND()) + ::SetWindowLong(GetHWND(), GWL_STYLE, style); + SyncCaption(); + return *this; +} + +TopWindow& TopWindow::ExStyle(dword _exstyle) +{ + GuiLock __; + exstyle = _exstyle; + if(GetHWND()) + ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exstyle); + SyncCaption(); + return *this; +} + +TopWindow& TopWindow::TopMost(bool b, bool stay_top) +{ + GuiLock __; + HWND hwnd; + if(hwnd = GetHWND()) + SetWindowPos(hwnd, b ? HWND_TOPMOST : (stay_top ? HWND_NOTOPMOST : HWND_BOTTOM), + 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE ); + return ExStyle(b ? GetExStyle() | WS_EX_TOPMOST : GetExStyle() & ~WS_EX_TOPMOST); +} + +bool TopWindow::IsTopMost() const +{ + return GetExStyle() & WS_EX_TOPMOST; +} + +void TopWindow::GuiPlatformConstruct() +{ + style = 0; + exstyle = 0; + ico = lico = NULL; +} + +void TopWindow::GuiPlatformDestruct() +{ + DeleteIco(); +} + +void TopWindow::SerializePlacement(Stream& s, bool reminimize) +{ + GuiLock __; +#ifndef PLATFORM_WINCE + int version = 0; + s / version; + Rect rect = GetRect(); + s % overlapped % rect; + bool mn = state == MINIMIZED; + bool mx = state == MAXIMIZED; + s.Pack(mn, mx); + LLOG("TopWindow::SerializePlacement / " << (s.IsStoring() ? "write" : "read")); + LLOG("minimized = " << mn << ", maximized = " << mx); + LLOG("rect = " << rect << ", overlapped = " << overlapped); + if(s.IsLoading()) { + if(mn) rect = overlapped; + Rect limit = GetWorkArea(); + Rect outer = rect; + ::AdjustWindowRect(outer, WS_OVERLAPPEDWINDOW, FALSE); + limit.left += rect.left - outer.left; + limit.top += rect.top - outer.top; + limit.right += rect.right - outer.right; + limit.bottom += rect.bottom - outer.bottom; + Size sz = min(rect.Size(), limit.Size()); + rect = RectC( + minmax(rect.left, limit.left, limit.right - sz.cx), + minmax(rect.top, limit.top, limit.bottom - sz.cy), + sz.cx, sz.cy); + state = OVERLAPPED; + if(mn && reminimize) + state = MINIMIZED; + if(mx) + state = MAXIMIZED; + if(state == OVERLAPPED) + SetRect(rect); + if(IsOpen()) { + HWND hwnd = GetHWND(); + switch(state) { + case MINIMIZED: + if(!IsIconic(hwnd)) + ::ShowWindow(hwnd, SW_MINIMIZE); + break; + case MAXIMIZED: + if(!IsZoomed(hwnd)) + ::ShowWindow(hwnd, SW_MAXIMIZE); + break; + default: + if(IsIconic(hwnd) || IsZoomed(hwnd)) + ::ShowWindow(hwnd, SW_RESTORE); + break; + } + } + } +#endif +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/UtilWinAlt.cpp b/rainbow/WinAlt/UtilWinAlt.cpp new file mode 100644 index 000000000..c0466fb91 --- /dev/null +++ b/rainbow/WinAlt/UtilWinAlt.cpp @@ -0,0 +1,75 @@ +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +SystemDraw& ScreenInfo(); + +bool ScreenInPaletteMode() +{ + return ScreenInfo().PaletteMode(); +} + +Size GetScreenSize() +{ + return ScreenInfo().GetPageSize(); +} + +HRGN GetFrameRgn(const Rect& rect, int n) { + HRGN rgn = CreateRectRgnIndirect(rect); + Rect r = rect; + r.Deflate(n); + if(r.Width() > 0 && r.Height() > 0) { + HRGN rgnin = CreateRectRgnIndirect(r); + CombineRgn(rgn, rgn, rgnin, RGN_XOR); + DeleteObject(rgnin); + } + return rgn; +} + +void DrawDragRect(SystemDraw& w, const Rect& _rect1, const Rect& _rect2, const Rect& _clip, int n, Color color, uint64 pattern) +{ + Point o = w.GetOffset(); + Rect rect1 = _rect1 + o; + Rect rect2 = _rect2 + o; + Rect clip = _clip + o; + HDC hdc = w.BeginGdi(); + word wpat[8] = { + (byte)(pattern >> 56), (byte)(pattern >> 48), (byte)(pattern >> 40), (byte)(pattern >> 32), + (byte)(pattern >> 24), (byte)(pattern >> 16), (byte)(pattern >> 8), (byte)(pattern >> 0), + }; + HBITMAP bitmap = CreateBitmap(8, 8, 1, 1, wpat); + HBRUSH brush = ::CreatePatternBrush(bitmap); + DeleteObject(bitmap); + SetTextColor(hdc, color); + SetBkColor(hdc, SColorText()); + Point offset; +#ifdef PLATFORM_WINCE + offset = Point(0, 0); +#else + ::GetViewportOrgEx(hdc, offset); +#endif + HRGN rgn = GetFrameRgn(rect1 + offset, n); + HRGN rgn2 = GetFrameRgn(rect2 + offset, n); + HRGN cliprgn = CreateRectRgnIndirect(clip + offset); + CombineRgn(rgn, rgn, rgn2, RGN_XOR); + CombineRgn(rgn, rgn, cliprgn, RGN_AND); + SelectClipRgn(hdc, rgn); + Rect r; + GetClipBox(hdc, r); + HBRUSH obrush = (HBRUSH) SelectObject(hdc, brush); + PatBlt(hdc, r.left, r.top, r.Width(), r.Height(), PATINVERT); + SelectObject(hdc, obrush); + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + DeleteObject(rgn2); + DeleteObject(cliprgn); + ReleaseDC(NULL, hdc); + DeleteObject(brush); + w.EndGdi(); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/WinAlt.h b/rainbow/WinAlt/WinAlt.h new file mode 100644 index 000000000..671bf13ad --- /dev/null +++ b/rainbow/WinAlt/WinAlt.h @@ -0,0 +1,385 @@ +#define GUI_WINALT + +NAMESPACE_UPP + +class SystemDraw : public Draw { +public: + virtual dword GetInfo() const; + virtual Size GetPageSize() const; + + virtual void BeginOp(); + virtual void EndOp(); + virtual void OffsetOp(Point p); + virtual bool ClipOp(const Rect& r); + virtual bool ClipoffOp(const Rect& r); + virtual bool ExcludeClipOp(const Rect& r); + virtual bool IntersectClipOp(const Rect& r); + virtual bool IsPaintingOp(const Rect& r) const; + virtual Rect GetPaintRect() const; + + virtual void DrawRectOp(int x, int y, int cx, int cy, Color color); + virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color); + virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color); + + virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, + const int *counts, int count_count, + int width, Color color, Color doxor); + virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int scc, + const int *disjunct_polygon_counts, int dpcc, + Color color, int width, Color outline, + uint64 pattern, Color doxor); + virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color); + + virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); + virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, + Color ink, int n, const int *dx); + + virtual Size GetNativeDpi() const; + virtual void BeginNative(); + virtual void EndNative(); + + virtual int GetCloffLevel() const; + +private: + Size pageSize; + Size nativeSize; + Size nativeDpi; + bool palette:1; + bool color16:1; + bool is_mono:1; + int native; + + friend class ImageDraw; + friend class FontInfo; + friend class Font; + + friend void StaticExitDraw_(); + + Point actual_offset_bak; + + struct Cloff : Moveable { + Point org; + HRGN hrgn; + Rect drawingclip; + }; + + Array cloff; + Rect drawingclip; + + COLORREF lastTextColor; + Color lastColor; + HBRUSH orgBrush; + HBRUSH actBrush; + HPEN orgPen; + HPEN actPen; + int lastPen; + Color lastPenColor; + + void Unselect0(); + void Cinit(); + + void LoadCaps(); + void SetPrinterMode(); + void Reset(); + void SetOrg(); + friend HPALETTE GetQlibPalette(); + void DotsMode(); + + static void InitColors(); + + friend class BackDraw; + friend class ScreenDraw; + friend class PrintDraw; + +protected: + dword style; + HDC handle; + Point actual_offset; + + SystemDraw(); + void Init(); + void InitClip(const Rect& clip); + +public: + static Rect GetVirtualScreenArea(); + + static void SetAutoPalette(bool ap); + static bool AutoPalette(); + bool PaletteMode() { return palette; } + + static void Flush() { GdiFlush(); } + + COLORREF GetColor(Color color) const; + + Point GetOffset() const { return actual_offset; } + +#ifndef PLATFORM_WINCE + Point LPtoDP(Point p) const; + Point DPtoLP(Point p) const; + Rect LPtoDP(const Rect& r) const; + Rect DPtoLP(const Rect& r) const; +#endif + + void SetColor(Color color); + void SetDrawPen(int width, Color color); + + Size GetSizeCaps(int i, int j) const; + HDC BeginGdi(); + void EndGdi(); + HDC GetHandle() { return handle; } + operator HDC() const { return handle; } + void Unselect(); + void Attach(HDC ahandle) { handle = ahandle; Init(); } + HDC Detach() { Unselect(); HDC h = handle; handle = NULL; return h; } + + SystemDraw(HDC hdc); + virtual ~SystemDraw(); + + bool CanSetSurface() { return IsGui() && IsWinNT(); } +}; + +#ifndef PLATFORM_WINCE +class WinMetaFile { + Size size; + HENHMETAFILE hemf; + + void Init(); + +public: + void Attach(HENHMETAFILE emf); + HENHMETAFILE Detach(); + + void Set(const void *data, dword len); + void Set(const String& data) { Set(~data, data.GetCount()); } + + String Get() const; + + operator bool() const { return hemf; } + void SetSize(const Size& sz) { size = sz; } + Size GetSize() const { return hemf ? size : Size(0, 0); } + + void Clear(); + + void Paint(Draw& w, const Rect& r) const; + void Paint(Draw& w, int x, int y, int cx, int cy) const; + + void Serialize(Stream& s); + + void ReadClipboard(); + void WriteClipboard() const; + void Load(const char *file) { Set(LoadFile(file)); } + + WinMetaFile() { Init(); } + WinMetaFile(HENHMETAFILE hemf); + WinMetaFile(HENHMETAFILE hemf, Size sz); + WinMetaFile(const char *file); + WinMetaFile(void *data, int len); + WinMetaFile(const String& data); + + ~WinMetaFile() { Clear(); } + + HENHMETAFILE GetHEMF() const { return hemf; } +}; + +class WinMetaFileDraw : public SystemDraw { + Size size; + +public: + bool Create(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + bool Create(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + WinMetaFile Close(); + + WinMetaFileDraw() {} + WinMetaFileDraw(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + WinMetaFileDraw(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + ~WinMetaFileDraw(); +}; + +void DrawWMF(Draw& w, int x, int y, int cx, int cy, const String& wmf); +void DrawWMF(Draw& w, int x, int y, const String& wmf); +Drawing LoadWMF(const char *path, int cx, int cy); +Drawing LoadWMF(const char *path); + +String AsWMF(const Drawing& iw); + +#endif + +class ScreenDraw : public SystemDraw { +public: + ScreenDraw(bool ic = false); + ~ScreenDraw(); +}; + +#ifndef PLATFORM_WINCE +class PrintDraw : public SystemDraw { +public: + virtual void StartPage(); + virtual void EndPage(); + +private: + bool aborted; + + void InitPrinter(); +public: + PrintDraw(HDC hdc, const char *jobname); + ~PrintDraw(); +}; +#endif + +inline bool BitBlt(HDC ddc, Point d, HDC sdc, const Rect& s, dword rop = SRCCOPY) +{ return BitBlt(ddc, d.x, d.y, s.Width(), s.Height(), sdc, s.left, s.top, rop); } + +inline bool StretchBlt(HDC ddc, const Rect& r, HDC sdc, const Rect& s, dword rop = SRCCOPY) +{ return StretchBlt(ddc, r.left, r.top, r.Width(), r.Height(), sdc, s.left, s.top, s.Width(), s.Height(), rop); } + +inline bool PatBlt(HDC dc, const Rect& r, dword rop = PATCOPY) +{ return PatBlt(dc, r.left, r.top, r.Width(), r.Height(), rop); } + +inline void MoveTo(HDC hdc, Point pt) { MoveToEx(hdc, pt.x, pt.y, 0); } +inline void LineTo(HDC hdc, Point pt) { LineTo(hdc, pt.x, pt.y); } + +inline void DrawLine(HDC hdc, Point p, Point q) { MoveTo(hdc, p); LineTo(hdc, q); } +inline void DrawLine(HDC hdc, int px, int py, int qx, int qy) { MoveToEx(hdc, px, py, 0); LineTo(hdc, qx, qy); } + +#ifndef PLATFORM_WINCE +inline void DrawArc(HDC hdc, const Rect& rc, Point p, Point q){ Arc(hdc, rc.left, rc.top, rc.right, rc.bottom, p.x, p.y, q.x, q.y); } +#endif +inline void DrawCircle(HDC hdc, int x, int y, int radius) { Ellipse(hdc, x - radius, y - radius, x + radius + 1, y + radius + 1); } +inline void DrawCircle(HDC hdc, Point centre, int radius) { DrawCircle(hdc, centre.x, centre.y, radius); } +inline void DrawEllipse(HDC hdc, const Rect& rc) { Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); } + +inline void DrawRect(HDC hdc, const Rect& rc) { Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); } + +HDC ScreenHDC(); +HPALETTE GetQlibPalette(); + +Image Win32Icon(LPCSTR id, int iconsize = 0); +Image Win32Icon(int id, int iconsize = 0); +Image Win32Cursor(LPCSTR id); +Image Win32Cursor(int id); +HICON IconWin32(const Image& img, bool cursor = false); +Image Win32DllIcon(const char *dll, int ii, bool large); + +class BackDraw : public SystemDraw { +public: + virtual bool IsPaintingOp(const Rect& r) const; + +protected: + HBITMAP hbmpold; + HBITMAP hbmp; + + Size size; + Draw *painting; + Point painting_offset; + +public: + void Put(SystemDraw& w, int x, int y); + void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); } + + void Create(SystemDraw& w, int cx, int cy); + void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); } + void Destroy(); + + void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; } + + BackDraw(); + ~BackDraw(); +}; + +class ImageDraw : public SystemDraw { + Size size; + + struct Section { + HDC dc; + HBITMAP hbmp, hbmpOld; + RGBA *pixels; + + void Init(int cx, int cy); + ~Section(); + }; + + Section rgb; + Section a; + SystemDraw alpha; + + + bool has_alpha; + + void Init(); + Image Get(bool pm) const; + +public: + Draw& Alpha(); + + operator Image() const; + + Image GetStraight() const; + + ImageDraw(Size sz); + ImageDraw(int cx, int cy); + ~ImageDraw(); +}; + +END_UPP_NAMESPACE + +#define GUIPLATFORM_KEYCODES_INCLUDE "Win32Keys.h" + + +#define GUIPLATFORM_CTRL_TOP_DECLS \ + HWND hwnd; \ + UDropTarget *dndtgt; \ + + +#define GUIPLATFORM_CTRL_DECLS_INCLUDE "Win32Ctrl.h" + + +#define GUIPLATFORM_PASTECLIP_DECLS \ + UDropTarget *dt; \ + +#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE "Win32Top.h" + +NAMESPACE_UPP + +inline unsigned GetHashValue(const HWND& hwnd) +{ + return (unsigned)(intptr_t)hwnd; +} +END_UPP_NAMESPACE + +#ifdef PLATFORM_WIN32 +#ifndef PLATFORM_WINCE + +#include + +#endif +#endif + +NAMESPACE_UPP + +class PrinterJob { + NilDraw nil; + Vector pages; + +public: + Draw& GetDraw() { return nil; } + operator Draw&() { return GetDraw(); } + const Vector& GetPages() const { return pages; } + int operator[](int i) const { return 0; } + int GetPageCount() const { return 0; } + + bool Execute() { return false; } + + PrinterJob& Landscape(bool b = true) { return *this; } + PrinterJob& MinMaxPage(int minpage, int maxpage) { return *this; } + PrinterJob& PageCount(int n) { return *this; } + PrinterJob& CurrentPage(int currentpage) { return *this; } + PrinterJob& Name(const char *_name) { return *this; } + + PrinterJob(const char *name = NULL) {} + ~PrinterJob() {} +}; + +END_UPP_NAMESPACE + +#define GUIPLATFORM_INCLUDE_AFTER diff --git a/rainbow/WinAlt/WinAlt.upp b/rainbow/WinAlt/WinAlt.upp new file mode 100644 index 000000000..c014305f6 --- /dev/null +++ b/rainbow/WinAlt/WinAlt.upp @@ -0,0 +1,19 @@ +file + WinAlt.h, + WinAltGuiA.h, + WinAltKeys.h, + DrawOpWinAlt.cpp, + DrawTextWinAlt.cpp, + DrawWinAlt.cpp, + ImageWinAlt.cpp, + UtilWinAlt.cpp, + WinAltCtrl.h, + WinAltCtrl.cpp, + TopWinAlt.cpp, + WinAltTop.h, + WinAltClip.cpp, + WinAltDnD.cpp, + WinAltProc.cpp, + WinAltWnd.cpp, + ChSysInit.cpp; + diff --git a/rainbow/WinAlt/WinAltClip.cpp b/rainbow/WinAlt/WinAltClip.cpp new file mode 100644 index 000000000..351efa720 --- /dev/null +++ b/rainbow/WinAlt/WinAltClip.cpp @@ -0,0 +1,521 @@ +#include +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) + +VectorMap& sClipMap() +{ + static VectorMap x; + return x; +} + +extern HWND utilityHWND; + +int GetClipboardFormatCode(const char *format_id) +{ + GuiLock ___; + int x = (int)(intptr_t)format_id; + if(x >= 0 && x < 65535) + return x; + String fmt = format_id; + if(fmt == "text") + return CF_TEXT; + if(fmt == "wtext") + return CF_UNICODETEXT; + if(fmt == "dib") + return CF_DIB; + if(fmt == "files") + return CF_HDROP; + static StaticMutex m; + Mutex::Lock __(m); + static VectorMap format_map; + int f = format_map.Find(format_id); + if(f < 0) { + f = format_map.GetCount(); + format_map.Add(format_id, +#ifdef PLATFORM_WINCE + ::RegisterClipboardFormat(ToSystemCharset(format_id)) +#else + ::RegisterClipboardFormat(format_id) +#endif + ); + } + return format_map[f]; +} + +void ClipboardLog(const char *txt) +{ +#ifdef flagCHECKCLIPBOARD + FileAppend f(GetExeDirFile("clip.log")); + f << txt << "\n"; +#endif +} + +void ClipboardError(const char *txt) +{ +#ifdef flagCHECKCLIPBOARD + String s = txt; + s << "\n" << GetLastErrorMessage(); + MessageBox(::GetActiveWindow(), s, "Clipboard error", MB_ICONSTOP | MB_OK | MB_APPLMODAL); + ClipboardLog(String().Cat() << s << " ERROR"); +#endif +} + +String FromWin32CF(int cf); + +void ClipboardError(const char *txt, int format) +{ +#ifdef flagCHECKCLIPBOARD + ClipboardError(String().Cat() << txt << ' ' << FromWin32CF(format)); +#endif +} + +bool ClipboardOpen() +{ + // Win32 has serious race condition problem with clipboard; system or other apps open it + // right after we close it thus blocking us to send more formats + // So the solution is to wait and retry... (mirek, 2011-01-09) + int delay = 5; + for(int i = 0; i < 5; i++) { + if(OpenClipboard(utilityHWND)) + return true; + Sleep(delay += delay); + } + return false; +} + +void ClearClipboard() +{ + GuiLock __; + sClipMap().Clear(); +#ifdef flagCHECKCLIPBOARD + DeleteFile(GetExeDirFile("clip.log")); +#endif + ClipboardLog("* ClearClipboard"); + if(ClipboardOpen()) { + if(!EmptyClipboard()) + ClipboardError("EmptyClipboard ERROR"); + if(!CloseClipboard()) + ClipboardError("CloseClipboard ERROR"); + } +#ifdef flagCHECKCLIPBOARD + else { + ClipboardError("OpenClipboard ERROR"); + } +#endif +} + +void SetClipboardRaw(int format, const byte *data, int length) +{ + GuiLock __; + HANDLE handle = NULL; + ClipboardLog("* SetClipboardRaw"); + if(data) { + handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, length + 2); + byte *ptr; + if(!handle) { + ClipboardLog("GlobalAlloc ERROR"); + return; + } + if(!(ptr = (byte *)GlobalLock(handle))) { + ClipboardLog("GlobalLock ERROR"); + GlobalFree(handle); + return; + } + memcpy(ptr, data, length); + ptr[length] = 0; + ptr[length + 1] = 0; + GlobalUnlock(handle); + } + if(!SetClipboardData(format, handle)) { + ClipboardError("SetCliboardData", format); + LLOG("SetClipboardData error: " << GetLastErrorMessage()); + GlobalFree(handle); + } +} + +void AppendClipboard(int format, const byte *data, int length) +{ + GuiLock __; + ClipboardLog("* AppendClipboard"); + if(ClipboardOpen()) { + SetClipboardRaw(format, data, length); + if(!CloseClipboard()) + ClipboardError("CloseClipboard", format); + } + else + ClipboardError("OpenClipboard", format); +} + +void AppendClipboard(const char *format, const byte *data, int length) +{ + GuiLock __; + Vector f = Split(format, ';'); + for(int i = 0; i < f.GetCount(); i++) + AppendClipboard(GetClipboardFormatCode(f[i]), data, length); +} + +void AppendClipboard(const char *format, const String& data) +{ + GuiLock __; + AppendClipboard(format, data, data.GetLength()); +} + +void AppendClipboard(const char *format, const Value& data, String (*render)(const Value&)) +{ + GuiLock __; + Vector f = Split(format, ';'); + for(int i = 0; i < f.GetCount(); i++) { + int c = GetClipboardFormatCode(f[i]); + sClipMap().GetAdd(c) = ClipData(data, render); + AppendClipboard(c, NULL, 0); + } +} + +void Ctrl::RenderFormat(int format) +{ + GuiLock __; + int q = sClipMap().Find(format); + if(q >= 0) { + String s = sClipMap()[q].Render(); + SetClipboardRaw(format, s, s.GetLength()); + } +} + +void Ctrl::RenderAllFormats() +{ + GuiLock __; + if(sClipMap().GetCount() && OpenClipboard(utilityHWND)) { + for(int i = 0; i < sClipMap().GetCount(); i++) + RenderFormat(sClipMap().GetKey(i)); + CloseClipboard(); + } +} + +void Ctrl::DestroyClipboard() +{ + GuiLock __; + sClipMap().Clear(); +} + +String ReadClipboard(const char *format) +{ + GuiLock __; + if(!OpenClipboard(NULL)) + return Null; + HGLOBAL hmem = GetClipboardData(GetClipboardFormatCode(format)); + if(hmem == 0) { + CloseClipboard(); + return Null; + } + const byte *src = (const byte *)GlobalLock(hmem); + ASSERT(src); + int length = (int)GlobalSize(hmem); + if(length < 0) { + CloseClipboard(); + return Null; + } + String out(src, length); + GlobalUnlock(hmem); + CloseClipboard(); + return out; +} + +void AppendClipboardText(const String& s) +{ +#ifdef PLATFORM_WINCE + AppendClipboardUnicodeText(s.ToWString()); +#else + AppendClipboard("text", ToSystemCharset(s)); +#endif +} + +void AppendClipboardUnicodeText(const WString& s) +{ +#ifndef PLATFORM_WINCE + AppendClipboardText(s.ToString()); +#endif + AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength()); +} + +const char *ClipFmtsText() +{ + return "wtext;text"; +} + +String GetString(PasteClip& clip) +{ + GuiLock __; + if(clip.Accept("wtext")) { + String s = ~clip; + return WString((const wchar *)~s, wstrlen((const wchar *)~s)).ToString(); + } + if(clip.IsAvailable("text")) + return ~clip; + return Null; +} + +WString GetWString(PasteClip& clip) +{ + GuiLock __; + if(clip.Accept("wtext")) { + String s = ~clip; + return WString((const wchar *)~s, wstrlen((const wchar *)~s)); + } + if(clip.IsAvailable("text")) + return (~clip).ToWString(); + return Null; +} + + +bool AcceptText(PasteClip& clip) +{ + return clip.Accept(ClipFmtsText()); +} + +static String sText(const Value& data) +{ + return data; +} + +static String sWText(const Value& data) +{ + return Unicode__(WString(data)); +} + +void Append(VectorMap& data, const String& text) +{ + data.GetAdd("text", ClipData(text, sText)); + data.GetAdd("wtext", ClipData(text, sWText)); +} + +void Append(VectorMap& data, const WString& text) +{ + data.GetAdd("text", ClipData(text, sText)); + data.GetAdd("wtext", ClipData(text, sWText)); +} + +String GetTextClip(const WString& text, const String& fmt) +{ + if(fmt == "text") + return text.ToString(); + if(fmt == "wtext") + return Unicode__(text); + return Null; +} + +String GetTextClip(const String& text, const String& fmt) +{ + if(fmt == "text") + return text; + if(fmt == "wtext") + return Unicode__(text.ToWString()); + return Null; +} + +String ReadClipboardText() +{ +#ifdef PLATFORM_WINCE + return ReadClipboardUnicodeText().ToString(); +#else + String s = ReadClipboard((const char *)CF_TEXT); + return String(s, (int)strlen(~s)); +#endif +} + +WString ReadClipboardUnicodeText() +{ + String s = ReadClipboard((const char *)CF_UNICODETEXT); + return WString((const wchar *)~s, wstrlen((const wchar *)~s)); +} + +bool IsClipboardAvailable(const char *id) +{ + return ::IsClipboardFormatAvailable(GetClipboardFormatCode(id)); +} + +bool IsClipboardAvailableText() +{ + return IsClipboardAvailable((const char *)CF_TEXT); +} + +const char *ClipFmtsImage() +{ + static const char *q; + ONCELOCK { + static String s = "dib;" + ClipFmt(); + q = s; + } + return q; +} + +bool AcceptImage(PasteClip& clip) +{ + GuiLock __; + return clip.Accept(ClipFmtsImage()); +} + +Image GetImage(PasteClip& clip) +{ + GuiLock __; + Image m; + if(Accept(clip)) { + LoadFromString(m, ~clip); + if(!m.IsEmpty()) + return m; + } + if(clip.Accept("dib")) { + String data = ~clip; + if((unsigned)data.GetCount() < sizeof(BITMAPINFO)) return Null; + BITMAPINFO *lpBI = (BITMAPINFO *)~data; + BITMAPINFOHEADER& hdr = lpBI->bmiHeader; + byte *bits = (byte *)lpBI + hdr.biSize; + if(hdr.biBitCount <= 8) + bits += (hdr.biClrUsed ? hdr.biClrUsed : 1 << hdr.biBitCount) * sizeof(RGBQUAD); + if(hdr.biBitCount >= 16 || hdr.biBitCount == 32) { + if(hdr.biCompression == 3) + bits += 12; + if(hdr.biClrUsed != 0) + bits += hdr.biClrUsed * sizeof(RGBQUAD); + } + int h = abs((int)hdr.biHeight); + ImageDraw iw(hdr.biWidth, h); + ::StretchDIBits(iw.GetHandle(), + 0, 0, hdr.biWidth, h, + 0, 0, hdr.biWidth, h, + bits, lpBI, DIB_RGB_COLORS, SRCCOPY); + return iw; + } + return Null; +} + +Image ReadClipboardImage() +{ + GuiLock __; + PasteClip d = Ctrl::Clipboard(); + return GetImage(d); +} + +String sDib(const Value& image) +{ + Image img = image; + BITMAPINFOHEADER header; + Zero(header); + header.biSize = sizeof(header); + header.biWidth = img.GetWidth(); + header.biHeight = -img.GetHeight(); + header.biBitCount = 32; + header.biPlanes = 1; + header.biCompression = BI_RGB; + StringBuffer b(sizeof(header) + 4 * img.GetLength()); + byte *p = (byte *)~b; + memcpy(p, &header, sizeof(header)); + memcpy(p + sizeof(header), ~img, 4 * img.GetLength()); + return b; +} + +String sImage(const Value& image) +{ + Image img = image; + return StoreAsString(const_cast(img)); +} + +String GetImageClip(const Image& img, const String& fmt) +{ + GuiLock __; + if(img.IsEmpty()) return Null; + if(fmt == "dib") + return sDib(img); + if(fmt == ClipFmt()) + return sImage(img); + return Null; +} + +void AppendClipboardImage(const Image& img) +{ + GuiLock __; + if(img.IsEmpty()) return; + AppendClipboard(ClipFmt(), img, sImage); + AppendClipboard("dib", img, sDib); +} + +bool AcceptFiles(PasteClip& clip) +{ + if(clip.Accept("files")) { + clip.SetAction(DND_COPY); + return true; + } + return false; +} + +bool IsAvailableFiles(PasteClip& clip) +{ + return clip.IsAvailable("files"); +} + +struct sDROPFILES { + DWORD offset; + POINT dummy; + BOOL dummy2; + BOOL unicode; +}; + +Vector GetFiles(PasteClip& clip) +{ + GuiLock __; + Vector f; + String data = clip; + if((unsigned)data.GetCount() < sizeof(sDROPFILES) + 2) + return f; + const sDROPFILES *df = (const sDROPFILES *)~data; + const char *s = ((const char *)df + df->offset); + if(df->unicode) { + const wchar *ws = (wchar *)s; + while(*ws) { + WString fn; + while(*ws) + fn.Cat(*ws++); + f.Add(fn.ToString()); + ws++; + } + } + else + while(*s) { + String fn; + while(*s) + fn.Cat(*s++); + f.Add(fn.ToString()); + s++; + } + return f; +} + +bool Has(UDropTarget *dt, const char *fmt); +String Get(UDropTarget *dt, const char *fmt); + +bool PasteClip::IsAvailable(const char *fmt) const +{ + if(this == &Ctrl::Selection()) + return false; + return dt ? UPP::Has(dt, fmt) : IsClipboardAvailable(fmt); +} + +String PasteClip::Get(const char *fmt) const +{ + if(this == &Ctrl::Selection()) + return Null; + return dt ? UPP::Get(dt, fmt) : ReadClipboard(fmt); +} + +void PasteClip::GuiPlatformConstruct() +{ + dt = NULL; +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/WinAltCtrl.cpp b/rainbow/WinAlt/WinAltCtrl.cpp new file mode 100644 index 000000000..b313b1e1c --- /dev/null +++ b/rainbow/WinAlt/WinAltCtrl.cpp @@ -0,0 +1,157 @@ +#include + +#ifdef GUI_WINALT + +#define LLOG(x) // DLOG(x) + +NAMESPACE_UPP + +void Ctrl::GuiPlatformConstruct() +{ + activex = false; + isdhctrl = false; +} + +void Ctrl::GuiPlatformDestruct() +{ +} + +void Ctrl::GuiPlatformRemove() +{ +} + +void Ctrl::GuiPlatformGetTopRect(Rect& r) const +{ + if(activex) + r = GetWndScreenRect(); +} + +bool Ctrl::GuiPlatformRefreshFrameSpecial(const Rect& r) +{ + if(isdhctrl) { + InvalidateRect(((DHCtrl *)this)->GetHWND(), r, false); + return true; + } + return false; +} + +bool Ctrl::GuiPlatformSetFullRefreshSpecial() +{ + return isdhctrl; +} + +void Ctrl::PaintCaret(SystemDraw& w) +{ +} + +String GuiPlatformGetKeyDesc(dword key) +{ + static struct { + dword key; + const char *name; + } nkey[] = { + { 0x100c0, "[`]" }, { 0x100bd, "[-]" }, { 0x100bb, "[=]" }, { 0x100dc, "[\\]" }, + { 0x100db, "[[]" }, { 0x100dd, "[]]" }, + { 0x100ba, "[;]" }, { 0x100de, "[']" }, + { 0x100bc, "[,]" }, { 0x100be, "[.]" }, { 0x100bf, "[/]" }, + { 0, NULL } + }; + for(int i = 0; nkey[i].key; i++) + if(nkey[i].key == key) + return nkey[i].name; + return Null; +} + +void Ctrl::GuiPlatformSelection(PasteClip&) +{ +} + +void GuiPlatformAdjustDragImage(ImageBuffer&) +{ +} + +bool GuiPlatformHasSizeGrip() +{ + return true; +} + +void GuiPlatformGripResize(TopWindow *q) +{ + HWND hwnd = q->GetHWND(); + Point p = GetMousePos() - q->GetRect().TopLeft(); + if(hwnd) { + ::SendMessage(hwnd, WM_SYSCOMMAND, 0xf008, MAKELONG(p.x, p.y)); + ::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELONG(p.x, p.y)); + } +} + +Color GuiPlatformGetScreenPixel(int x, int y) +{ + HDC sdc = GetWindowDC(0); + Color c = Color::FromCR(GetPixel(sdc, x, y)); + ReleaseDC(0, sdc); + return c; +} + +void GuiPlatformAfterMenuPopUp() +{ +} + +void Ctrl::SetCaret(int x, int y, int cx, int cy) +{ + GuiLock __; + caretx = x; + carety = y; + caretcx = cx; + caretcy = cy; + SyncCaret(); +} + +void Ctrl::SyncCaret() { + GuiLock __; + Rect cr; + cr.Clear(); + if(focusCtrl && focusCtrl->IsVisible()) { + bool inframe = focusCtrl->InFrame(); + cr = focusCtrl->GetScreenView(); + cr = RectC(focusCtrl->caretx + cr.left, focusCtrl->carety + cr.top, + focusCtrl->caretcx, focusCtrl->caretcy) & cr; + for(Ctrl *q = focusCtrl->GetParent(); q; q = q->GetParent()) { + cr &= inframe ? q->GetScreenRect() : q->GetScreenView(); + inframe = q->InFrame(); + } + } + if(focusCtrl != caretCtrl || cr != caretRect) { + LLOG("Do SyncCaret focusCtrl: " << UPP::Name(focusCtrl) + << ", caretCtrl: " << UPP::Name(caretCtrl) + << ", cr: " << cr); + WndDestroyCaret(); + if(focusCtrl && !cr.IsEmpty()) + focusCtrl->GetTopCtrl()->WndCreateCaret(cr); + caretCtrl = focusCtrl; + caretRect = cr; + } +} + +String Ctrl::Name() const { + GuiLock __; +#ifdef CPU_64 + String s = String(typeid(*this).name()) + " : 0x" + FormatIntHex(this); +#else + String s = String(typeid(*this).name()) + " : " + Format("0x%x", (int) this); +#endif + if(IsChild()) + s << "(parent " << String(typeid(*parent).name()) << ")"; + else + s << Format("(hwnd 0x%x)", (int)(intptr_t) GetHWND()); + return s; +} + +void Ctrl::WndCreateCaret(const Rect& cr) +{ + ICall(THISBACK1(WndCreateCaret0, cr)); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/WinAltCtrl.h b/rainbow/WinAlt/WinAltCtrl.h new file mode 100644 index 000000000..dc95241e0 --- /dev/null +++ b/rainbow/WinAlt/WinAltCtrl.h @@ -0,0 +1,68 @@ +//$ class Ctrl { +private: + bool activex:1; + bool isdhctrl:1; + + static void WndDestroyCaret(); + void WndCreateCaret0(const Rect& cr); + void WndCreateCaret(const Rect& cr); + + static bool PeekMsg(MSG& msg); + + static LRESULT CALLBACK UtilityProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + static void RenderFormat(int format); + static void RenderAllFormats(); + static void DestroyClipboard(); + +public: + static Event ExitLoopEvent; + static bool& EndSession(); + static bool IsEndSession() { return EndSession(); } + static HINSTANCE hInstance; + +protected: + static HCURSOR hCursor; + + static VectorMap< HWND, Ptr >& Windows(); + static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + + static Event OverwatchEndSession; + static HWND OverwatchHWND; + static HANDLE OverwatchThread; + + static LRESULT CALLBACK OverwatchWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + static DWORD WINAPI Win32OverwatchThread(LPVOID); + + static Rect GetScreenClient(HWND hwnd); + struct CreateBox; + void Create0(CreateBox *cr); + void Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int show, bool dropshadow); + Image DoMouse(int e, Point p, int zd = 0); + static void sProcessMSG(MSG& msg); + + static Vector hotkey; + + friend void sSetCursor(Ctrl *ctrl, const Image& m); + +public: + virtual void NcCreate(HWND hwnd); + virtual void NcDestroy(); + virtual void PreDestroy(); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + + HWND GetHWND() const { return parent ? NULL : top ? top->hwnd : NULL; } + HWND GetOwnerHWND() const; + + static Ctrl *CtrlFromHWND(HWND hwnd); + + Ctrl& ActiveX(bool ax = true) { activex = ax; return *this; } + Ctrl& NoActiveX() { return ActiveX(false); } + bool IsActiveX() const { return activex; } + + void PopUpHWND(HWND hwnd, bool savebits = true, bool activate = true, bool dropshadow = false, + bool topmost = false); + + static void InitWin32(HINSTANCE hinst); + static void ExitWin32(); + static void GuiFlush() { ::GdiFlush(); } +//$ }; diff --git a/rainbow/WinAlt/WinAltDnD.cpp b/rainbow/WinAlt/WinAltDnD.cpp new file mode 100644 index 000000000..32e663f00 --- /dev/null +++ b/rainbow/WinAlt/WinAltDnD.cpp @@ -0,0 +1,542 @@ +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) + +int GetClipboardFormatCode(const char *format_id); + +int ToWin32CF(const char *s) +{ + return GetClipboardFormatCode(s); +} + +String FromWin32CF(int cf) +{ + GuiLock __; + if(cf == CF_TEXT) + return "text"; + if(cf == CF_UNICODETEXT) + return "wtext"; + if(cf == CF_DIB) + return "dib"; +#ifndef PLATFORM_WINCE + if(cf == CF_HDROP) + return "files"; +#endif + char h[256]; + GetClipboardFormatNameA(cf, h, 255); + return h; +} + +FORMATETC ToFORMATETC(const char *s) +{ + FORMATETC fmtetc; + fmtetc.cfFormat = ToWin32CF(s); + fmtetc.dwAspect = DVASPECT_CONTENT; + fmtetc.lindex = -1; + fmtetc.ptd = NULL; + fmtetc.tymed = TYMED_HGLOBAL; + return fmtetc; +} + +String AsString(POINTL p) +{ + return String().Cat() << "[" << p.x << ", " << p.y << "]"; +} + +struct UDropTarget : public IDropTarget { + ULONG rc; + LPDATAOBJECT data; + Ptr ctrl; + Index fmt; + + STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj); + STDMETHOD_(ULONG, AddRef)(void) { return ++rc; } + STDMETHOD_(ULONG, Release)(void) { if(--rc == 0) { delete this; return 0; } return rc; } + + STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect); + STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect); + STDMETHOD(DragLeave)(); + STDMETHOD(Drop)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect); + + void DnD(POINTL p, bool drop, DWORD *effect, DWORD keys); + void FreeData(); + void Repeat(); + void EndDrag(); + String Get(const char *fmt) const; + + UDropTarget() { rc = 1; data = NULL; } + ~UDropTarget(); +}; + +bool Has(UDropTarget *dt, const char *fmt) +{ + return dt->fmt.Find(fmt) >= 0; +} + +String Get(UDropTarget *dt, const char *fmt) +{ + return dt->Get(fmt); +} + +STDMETHODIMP UDropTarget::QueryInterface(REFIID iid, void ** ppv) +{ + if(iid == IID_IUnknown || iid == IID_IDropTarget) { + *ppv = this; + AddRef(); + return S_OK; + } + *ppv = NULL; + return E_NOINTERFACE; +} + +String UDropTarget::Get(const char *fmt) const +{ + FORMATETC fmtetc = ToFORMATETC(fmt); + STGMEDIUM s; + if(data->GetData(&fmtetc, &s) == S_OK && s.tymed == TYMED_HGLOBAL) { + char *val = (char *)GlobalLock(s.hGlobal); + String data(val, (int)GlobalSize(s.hGlobal)); + GlobalUnlock(s.hGlobal); + ReleaseStgMedium(&s); + return data; + } + return Null; +} + +void UDropTarget::DnD(POINTL pl, bool drop, DWORD *effect, DWORD keys) +{ + GuiLock __; + LLOG("DnD effect: " << *effect); + dword e = *effect; + *effect = DROPEFFECT_NONE; + if(!ctrl) + return; + PasteClip d; + d.dt = this; + d.paste = drop; + d.accepted = false; + d.allowed = 0; + d.action = 0; + if(e & DROPEFFECT_COPY) { + LLOG("DnD DROPEFFECT_COPY"); + d.allowed = DND_COPY; + d.action = DND_COPY; + } + if(e & DROPEFFECT_MOVE) { + LLOG("DnD DROPEFFECT_MOVE"); + d.allowed |= DND_MOVE; + if(Ctrl::GetDragAndDropSource()) + d.action = DND_MOVE; + } + LLOG("DnD keys & MK_CONTROL:" << (keys & MK_CONTROL)); + if((keys & MK_CONTROL) && (d.allowed & DND_COPY)) + d.action = DND_COPY; + if((keys & (MK_ALT|MK_SHIFT)) && (d.allowed & DND_MOVE)) + d.action = DND_MOVE; + ctrl->DnD(Point(pl.x, pl.y), d); + if(d.IsAccepted()) { + LLOG("DnD accepted, action: " << (int)d.action); + if(d.action == DND_MOVE) + *effect = DROPEFFECT_MOVE; + if(d.action == DND_COPY) + *effect = DROPEFFECT_COPY; + } +} + +void UDropTarget::Repeat() +{ + Ctrl::DnDRepeat(); +} + +STDMETHODIMP UDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) +{ + GuiLock __; + LLOG("DragEnter " << pt); + data = pDataObj; + data->AddRef(); + fmt.Clear(); + IEnumFORMATETC *fe; + if(!ctrl || pDataObj->EnumFormatEtc(DATADIR_GET, &fe) != NOERROR) { + *pdwEffect = DROPEFFECT_NONE; + return NOERROR; + } + FORMATETC fmtetc; + while(fe->Next(1, &fmtetc, 0) == S_OK) { + fmt.FindAdd(FromWin32CF(fmtetc.cfFormat)); + if(fmtetc.ptd) + CoTaskMemFree(fmtetc.ptd); + } + fe->Release(); + DnD(pt, false, pdwEffect, grfKeyState); + return NOERROR; +} + + +STDMETHODIMP UDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) +{ + LLOG("DragOver " << pt << " keys: " << grfKeyState); + DnD(pt, false, pdwEffect, grfKeyState); + return NOERROR; +} + +void UDropTarget::FreeData() +{ + if(data) { + data->Release(); + data = NULL; + } +} + +void UDropTarget::EndDrag() +{ + Ctrl::DnDLeave(); +} + +STDMETHODIMP UDropTarget::DragLeave() +{ + LLOG("DragLeave"); + EndDrag(); + FreeData(); + return NOERROR; +} + +STDMETHODIMP UDropTarget::Drop(LPDATAOBJECT, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) +{ + LLOG("Drop"); + if(Ctrl::GetDragAndDropSource()) + Ctrl::OverrideCursor(Null); + DnD(pt, true, pdwEffect, grfKeyState); + EndDrag(); + FreeData(); + return NOERROR; +} + +UDropTarget::~UDropTarget() +{ + if(data) data->Release(); + EndDrag(); +} + +// -------------------------------------------------------------------------------------------- + +Ptr sDnDSource; + +Ctrl * Ctrl::GetDragAndDropSource() +{ + return sDnDSource; +} + +struct UDataObject : public IDataObject { + ULONG rc; + dword effect; + VectorMap data; + + STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj); + STDMETHOD_(ULONG, AddRef)(void) { return ++rc; } + STDMETHOD_(ULONG, Release)(void) { if(--rc == 0) { delete this; return 0; } return rc; } + + STDMETHOD(GetData)(FORMATETC *fmtetc, STGMEDIUM *medium); + STDMETHOD(GetDataHere)(FORMATETC *, STGMEDIUM *); + STDMETHOD(QueryGetData)(FORMATETC *fmtetc); + STDMETHOD(GetCanonicalFormatEtc)(FORMATETC *, FORMATETC *pformatetcOut); + STDMETHOD(SetData)(FORMATETC *fmtetc, STGMEDIUM *medium, BOOL release); + STDMETHOD(EnumFormatEtc)(DWORD dwDirection, IEnumFORMATETC **ief); + STDMETHOD(DAdvise)(FORMATETC *, DWORD, IAdviseSink *, DWORD *); + STDMETHOD(DUnadvise)(DWORD); + STDMETHOD(EnumDAdvise)(LPENUMSTATDATA *); + + UDataObject() { rc = 1; effect = 0; } +}; + +struct UEnumFORMATETC : public IEnumFORMATETC { + ULONG rc; + int ii; + UDataObject *data; + + STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj); + STDMETHOD_(ULONG, AddRef)(void) { return ++rc; } + STDMETHOD_(ULONG, Release)(void) { if(--rc == 0) { delete this; return 0; } return rc; } + + STDMETHOD(Next)(ULONG n, FORMATETC *fmtetc, ULONG *fetched); + STDMETHOD(Skip)(ULONG n); + STDMETHOD(Reset)(void); + STDMETHOD(Clone)(IEnumFORMATETC **newEnum); + + UEnumFORMATETC() { ii = 0; rc = 1; } + ~UEnumFORMATETC() { data->Release(); } +}; + +struct UDropSource : public IDropSource { + ULONG rc; + Image no, move, copy; + + STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj); + STDMETHOD_(ULONG, AddRef)(void) { return ++rc; } + STDMETHOD_(ULONG, Release)(void) { if(--rc == 0) { delete this; return 0; } return rc; } + + STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState); + STDMETHOD(GiveFeedback)(DWORD dwEffect); + + UDropSource() { rc = 1; } +}; + +STDMETHODIMP UDataObject::QueryInterface(REFIID iid, void ** ppv) +{ + if(iid == IID_IUnknown || iid == IID_IDataObject) { + *ppv = this; + AddRef(); + return S_OK; + } + *ppv = NULL; + return E_NOINTERFACE; +} + +void SetMedium(STGMEDIUM *medium, const String& data) +{ + int sz = data.GetCount(); + HGLOBAL hData = GlobalAlloc(0, sz + 4); + if (hData) { + char *ptr = (char *) GlobalLock(hData); + memcpy(ptr, ~data, sz); + memset(ptr + sz, 0, 4); + GlobalUnlock(hData); + medium->tymed = TYMED_HGLOBAL; + medium->hGlobal = hData; + medium->pUnkForRelease = 0; + } +} + +STDMETHODIMP UDataObject::GetData(FORMATETC *fmtetc, STGMEDIUM *medium) +{ + String fmt = FromWin32CF(fmtetc->cfFormat); + ClipData *s = data.FindPtr(fmt); + if(s) { + String q = s->Render(); + SetMedium(medium, q.GetCount() ? q : sDnDSource ? sDnDSource->GetDropData(fmt) : String()); + return S_OK; + } + return DV_E_FORMATETC; +} + +STDMETHODIMP UDataObject::GetDataHere(FORMATETC *, STGMEDIUM *) +{ + return DV_E_FORMATETC; +} + +STDMETHODIMP UDataObject::QueryGetData(FORMATETC *fmtetc) +{ + return data.Find(FromWin32CF(fmtetc->cfFormat)) >= 0 ? S_OK : DV_E_FORMATETC; +} + +STDMETHODIMP UDataObject::GetCanonicalFormatEtc(FORMATETC *, FORMATETC *pformatetcOut) +{ + pformatetcOut->ptd = NULL; + return E_NOTIMPL; +} + +#ifdef PLATFORM_WINCE +static int CF_PERFORMEDDROPEFFECT = RegisterClipboardFormat(_T("Performed DropEffect")); +#else +static int CF_PERFORMEDDROPEFFECT = RegisterClipboardFormat("Performed DropEffect"); +#endif + +STDMETHODIMP UDataObject::SetData(FORMATETC *fmtetc, STGMEDIUM *medium, BOOL release) +{ + if(fmtetc->cfFormat == CF_PERFORMEDDROPEFFECT && medium->tymed == TYMED_HGLOBAL) { + DWORD *val = (DWORD*)GlobalLock(medium->hGlobal); + effect = *val; + GlobalUnlock(medium->hGlobal); + if(release) + ReleaseStgMedium(medium); + return S_OK; + } + return E_NOTIMPL; +} + +STDMETHODIMP UDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ief) +{ + UEnumFORMATETC *ef = new UEnumFORMATETC; + ef->data = this; + AddRef(); + *ief = ef; + return S_OK; +} + +STDMETHODIMP UDataObject::DAdvise(FORMATETC *, DWORD, IAdviseSink *, DWORD *) +{ + return OLE_E_ADVISENOTSUPPORTED; +} + + +STDMETHODIMP UDataObject::DUnadvise(DWORD) +{ + return OLE_E_ADVISENOTSUPPORTED; +} + +STDMETHODIMP UDataObject::EnumDAdvise(LPENUMSTATDATA FAR*) +{ + return OLE_E_ADVISENOTSUPPORTED; +} + +STDMETHODIMP UEnumFORMATETC::QueryInterface(REFIID riid, void FAR* FAR* ppvObj) +{ + if (riid == IID_IUnknown || riid == IID_IEnumFORMATETC) { + *ppvObj = this; + AddRef(); + return NOERROR; + } + *ppvObj = NULL; + return ResultFromScode(E_NOINTERFACE); +} + +STDMETHODIMP UEnumFORMATETC::Next(ULONG n, FORMATETC *t, ULONG *fetched) { + if(t == NULL) + return E_INVALIDARG; + if(fetched) *fetched = 0; + while(ii < data->data.GetCount() && n > 0) { + if(fetched) (*fetched)++; + n--; + *t++ = ToFORMATETC(data->data.GetKey(ii++)); + } + return n ? S_FALSE : NOERROR; +} + +STDMETHODIMP UEnumFORMATETC::Skip(ULONG n) { + ii += n; + if(ii >= data->data.GetCount()) + return S_FALSE; + return NOERROR; +} + +STDMETHODIMP UEnumFORMATETC::Reset() +{ + ii = 0; + return NOERROR; +} + +STDMETHODIMP UEnumFORMATETC::Clone(IEnumFORMATETC **newEnum) +{ + if(newEnum == NULL) + return E_INVALIDARG; + UEnumFORMATETC *ef = new UEnumFORMATETC; + ef->data = data; + data->AddRef(); + ef->ii = ii; + *newEnum = ef; + return NOERROR; +} + +STDMETHODIMP UDropSource::QueryInterface(REFIID riid, void **ppvObj) +{ + if (riid == IID_IUnknown || riid == IID_IDropSource) { + *ppvObj = this; + AddRef(); + return NOERROR; + } + *ppvObj = NULL; + return ResultFromScode(E_NOINTERFACE); +} + +STDMETHODIMP UDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) +{ + if(fEscapePressed) + return DRAGDROP_S_CANCEL; + else + if(!(grfKeyState & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))) + return DRAGDROP_S_DROP; + Ctrl::ProcessEvents(); + return NOERROR; +} + +STDMETHODIMP UDropSource::GiveFeedback(DWORD dwEffect) +{ + LLOG("GiveFeedback"); + Image m = IsNull(move) ? copy : move; + if((dwEffect & DROPEFFECT_COPY) == DROPEFFECT_COPY) { + LLOG("GiveFeedback COPY"); + if(!IsNull(copy)) m = copy; + } + else + if((dwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE) { + LLOG("GiveFeedback MOVE"); + if(!IsNull(move)) m = move; + } + else + m = no; + Ctrl::OverrideCursor(m); + Ctrl::SetMouseCursor(m); + return S_OK; +} + +Image MakeDragImage(const Image& arrow, Image sample); + +Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample) +{ + if(IsWin2K()) + return MakeDragImage(arrow, sample); + else + return arrow98; +} + +int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions, + const VectorMap& data) +{ + UDataObject *obj = new UDataObject; + obj->data <<= data; + if(fmts) { + Vector f = Split(fmts, ';'); + for(int i = 0; i < f.GetCount(); i++) + obj->data.GetAdd(f[i]); + } + UDropSource *dsrc = new UDropSource; + DWORD result = 0; + Image m = Ctrl::OverrideCursor(CtrlCoreImg::DndMove()); + dsrc->no = MakeDragImage(CtrlCoreImg::DndNone(), CtrlCoreImg::DndNone98(), sample); + if(actions & DND_COPY) + dsrc->copy = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndCopy(), CtrlCoreImg::DndCopy98(), sample); + if(actions & DND_MOVE) + dsrc->move = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndMove(), CtrlCoreImg::DndMove98(), sample); + sDnDSource = this; + int level = LeaveGMutexAll(); + HRESULT r = DoDragDrop(obj, dsrc, + (actions & DND_COPY ? DROPEFFECT_COPY : 0) | + (actions & DND_MOVE ? DROPEFFECT_MOVE : 0), &result); + EnterGMutex(level); + DWORD re = obj->effect; + obj->Release(); + dsrc->Release(); + OverrideCursor(m); + SyncCaret(); + CheckMouseCtrl(); + KillRepeat(); + sDnDSource = NULL; + if(r == DRAGDROP_S_DROP) { + if(((result | re) & DROPEFFECT_MOVE) == DROPEFFECT_MOVE && (actions & DND_MOVE)) + return DND_MOVE; + if(((result | re) & DROPEFFECT_COPY) == DROPEFFECT_COPY && (actions & DND_COPY)) + return DND_COPY; + } + return DND_NONE; +} + +void ReleaseUDropTarget(UDropTarget *dt) +{ + dt->Release(); +} + +UDropTarget *NewUDropTarget(Ctrl *ctrl) +{ + UDropTarget *dt = new UDropTarget; + dt->ctrl = ctrl; + return dt; +} + +void Ctrl::SetSelectionSource(const char *fmts) {} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/WinAltGui.h b/rainbow/WinAlt/WinAltGui.h new file mode 100644 index 000000000..274828d8b --- /dev/null +++ b/rainbow/WinAlt/WinAltGui.h @@ -0,0 +1,358 @@ +#define GUI_WINALT + +NAMESPACE_UPP + +class SystemDraw : public Draw { +public: + virtual dword GetInfo() const; + virtual Size GetPageSize() const; + + virtual void BeginOp(); + virtual void EndOp(); + virtual void OffsetOp(Point p); + virtual bool ClipOp(const Rect& r); + virtual bool ClipoffOp(const Rect& r); + virtual bool ExcludeClipOp(const Rect& r); + virtual bool IntersectClipOp(const Rect& r); + virtual bool IsPaintingOp(const Rect& r) const; + virtual Rect GetPaintRect() const; + + virtual void DrawRectOp(int x, int y, int cx, int cy, Color color); + virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color); + virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color); + + virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, + const int *counts, int count_count, + int width, Color color, Color doxor); + virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int scc, + const int *disjunct_polygon_counts, int dpcc, + Color color, int width, Color outline, + uint64 pattern, Color doxor); + virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color); + + virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); + virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, + Color ink, int n, const int *dx); + + virtual Size GetNativeDpi() const; + virtual void BeginNative(); + virtual void EndNative(); + + virtual int GetCloffLevel() const; + +private: + Size pageSize; + Size nativeSize; + Size nativeDpi; + bool palette:1; + bool color16:1; + bool is_mono:1; + int native; + + friend class ImageDraw; + friend class FontInfo; + friend class Font; + + friend void StaticExitDraw_(); + + Point actual_offset_bak; + + struct Cloff : Moveable { + Point org; + HRGN hrgn; + Rect drawingclip; + }; + + Array cloff; + Rect drawingclip; + + COLORREF lastTextColor; + Color lastColor; + HBRUSH orgBrush; + HBRUSH actBrush; + HPEN orgPen; + HPEN actPen; + int lastPen; + Color lastPenColor; + + void Unselect0(); + void Cinit(); + + void LoadCaps(); + void SetPrinterMode(); + void Reset(); + void SetOrg(); + friend HPALETTE GetQlibPalette(); + void DotsMode(); + + static void InitColors(); + + friend class BackDraw; + friend class ScreenDraw; + friend class PrintDraw; + +protected: + dword style; + HDC handle; + Point actual_offset; + + SystemDraw(); + void Init(); + void InitClip(const Rect& clip); + +public: + static Rect GetVirtualScreenArea(); + + static void SetAutoPalette(bool ap); + static bool AutoPalette(); + bool PaletteMode() { return palette; } + + static void Flush() { GdiFlush(); } + + COLORREF GetColor(Color color) const; + + Point GetOffset() const { return actual_offset; } + +#ifndef PLATFORM_WINCE + Point LPtoDP(Point p) const; + Point DPtoLP(Point p) const; + Rect LPtoDP(const Rect& r) const; + Rect DPtoLP(const Rect& r) const; +#endif + + void SetColor(Color color); + void SetDrawPen(int width, Color color); + + Size GetSizeCaps(int i, int j) const; + HDC BeginGdi(); + void EndGdi(); + HDC GetHandle() { return handle; } + operator HDC() const { return handle; } + void Unselect(); + void Attach(HDC ahandle) { handle = ahandle; Init(); } + HDC Detach() { Unselect(); HDC h = handle; handle = NULL; return h; } + + SystemDraw(HDC hdc); + virtual ~SystemDraw(); + + bool CanSetSurface() { return IsGui() && IsWinNT(); } +}; + +#ifndef PLATFORM_WINCE +class WinMetaFile { + Size size; + HENHMETAFILE hemf; + + void Init(); + +public: + void Attach(HENHMETAFILE emf); + HENHMETAFILE Detach(); + + void Set(const void *data, dword len); + void Set(const String& data) { Set(~data, data.GetCount()); } + + String Get() const; + + operator bool() const { return hemf; } + void SetSize(const Size& sz) { size = sz; } + Size GetSize() const { return hemf ? size : Size(0, 0); } + + void Clear(); + + void Paint(Draw& w, const Rect& r) const; + void Paint(Draw& w, int x, int y, int cx, int cy) const; + + void Serialize(Stream& s); + + void ReadClipboard(); + void WriteClipboard() const; + void Load(const char *file) { Set(LoadFile(file)); } + + WinMetaFile() { Init(); } + WinMetaFile(HENHMETAFILE hemf); + WinMetaFile(HENHMETAFILE hemf, Size sz); + WinMetaFile(const char *file); + WinMetaFile(void *data, int len); + WinMetaFile(const String& data); + + ~WinMetaFile() { Clear(); } + + HENHMETAFILE GetHEMF() const { return hemf; } +}; + +class WinMetaFileDraw : public SystemDraw { + Size size; + +public: + bool Create(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + bool Create(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + WinMetaFile Close(); + + WinMetaFileDraw() {} + WinMetaFileDraw(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + WinMetaFileDraw(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + ~WinMetaFileDraw(); +}; + +void DrawWMF(Draw& w, int x, int y, int cx, int cy, const String& wmf); +void DrawWMF(Draw& w, int x, int y, const String& wmf); +Drawing LoadWMF(const char *path, int cx, int cy); +Drawing LoadWMF(const char *path); + +String AsWMF(const Drawing& iw); + +#endif + +class ScreenDraw : public SystemDraw { +public: + ScreenDraw(bool ic = false); + ~ScreenDraw(); +}; + +#ifndef PLATFORM_WINCE +class PrintDraw : public SystemDraw { +public: + virtual void StartPage(); + virtual void EndPage(); + +private: + bool aborted; + + void InitPrinter(); +public: + PrintDraw(HDC hdc, const char *jobname); + ~PrintDraw(); +}; +#endif + +inline bool BitBlt(HDC ddc, Point d, HDC sdc, const Rect& s, dword rop = SRCCOPY) +{ return BitBlt(ddc, d.x, d.y, s.Width(), s.Height(), sdc, s.left, s.top, rop); } + +inline bool StretchBlt(HDC ddc, const Rect& r, HDC sdc, const Rect& s, dword rop = SRCCOPY) +{ return StretchBlt(ddc, r.left, r.top, r.Width(), r.Height(), sdc, s.left, s.top, s.Width(), s.Height(), rop); } + +inline bool PatBlt(HDC dc, const Rect& r, dword rop = PATCOPY) +{ return PatBlt(dc, r.left, r.top, r.Width(), r.Height(), rop); } + +inline void MoveTo(HDC hdc, Point pt) { MoveToEx(hdc, pt.x, pt.y, 0); } +inline void LineTo(HDC hdc, Point pt) { LineTo(hdc, pt.x, pt.y); } + +inline void DrawLine(HDC hdc, Point p, Point q) { MoveTo(hdc, p); LineTo(hdc, q); } +inline void DrawLine(HDC hdc, int px, int py, int qx, int qy) { MoveToEx(hdc, px, py, 0); LineTo(hdc, qx, qy); } + +#ifndef PLATFORM_WINCE +inline void DrawArc(HDC hdc, const Rect& rc, Point p, Point q){ Arc(hdc, rc.left, rc.top, rc.right, rc.bottom, p.x, p.y, q.x, q.y); } +#endif +inline void DrawCircle(HDC hdc, int x, int y, int radius) { Ellipse(hdc, x - radius, y - radius, x + radius + 1, y + radius + 1); } +inline void DrawCircle(HDC hdc, Point centre, int radius) { DrawCircle(hdc, centre.x, centre.y, radius); } +inline void DrawEllipse(HDC hdc, const Rect& rc) { Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); } + +inline void DrawRect(HDC hdc, const Rect& rc) { Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); } + +HDC ScreenHDC(); +HPALETTE GetQlibPalette(); + +Image Win32Icon(LPCSTR id, int iconsize = 0); +Image Win32Icon(int id, int iconsize = 0); +Image Win32Cursor(LPCSTR id); +Image Win32Cursor(int id); +HICON IconWin32(const Image& img, bool cursor = false); +Image Win32DllIcon(const char *dll, int ii, bool large); + +class BackDraw : public SystemDraw { +public: + virtual bool IsPaintingOp(const Rect& r) const; + +protected: + HBITMAP hbmpold; + HBITMAP hbmp; + + Size size; + Draw *painting; + Point painting_offset; + +public: + void Put(SystemDraw& w, int x, int y); + void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); } + + void Create(SystemDraw& w, int cx, int cy); + void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); } + void Destroy(); + + void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; } + + BackDraw(); + ~BackDraw(); +}; + +class ImageDraw : public SystemDraw { + Size size; + + struct Section { + HDC dc; + HBITMAP hbmp, hbmpOld; + RGBA *pixels; + + void Init(int cx, int cy); + ~Section(); + }; + + Section rgb; + Section a; + SystemDraw alpha; + + + bool has_alpha; + + void Init(); + Image Get(bool pm) const; + +public: + Draw& Alpha(); + + operator Image() const; + + Image GetStraight() const; + + ImageDraw(Size sz); + ImageDraw(int cx, int cy); + ~ImageDraw(); +}; + +END_UPP_NAMESPACE + +#define GUIPLATFORM_KEYCODES_INCLUDE "Win32Keys.h" + + +#define GUIPLATFORM_CTRL_TOP_DECLS \ + HWND hwnd; \ + UDropTarget *dndtgt; \ + + +#define GUIPLATFORM_CTRL_DECLS_INCLUDE "Win32Ctrl.h" + + +#define GUIPLATFORM_PASTECLIP_DECLS \ + UDropTarget *dt; \ + +#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE "Win32Top.h" + +NAMESPACE_UPP + +inline unsigned GetHashValue(const HWND& hwnd) +{ + return (unsigned)(intptr_t)hwnd; +} +END_UPP_NAMESPACE + +#ifdef PLATFORM_WIN32 +#ifndef PLATFORM_WINCE + +#include + +#endif +#endif + +#define GUIPLATFORM_INCLUDE_AFTER "Win32GuiA.h" diff --git a/rainbow/WinAlt/WinAltGuiA.h b/rainbow/WinAlt/WinAltGuiA.h new file mode 100644 index 000000000..3f2d16365 --- /dev/null +++ b/rainbow/WinAlt/WinAltGuiA.h @@ -0,0 +1,103 @@ +class ViewDraw : public SystemDraw { +public: + ViewDraw(Ctrl *ctrl); + ~ViewDraw(); + +protected: + HWND hwnd; +}; + + +Vector& coreCmdLine__(); +Vector SplitCmdLine__(const char *cmd); + +#ifdef PLATFORM_WINCE + +#define GUI_APP_MAIN \ +void GuiMainFn_();\ +\ +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow) \ +{ \ + UPP::Ctrl::InitWin32(hInstance); \ + UPP::coreCmdLine__() = UPP::SplitCmdLine__(UPP::FromSystemCharset(lpCmdLine)); \ + UPP::AppInitEnvironment__(); \ + GuiMainFn_(); \ + UPP::Ctrl::CloseTopCtrls(); \ + UPP::UsrLog("---------- About to delete this log..."); \ + UPP::DeleteUsrLog(); \ + UPP::Ctrl::ExitWin32(); \ + UPP::AppExit__(); \ + return UPP::GetExitCode(); \ +} \ +\ +void GuiMainFn_() + +#else + +#define GUI_APP_MAIN \ +void GuiMainFn_();\ +\ +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow) \ +{ \ + UPP::Ctrl::InitWin32(hInstance); \ + UPP::coreCmdLine__() = UPP::SplitCmdLine__(UPP::FromSystemCharset(lpCmdLine)); \ + UPP::AppInitEnvironment__(); \ + GuiMainFn_(); \ + UPP::Ctrl::CloseTopCtrls(); \ + UPP::UsrLog("---------- About to delete this log..."); \ + UPP::DeleteUsrLog(); \ + UPP::Ctrl::ExitWin32(); \ + UPP::AppExit__(); \ + return UPP::GetExitCode(); \ +} \ +\ +void GuiMainFn_() + +#define DLL_APP_MAIN \ +void _DllMainAppInit(); \ +\ +BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpReserved) \ +{ \ + if(fdwReason == DLL_PROCESS_ATTACH) { \ + Ctrl::InitWin32(AppGetHandle()); \ + AppInitEnvironment__(); \ + _DllMainAppInit(); \ + } \ + else \ + if(fdwReason == DLL_PROCESS_DETACH) { \ + Ctrl::ExitWin32(); \ + } \ + return true; \ +} \ +\ +void _DllMainAppInit() + +#endif + +#ifndef PLATFORM_WINCE + +class DHCtrl : public Ctrl { +public: + virtual void State(int reason); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + virtual void NcCreate(HWND hwnd); + virtual void NcDestroy(); + +private: + void OpenHWND(); + void SyncHWND(); + +protected: + void CloseHWND(); + HWND hwnd; + +public: + HWND GetHWND() { return hwnd; } +// void Refresh() { InvalidateRect(GetHWND(), NULL, false); } + + DHCtrl(); + ~DHCtrl(); +}; + +#endif + diff --git a/rainbow/WinAlt/WinAltKeys.h b/rainbow/WinAlt/WinAltKeys.h new file mode 100644 index 000000000..000cea433 --- /dev/null +++ b/rainbow/WinAlt/WinAltKeys.h @@ -0,0 +1,109 @@ +K_BACK = VK_BACK + K_DELTA, +K_BACKSPACE = VK_BACK + K_DELTA, + +K_TAB = 9, + +K_SPACE = 32, + +K_RETURN = 13, +K_ENTER = K_RETURN, + +K_SHIFT_KEY = VK_SHIFT + K_DELTA, +K_CTRL_KEY = VK_CONTROL + K_DELTA, +K_ALT_KEY = VK_MENU + K_DELTA, +K_CAPSLOCK = VK_CAPITAL + K_DELTA, +K_ESCAPE = VK_ESCAPE + K_DELTA, +K_PRIOR = VK_PRIOR + K_DELTA, +K_PAGEUP = VK_PRIOR + K_DELTA, +K_NEXT = VK_NEXT + K_DELTA, +K_PAGEDOWN = VK_NEXT + K_DELTA, +K_END = VK_END + K_DELTA, +K_HOME = VK_HOME + K_DELTA, +K_LEFT = VK_LEFT + K_DELTA, +K_UP = VK_UP + K_DELTA, +K_RIGHT = VK_RIGHT + K_DELTA, +K_DOWN = VK_DOWN + K_DELTA, +K_INSERT = VK_INSERT + K_DELTA, +K_DELETE = VK_DELETE + K_DELTA, + +K_NUMPAD0 = VK_NUMPAD0 + K_DELTA, +K_NUMPAD1 = VK_NUMPAD1 + K_DELTA, +K_NUMPAD2 = VK_NUMPAD2 + K_DELTA, +K_NUMPAD3 = VK_NUMPAD3 + K_DELTA, +K_NUMPAD4 = VK_NUMPAD4 + K_DELTA, +K_NUMPAD5 = VK_NUMPAD5 + K_DELTA, +K_NUMPAD6 = VK_NUMPAD6 + K_DELTA, +K_NUMPAD7 = VK_NUMPAD7 + K_DELTA, +K_NUMPAD8 = VK_NUMPAD8 + K_DELTA, +K_NUMPAD9 = VK_NUMPAD9 + K_DELTA, +K_MULTIPLY = VK_MULTIPLY + K_DELTA, +K_ADD = VK_ADD + K_DELTA, +K_SEPARATOR = VK_SEPARATOR + K_DELTA, +K_SUBTRACT = VK_SUBTRACT + K_DELTA, +K_DECIMAL = VK_DECIMAL + K_DELTA, +K_DIVIDE = VK_DIVIDE + K_DELTA, +K_SCROLL = VK_SCROLL + K_DELTA, + +K_F1 = VK_F1 + K_DELTA, +K_F2 = VK_F2 + K_DELTA, +K_F3 = VK_F3 + K_DELTA, +K_F4 = VK_F4 + K_DELTA, +K_F5 = VK_F5 + K_DELTA, +K_F6 = VK_F6 + K_DELTA, +K_F7 = VK_F7 + K_DELTA, +K_F8 = VK_F8 + K_DELTA, +K_F9 = VK_F9 + K_DELTA, +K_F10 = VK_F10 + K_DELTA, +K_F11 = VK_F11 + K_DELTA, +K_F12 = VK_F12 + K_DELTA, + +K_A = 'A' + K_DELTA, +K_B = 'B' + K_DELTA, +K_C = 'C' + K_DELTA, +K_D = 'D' + K_DELTA, +K_E = 'E' + K_DELTA, +K_F = 'F' + K_DELTA, +K_G = 'G' + K_DELTA, +K_H = 'H' + K_DELTA, +K_I = 'I' + K_DELTA, +K_J = 'J' + K_DELTA, +K_K = 'K' + K_DELTA, +K_L = 'L' + K_DELTA, +K_M = 'M' + K_DELTA, +K_N = 'N' + K_DELTA, +K_O = 'O' + K_DELTA, +K_P = 'P' + K_DELTA, +K_Q = 'Q' + K_DELTA, +K_R = 'R' + K_DELTA, +K_S = 'S' + K_DELTA, +K_T = 'T' + K_DELTA, +K_U = 'U' + K_DELTA, +K_V = 'V' + K_DELTA, +K_W = 'W' + K_DELTA, +K_X = 'X' + K_DELTA, +K_Y = 'Y' + K_DELTA, +K_Z = 'Z' + K_DELTA, +K_0 = '0' + K_DELTA, +K_1 = '1' + K_DELTA, +K_2 = '2' + K_DELTA, +K_3 = '3' + K_DELTA, +K_4 = '4' + K_DELTA, +K_5 = '5' + K_DELTA, +K_6 = '6' + K_DELTA, +K_7 = '7' + K_DELTA, +K_8 = '8' + K_DELTA, +K_9 = '9' + K_DELTA, + +K_CTRL_LBRACKET = K_CTRL|219|K_DELTA, +K_CTRL_RBRACKET = K_CTRL|221|K_DELTA, +K_CTRL_MINUS = K_CTRL|0xbd|K_DELTA, +K_CTRL_GRAVE = K_CTRL|0xc0|K_DELTA, +K_CTRL_SLASH = K_CTRL|0xbf|K_DELTA, +K_CTRL_BACKSLASH = K_CTRL|0xdc|K_DELTA, +K_CTRL_COMMA = K_CTRL|0xbc|K_DELTA, +K_CTRL_PERIOD = K_CTRL|0xbe|K_DELTA, +K_CTRL_SEMICOLON = K_CTRL|0xbe|K_DELTA, +K_CTRL_EQUAL = K_CTRL|0xbb|K_DELTA, +K_CTRL_APOSTROPHE= K_CTRL|0xde|K_DELTA, + +K_BREAK = VK_CANCEL + K_DELTA, diff --git a/rainbow/WinAlt/WinAltMsg.i b/rainbow/WinAlt/WinAltMsg.i new file mode 100644 index 000000000..a578ff256 --- /dev/null +++ b/rainbow/WinAlt/WinAltMsg.i @@ -0,0 +1,126 @@ +#pragma BLITZ_APPROVE + +x_MSG(WM_CREATE) +x_MSG(WM_DESTROY) +x_MSG(WM_MOVE) +x_MSG(WM_SIZE) +x_MSG(WM_ACTIVATE) +x_MSG(WM_SETFOCUS) +x_MSG(WM_KILLFOCUS) +x_MSG(WM_ENABLE) +x_MSG(WM_SETREDRAW) +x_MSG(WM_SETTEXT) +x_MSG(WM_GETTEXT) +x_MSG(WM_GETTEXTLENGTH) +x_MSG(WM_PAINT) +x_MSG(WM_CLOSE) +x_MSG(WM_QUIT) +x_MSG(WM_ERASEBKGND) +x_MSG(WM_SYSCOLORCHANGE) +x_MSG(WM_SHOWWINDOW) +x_MSG(WM_WININICHANGE) +x_MSG(WM_FONTCHANGE) +x_MSG(WM_NEXTDLGCTL) +x_MSG(WM_DRAWITEM) +x_MSG(WM_MEASUREITEM) +x_MSG(WM_DELETEITEM) +x_MSG(WM_VKEYTOITEM) +x_MSG(WM_CHARTOITEM) +x_MSG(WM_SETFONT) +x_MSG(WM_GETFONT) +x_MSG(WM_QUERYDRAGICON) +x_MSG(WM_COMPAREITEM) +x_MSG(WM_GETDLGCODE) +x_MSG(WM_KEYDOWN) +x_MSG(WM_KEYUP) +x_MSG(WM_CHAR) +x_MSG(WM_DEADCHAR) +x_MSG(WM_SYSKEYDOWN) +x_MSG(WM_SYSKEYUP) +x_MSG(WM_SYSCHAR) +x_MSG(WM_SYSDEADCHAR) +x_MSG(WM_KEYLAST) +x_MSG(WM_INITDIALOG) +x_MSG(WM_COMMAND) +x_MSG(WM_SYSCOMMAND) +x_MSG(WM_TIMER) +x_MSG(WM_HSCROLL) +x_MSG(WM_VSCROLL) +x_MSG(WM_INITMENUPOPUP) +x_MSG(WM_MENUCHAR) +x_MSG(WM_LBUTTONDOWN) +x_MSG(WM_LBUTTONUP) +x_MSG(WM_LBUTTONDBLCLK) +x_MSG(WM_RBUTTONDOWN) +x_MSG(WM_RBUTTONUP) +x_MSG(WM_RBUTTONDBLCLK) +x_MSG(WM_MBUTTONDOWN) +x_MSG(WM_MBUTTONUP) +x_MSG(WM_MBUTTONDBLCLK) +x_MSG(WM_MOUSEMOVE) +x_MSG(WM_CUT) +x_MSG(WM_COPY) +x_MSG(WM_PASTE) +x_MSG(WM_CLEAR) +x_MSG(WM_UNDO) +x_MSG(WM_RENDERFORMAT) +x_MSG(WM_RENDERALLFORMATS) +x_MSG(WM_DESTROYCLIPBOARD) +x_MSG(WM_QUERYNEWPALETTE) +x_MSG(WM_PALETTECHANGED) +x_MSG(WM_WINDOWPOSCHANGED) + +#ifndef PLATFORM_WINCE +x_MSG(WM_QUERYENDSESSION) +x_MSG(WM_ENDSESSION) +x_MSG(WM_QUERYOPEN) +x_MSG(WM_DEVMODECHANGE) +x_MSG(WM_ACTIVATEAPP) +x_MSG(WM_TIMECHANGE) +x_MSG(WM_MOUSEACTIVATE) +x_MSG(WM_CHILDACTIVATE) +x_MSG(WM_QUEUESYNC) +x_MSG(WM_GETMINMAXINFO) +x_MSG(WM_ICONERASEBKGND) +x_MSG(WM_SPOOLERSTATUS) +x_MSG(WM_COMPACTING) +x_MSG(WM_NCLBUTTONDOWN) +x_MSG(WM_NCLBUTTONUP) +x_MSG(WM_NCLBUTTONDBLCLK) +x_MSG(WM_NCRBUTTONDOWN) +x_MSG(WM_NCRBUTTONUP) +x_MSG(WM_NCRBUTTONDBLCLK) +x_MSG(WM_NCMBUTTONDOWN) +x_MSG(WM_NCMBUTTONUP) +x_MSG(WM_NCMBUTTONDBLCLK) +x_MSG(WM_NCCREATE) +x_MSG(WM_NCDESTROY) +x_MSG(WM_NCCALCSIZE) +x_MSG(WM_NCPAINT) +x_MSG(WM_NCACTIVATE) +x_MSG(WM_INITMENU) +x_MSG(WM_MENUSELECT) +x_MSG(WM_PARENTNOTIFY) +x_MSG(WM_MDICREATE) +x_MSG(WM_MDIDESTROY) +x_MSG(WM_MDIACTIVATE) +x_MSG(WM_MDIRESTORE) +x_MSG(WM_MDINEXT) +x_MSG(WM_MDIMAXIMIZE) +x_MSG(WM_MDITILE) +x_MSG(WM_MDICASCADE) +x_MSG(WM_MDIICONARRANGE) +x_MSG(WM_MDIGETACTIVE) +x_MSG(WM_MDISETMENU) +x_MSG(WM_DRAWCLIPBOARD) +x_MSG(WM_PAINTCLIPBOARD) +x_MSG(WM_VSCROLLCLIPBOARD) +x_MSG(WM_SIZECLIPBOARD) +x_MSG(WM_ASKCBFORMATNAME) +x_MSG(WM_CHANGECBCHAIN) +x_MSG(WM_HSCROLLCLIPBOARD) +x_MSG(WM_PALETTEISCHANGING) +x_MSG(WM_DROPFILES) +x_MSG(WM_POWER) +x_MSG(WM_WINDOWPOSCHANGING) +#endif diff --git a/rainbow/WinAlt/WinAltProc.cpp b/rainbow/WinAlt/WinAltProc.cpp new file mode 100644 index 000000000..7a7f6f4db --- /dev/null +++ b/rainbow/WinAlt/WinAltProc.cpp @@ -0,0 +1,502 @@ +#include + +#ifdef GUI_WINALT + +#include + +//#include "imm.h" + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) + +dword Ctrl::KEYtoK(dword chr) { + if(chr == VK_TAB) + chr = K_TAB; + else + if(chr == VK_SPACE) + chr = K_SPACE; + else + if(chr == VK_RETURN) + chr = K_RETURN; + else + chr = chr + K_DELTA; + if(chr == K_ALT_KEY || chr == K_CTRL_KEY || chr == K_SHIFT_KEY) + return chr; + if(GetCtrl()) chr |= K_CTRL; + if(GetAlt()) chr |= K_ALT; + if(GetShift()) chr |= K_SHIFT; + return chr; +} + + +class NilDrawFull : public NilDraw { + virtual bool IsPaintingOp(const Rect& r) const { return true; } +}; + +#ifdef PLATFORM_WINCE + + +bool GetShift() { return false; } +bool GetCtrl() { return false; } +bool GetAlt() { return false; } +bool GetCapsLock() { return false; } + +bool wince_mouseleft; +bool wince_mouseright; + +bool GetMouseLeft() { return wince_mouseleft; } +bool GetMouseRight() { return wince_mouseright; } +bool GetMouseMiddle() { return false; } + +Point wince_mousepos = Null; + +Point GetMousePos() { + return wince_mousepos; +} + +void SetWinceMouse(HWND hwnd, LPARAM lparam) +{ + Point p(lparam); + ClientToScreen(hwnd, p); + wince_mousepos = p; +} +#else +void SetWinceMouse(HWND hwnd, LPARAM lparam) {} + +bool GetShift() { return !!(GetKeyState(VK_SHIFT) & 0x8000); } +bool GetCtrl() { return !!(GetKeyState(VK_CONTROL) & 0x8000); } +bool GetAlt() { return !!(GetKeyState(VK_MENU) & 0x8000); } +bool GetCapsLock() { return !!(GetKeyState(VK_CAPITAL) & 1); } +bool GetMouseLeft() { return !!(GetKeyState(VK_LBUTTON) & 0x8000); } +bool GetMouseRight() { return !!(GetKeyState(VK_RBUTTON) & 0x8000); } +bool GetMouseMiddle() { return !!(GetKeyState(VK_MBUTTON) & 0x8000); } +#endif + +void AvoidPaintingCheck__() +{ + Ctrl::painting = false; +} + +bool PassWindowsKey(int wParam); + +LRESULT Ctrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { + GuiLock __; + eventid++; + ASSERT_(!painting, "WindowProc invoked while in Paint routine"); +// LLOG("Ctrl::WindowProc(" << message << ") in " << ::Name(this) << ", focus " << (void *)::GetFocus()); + Ptr _this = this; + HWND hwnd = GetHWND(); + switch(message) { + case WM_PALETTECHANGED: + if((HWND)wParam == hwnd) + break; +#ifndef PLATFORM_WINCE + case WM_QUERYNEWPALETTE: + if(!SystemDraw::AutoPalette()) break; + { + HDC hDC = GetDC(hwnd); + HPALETTE hOldPal = SelectPalette(hDC, GetQlibPalette(), FALSE); + int i = RealizePalette(hDC); + SelectPalette(hDC, hOldPal, TRUE); + RealizePalette(hDC); + ReleaseDC(hwnd, hDC); + LLOG("Realized " << i << " colors"); + if(i) InvalidateRect(hwnd, NULL, TRUE); + return i; + } +#endif + case WM_PAINT: + ASSERT(hwnd); + if(hwnd) { + PAINTSTRUCT ps; + if(IsVisible()) + SyncScroll(); + HDC dc = BeginPaint(hwnd, &ps); + fullrefresh = false; + if(IsVisible()) { + SystemDraw draw(dc); + #ifndef PLATFORM_WINCE + HPALETTE hOldPal; + if(draw.PaletteMode() && SystemDraw::AutoPalette()) { + hOldPal = SelectPalette(dc, GetQlibPalette(), TRUE); + int n = RealizePalette(dc); + LLOG("In paint realized " << n << " colors"); + } + #endif + painting = true; + UpdateArea(draw, Rect(ps.rcPaint)); + painting = false; + #ifndef PLATFORM_WINCE + if(draw.PaletteMode() && SystemDraw::AutoPalette()) + SelectPalette(dc, hOldPal, TRUE); + #endif + } + EndPaint(hwnd, &ps); + } + return 0L; +#ifndef PLATFORM_WINCE + case WM_NCHITTEST: + CheckMouseCtrl(); + if(ignoremouse) return HTTRANSPARENT; + break; +#endif + case WM_LBUTTONDOWN: +#ifdef PLARFORM_WINCE + wince_mouseleft = true; +#endif + SetWinceMouse(hwnd, lParam); + ClickActivateWnd(); + if(ignoreclick) return 0L; + DoMouse(LEFTDOWN, Point((dword)lParam), 0); + if(_this) PostInput(); + return 0L; + case WM_LBUTTONUP: + if(ignoreclick) + EndIgnore(); + else + DoMouse(LEFTUP, Point((dword)lParam), 0); +#ifdef PLATFORM_WINCE + wince_mouseleft = false; +#endif +#ifdef PLATFORM_WINCE + wince_mousepos = Point(-99999, -99999); + if(!ignoreclick) + if(_this) DoMouse(MOUSEMOVE, Point(-99999, -99999)); +#endif + if(_this) PostInput(); + return 0L; + case WM_LBUTTONDBLCLK: + ClickActivateWnd(); + if(ignoreclick) return 0L; + DoMouse(LEFTDOUBLE, Point((dword)lParam), 0); + if(_this) PostInput(); + return 0L; + case WM_RBUTTONDOWN: + ClickActivateWnd(); + if(ignoreclick) return 0L; + DoMouse(RIGHTDOWN, Point((dword)lParam)); + if(_this) PostInput(); + return 0L; + case WM_RBUTTONUP: + if(ignoreclick) + EndIgnore(); + else + DoMouse(RIGHTUP, Point((dword)lParam)); + if(_this) PostInput(); + return 0L; + case WM_RBUTTONDBLCLK: + ClickActivateWnd(); + if(ignoreclick) return 0L; + DoMouse(RIGHTDOUBLE, Point((dword)lParam)); + if(_this) PostInput(); + return 0L; + case WM_MBUTTONDOWN: + ClickActivateWnd(); + if(ignoreclick) return 0L; + DoMouse(MIDDLEDOWN, Point((dword)lParam)); + if(_this) PostInput(); + return 0L; + case WM_MBUTTONUP: + if(ignoreclick) + EndIgnore(); + else + DoMouse(MIDDLEUP, Point((dword)lParam)); + if(_this) PostInput(); + return 0L; + case WM_MBUTTONDBLCLK: + ClickActivateWnd(); + if(ignoreclick) return 0L; + DoMouse(MIDDLEDOUBLE, Point((dword)lParam)); + if(_this) PostInput(); + return 0L; +#ifndef PLATFORM_WINCE + case WM_NCLBUTTONDOWN: + case WM_NCRBUTTONDOWN: + case WM_NCMBUTTONDOWN: + ClickActivateWnd(); + IgnoreMouseUp(); + break; +#endif + case WM_MOUSEMOVE: + SetWinceMouse(hwnd, lParam); + LLOG("WM_MOUSEMOVE: ignoreclick = " << ignoreclick); + if(ignoreclick) { + EndIgnore(); + return 0L; + } + if(_this) + DoMouse(MOUSEMOVE, Point((dword)lParam)); + DoCursorShape(); + return 0L; + case 0x20a: // WM_MOUSEWHEEL: + if(ignoreclick) { + EndIgnore(); + return 0L; + } + if(_this) + DoMouse(MOUSEWHEEL, Point((dword)lParam), (short)HIWORD(wParam)); + if(_this) PostInput(); + return 0L; + case WM_SETCURSOR: + if((HWND)wParam == hwnd && LOWORD((dword)lParam) == HTCLIENT) { + if(hCursor) SetCursor(hCursor); + return TRUE; + } + break; +// case WM_MENUCHAR: +// return MAKELONG(0, MNC_SELECT); + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_CHAR: + ignorekeyup = false; + case WM_KEYUP: + case WM_SYSKEYUP: + { +#if 0 + String msgdump; + switch(message) + { + case WM_KEYDOWN: msgdump << "WM_KEYDOWN"; break; + case WM_KEYUP: msgdump << "WM_KEYUP"; break; + case WM_SYSKEYDOWN: msgdump << "WM_SYSKEYDOWN"; break; + case WM_SYSKEYUP: msgdump << "WM_SYSKEYUP"; break; + case WM_CHAR: msgdump << "WM_CHAR"; break; + } + msgdump << " wParam = 0x" << FormatIntHex(wParam, 8) + << ", lParam = 0x" << FormatIntHex(lParam, 8) + << ", ignorekeyup = " << (ignorekeyup ? "true" : "false"); + LLOG(msgdump); +#endif + dword keycode = 0; + if(message == WM_KEYDOWN) { + keycode = KEYtoK((dword)wParam); + if(keycode == K_SPACE) + keycode = 0; + } + else + if(message == WM_KEYUP) + keycode = KEYtoK((dword)wParam) | K_KEYUP; + else + if(message == WM_SYSKEYDOWN /*&& ((lParam & 0x20000000) || wParam == VK_F10)*/) + keycode = KEYtoK((dword)wParam); + else + if(message == WM_SYSKEYUP /*&& ((lParam & 0x20000000) || wParam == VK_F10)*/) + keycode = KEYtoK((dword)wParam) | K_KEYUP; + else + if(message == WM_CHAR && wParam != 127 && wParam > 32 || wParam == 32 && KEYtoK(VK_SPACE) == K_SPACE) { +#ifdef PLATFORM_WINCE + keycode = wParam; +#else + if(IsWindowUnicode(hwnd)) // TRC 04/10/17: ActiveX Unicode patch + keycode = (dword)wParam; + else { + char b[20]; + ::GetLocaleInfo(MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT), + LOCALE_IDEFAULTANSICODEPAGE, b, 20); + int codepage = atoi(b); + if(codepage >= 1250 && codepage <= 1258) + keycode = ToUnicode((dword)wParam, codepage - 1250 + CHARSET_WIN1250); + else + keycode = (dword)wParam; + } +#endif + } + bool b = false; + if(keycode) { + b = DispatchKey(keycode, LOWORD(lParam)); + SyncCaret(); + if(_this) PostInput(); + } +// LOG("key processed = " << b); + if(b || (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP) + && wParam != VK_F4 && !PassWindowsKey((dword)wParam)) // 17.11.2003 Mirek -> invoke system menu + return 0L; + break; + } + break; +// case WM_GETDLGCODE: +// return wantfocus ? 0 : DLGC_STATIC; + case WM_ERASEBKGND: + return 1L; + case WM_DESTROY: + PreDestroy(); +#ifndef PLATFORM_WINCE + break; + case WM_NCDESTROY: +#endif + if(!hwnd) break; + if(HasChildDeep(mouseCtrl) || this == ~mouseCtrl) mouseCtrl = NULL; + if(HasChildDeep(focusCtrl) || this == ~focusCtrl) focusCtrl = NULL; + if(HasChildDeep(focusCtrlWnd) || this == ~focusCtrlWnd) { + LLOG("WM_NCDESTROY: clearing focusCtrlWnd = " << ::Name(focusCtrlWnd)); + focusCtrlWnd = NULL; + focusCtrl = NULL; + } + if(::GetFocus() == NULL) { + Ctrl *owner = GetOwner(); + if(owner && (owner->IsForeground() || IsForeground()) && !owner->SetWantFocus()) + IterateFocusForward(owner, owner); + } +#ifdef PLATFORM_WINCE + DefWindowProc(hwnd, message, wParam, lParam); +#else + if(IsWindowUnicode(hwnd)) // TRC 04/10/17: ActiveX unicode patch + DefWindowProcW(hwnd, message, wParam, lParam); + else + DefWindowProc(hwnd, message, wParam, lParam); +#endif + hwnd = NULL; + return 0L; + case WM_CANCELMODE: + if(this == ~captureCtrl || HasChildDeep(captureCtrl)) + ReleaseCtrlCapture(); + break; + case WM_SHOWWINDOW: + visible = (BOOL) wParam; + StateH(SHOW); + break; +#ifndef PLATFORM_WINCE + case WM_MOUSEACTIVATE: + LLOG("WM_MOUSEACTIVATE " << Name() << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); + if(!IsEnabled()) { + if(lastActiveWnd && lastActiveWnd->IsEnabled()) { + LLOG("WM_MOUSEACTIVATE -> ::SetFocus for " << UPP::Name(lastActiveWnd)); + ::SetFocus(lastActiveWnd->GetHWND()); + } + else + MessageBeep(MB_OK); + return MA_NOACTIVATEANDEAT; + } + if(IsPopUp()) return MA_NOACTIVATE; + break; +#endif + case WM_SIZE: + case WM_MOVE: + if(hwnd) { + Rect rect; +#ifndef PLATFORM_WINCE + if(activex) { + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWINFO); + ::GetWindowPlacement(hwnd, &wp); + rect = wp.rcNormalPosition; + } + else +#endif + rect = GetScreenClient(hwnd); + LLOG("WM_MOVE / WM_SIZE: screen client = " << rect); + if(GetRect() != rect) + SetWndRect(rect); + WndDestroyCaret(); + caretCtrl = NULL; + SyncCaret(); + } + return 0L; + case WM_HELP: + return TRUE; + case WM_ACTIVATE: + LLOG("WM_ACTIVATE " << Name() << ", wParam = " << (int)wParam << ", focusCtrlWnd = " << ::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); + ignorekeyup = true; + break; + case WM_SETFOCUS: + LLOG("WM_SETFOCUS " << Name() << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); + if(this != focusCtrlWnd) + if(IsEnabled()) { + LLOG("WM_SETFOCUS -> ActivateWnd: this != focusCtrlWnd, this = " + << Name() << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd)); + ActivateWnd(); + } + else { + if(focusCtrlWnd && focusCtrlWnd->IsEnabled()) { + if(!IsEnabled()) + MessageBeep(MB_OK); + LLOG("WM_SETFOCUS -> ::SetFocus for " << UPP::Name(focusCtrlWnd)); + ::SetFocus(focusCtrlWnd->GetHWND()); + } + else + if(lastActiveWnd && lastActiveWnd->IsEnabled()) { + LLOG("WM_SETFOCUS -> ::SetFocus for " << UPP::Name(lastActiveWnd)); + ::SetFocus(lastActiveWnd->GetHWND()); + } + else { + LLOG("WM_SETFOCUS - ::SetFocus(NULL)"); + ::SetFocus(NULL); + } + } + LLOG("//WM_SETFOCUS " << (void *)hwnd << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); + return 0L; + case WM_KILLFOCUS: + LLOG("WM_KILLFOCUS " << (void *)(HWND)wParam << ", this = " << UPP::Name(this) << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); + LLOG("Kill " << ::Name(CtrlFromHWND((HWND)wParam))); + if(!CtrlFromHWND((HWND)wParam)) { + LLOG("WM_KILLFOCUS -> KillFocusWnd: " << UPP::Name(this)); + KillFocusWnd(); + } + LLOG("//WM_KILLFOCUS " << (void *)(HWND)wParam << ", focusCtrlWnd = " << ::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); + return 0L; + case WM_ENABLE: + if(!!wParam != enabled) { + enabled = !!wParam; + RefreshFrame(); + StateH(ENABLE); + } + return 0L; +#ifndef PLATFORM_WINCE + case WM_GETMINMAXINFO: + { + MINMAXINFO *mmi = (MINMAXINFO *)lParam; + Rect frmrc = Size(200, 200); + ::AdjustWindowRect(frmrc, WS_OVERLAPPEDWINDOW, FALSE); + Size msz = Ctrl::GetWorkArea().Deflated(-frmrc.left, -frmrc.top, + frmrc.right - 200, frmrc.bottom - 200).GetSize(); + Rect minr(Point(50, 50), min(msz, GetMinSize())); + Rect maxr(Point(50, 50), min(msz, GetMaxSize())); + dword style = ::GetWindowLong(hwnd, GWL_STYLE); + dword exstyle = ::GetWindowLong(hwnd, GWL_EXSTYLE); + AdjustWindowRectEx(minr, style, FALSE, exstyle); + AdjustWindowRectEx(maxr, style, FALSE, exstyle); + mmi->ptMinTrackSize = Point(minr.Size()); + mmi->ptMaxTrackSize = Point(maxr.Size()); + LLOG("WM_GETMINMAXINFO: MinTrackSize = " << Point(mmi->ptMinTrackSize) << ", MaxTrackSize = " << Point(mmi->ptMaxTrackSize)); + LLOG("ptMaxSize = " << Point(mmi->ptMaxSize) << ", ptMaxPosition = " << Point(mmi->ptMaxPosition)); + } + return 0L; +#endif + case WM_SETTINGCHANGE: + case 0x031A: // WM_THEMECHANGED + ChSync(); + RefreshLayoutDeep(); + RefreshFrame(); + break; +/* + case WM_IME_COMPOSITION: + HIMC himc = ImmGetContext(hwnd); + if(!himc) break; + CANDIDATEFORM cf; + Rect r = GetScreenRect(); + cf.dwIndex = 0; + cf.dwStyle = CFS_CANDIDATEPOS; + cf.ptCurrentPos.x = r.left + caretx; + cf.ptCurrentPos.y = r.top + carety + caretcy; + ImmSetCandidateWindow (himc, &cf); + break; +*/ + } + if(hwnd) +#ifdef PLATFORM_WINCE + return DefWindowProc(hwnd, message, wParam, lParam); +#else + if(IsWindowUnicode(hwnd)) // TRC 04/10/17: ActiveX unicode patch + return DefWindowProcW(hwnd, message, wParam, lParam); + else + return DefWindowProc(hwnd, message, wParam, lParam); +#endif + return 0L; +} + +void Ctrl::PreDestroy() {} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/WinAltTop.h b/rainbow/WinAlt/WinAltTop.h new file mode 100644 index 000000000..969ea547d --- /dev/null +++ b/rainbow/WinAlt/WinAltTop.h @@ -0,0 +1,20 @@ +//$ class TopWindow { +public: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + +private: + dword style; + dword exstyle; + HICON ico, lico; + + void DeleteIco0(); + void DeleteIco(); + void CenterRect(HWND owner, int center); + +public: + void Open(HWND ownerhwnd); + TopWindow& Style(dword _style); + dword GetStyle() const { return style; } + TopWindow& ExStyle(dword _exstyle); + dword GetExStyle() const { return exstyle; } +//$ }; \ No newline at end of file diff --git a/rainbow/WinAlt/WinAltWnd.cpp b/rainbow/WinAlt/WinAltWnd.cpp new file mode 100644 index 000000000..cd2bdade2 --- /dev/null +++ b/rainbow/WinAlt/WinAltWnd.cpp @@ -0,0 +1,1338 @@ +#include + +#ifdef GUI_WINALT + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) +#define LOGTIMING 0 + +#ifdef _DEBUG +#define LOGMESSAGES 0 +#endif + +#define ELOGW(x) // RLOG(GetSysTime() << ": " << x) // Only activate in MT! +#define ELOG(x) // RLOG(GetSysTime() << ": " << x) + +template<> +unsigned GetHashValue(const HWND& h) +{ + return (unsigned)(intptr_t)h; +} + +bool Ctrl::PeekMsg(MSG& msg) +{ + if(!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) return false; + return IsWindowUnicode(msg.hwnd) ? PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE) + : PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); +} + +static bool sFinished; + +bool IsExiting() +{ + return sFinished; +} + +static BOOL CALLBACK sDumpWindow(HWND hwnd, LPARAM lParam) { + String dump; + dump << (IsWindowEnabled(hwnd) ? "ena" : "dis") << ' ' + << (IsWindowVisible(hwnd) ? "vis" : "hid") << ' ' + << Sprintf("owner=0x%x ", GetWindow(hwnd, GW_OWNER)); + Ctrl *ctrl = Ctrl::CtrlFromHWND(hwnd); + if(ctrl) { +#ifdef _DEBUG + dump << "Ctrl: " << UPP::Name(ctrl); +#endif + } + else if(!lParam) + return TRUE; + else + { +#ifdef PLATFORM_WINCE + wchar clsname[256], title[1024]; +#else + char clsname[256], title[1024]; +#endif + ::GetClassName(hwnd, clsname, __countof(clsname)); + ::GetWindowText(hwnd, title, __countof(title)); + dump << "HWND: " << Sprintf("0x%x", hwnd) << ", class = " + << clsname << ", title = " << title; + } + LLOG(dump); + return TRUE; +} + +void DumpWindowOrder(bool aliens) { +#ifndef PLATFORM_WINCE + LLOG("DumpWindowOrder" << BeginIndent); + EnumChildWindows(NULL, &sDumpWindow, (LPARAM)(aliens ? 1 : 0)); + LLOG(EndIndent << "//DumpWindowOrder"); +#endif +} + +#ifndef PLATFORM_WINCE +Point GetMousePos() { + Point p; + return ::GetCursorPos(p) ? p : Null; + ::GetCursorPos(p); + return p; +} +#endif + +HCURSOR Ctrl::hCursor; +HINSTANCE Ctrl::hInstance; +#ifndef flagDLL +#ifndef PLATFORM_WINCE +HANDLE Ctrl::OverwatchThread; +HWND Ctrl::OverwatchHWND; + +Event Ctrl::OverwatchEndSession; +Event Ctrl::ExitLoopEvent; +#endif +#endif + +GLOBAL_VAR(bool, Ctrl::EndSession) + +#ifndef flagDLL +#ifndef PLATFORM_WINCE +LRESULT CALLBACK Ctrl::OverwatchWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if(msg == WM_USER) { + ELOGW("WM_USER"); + PostQuitMessage(0); + } + if(msg == WM_ENDSESSION) { + EndSession() = true; + ELOGW("WM_ENDSESSION 1"); + ExitLoopEvent.Set(); + ELOGW("WM_ENDSESSION 2"); + OverwatchEndSession.Wait(); + ELOGW("WM_ENDSESSION 3"); + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +DWORD WINAPI Ctrl::Win32OverwatchThread(LPVOID) +{ + WNDCLASS wc; + Zero(wc); + wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)OverwatchWndProc; + wc.hInstance = hInstance; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszClassName = "UPP-OVERWATCH"; + RegisterClass(&wc); + + OverwatchHWND = CreateWindowEx(0, "UPP-OVERWATCH", "", WS_OVERLAPPEDWINDOW, + -1000, -1000, 50, 50, NULL, NULL, hInstance, NULL); + + ELOGW("OverWatch 1"); + ExitLoopEvent.Set(); + ELOGW("OverWatch 2"); + MSG Msg; + while(GetMessage(&Msg, NULL, 0, 0) > 0) { + TranslateMessage(&Msg); + if(IsWindowUnicode(Msg.hwnd)) + DispatchMessageW(&Msg); + else + DispatchMessage(&Msg); + } + ELOGW("OverWatch 3"); + return 0; +} +#endif +#endif + +HWND utilityHWND = 0; + +extern VectorMap& sClipMap(); + +INITBLOCK +{ + sClipMap(); +} + +EXITBLOCK +{ + if(utilityHWND) DestroyWindow(utilityHWND); +} + +LRESULT CALLBACK Ctrl::UtilityProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + sClipMap(); + switch(message) { + case WM_RENDERFORMAT: + RenderFormat((dword)wParam); + return 0; + case WM_DESTROYCLIPBOARD: + DestroyClipboard(); + return 0; + } + return ::DefWindowProc(hWnd, message, wParam, lParam); +} + +#ifdef PLATFORM_WINCE +#define L_(x) L##x +#else +#define L_(x) x +#endif + +static DWORD sMainThreadId; + +void WakeUpGuiThread() +{ + ::PostThreadMessage(sMainThreadId, WM_NULL, 0, 0); +} + +static void Win32PanicMessageBox(const char *title, const char *text) +{ +#ifdef PLATFORM_WINCE + static wchar wtext[256], wtitle[256]; + ToUnicode(wtext, text, strlen(text), CHARSET_DEFAULT); + ToUnicode(wtitle, title, strlen(title), CHARSET_DEFAULT); + MessageBox(::GetActiveWindow(), wtext, wtitle, MB_ICONSTOP | MB_OK | MB_APPLMODAL); +#else + MessageBox(::GetActiveWindow(), text, title, MB_ICONSTOP | MB_OK | MB_APPLMODAL); +#endif +} + +void Ctrl::InitWin32(HINSTANCE hInstance) +{ + GuiLock __; + LLOG("InitWin32"); + InstallPanicMessageBox(&Win32PanicMessageBox); +// RLOGBLOCK("Ctrl::InitWin32"); + sMainThreadId = GetCurrentThreadId(); +#define ILOG(x) // RLOG(x) + Ctrl::hInstance = hInstance; + ILOG("RegisterClassW"); +#ifndef PLATFORM_WINCE + if(IsWinNT()) +#endif + { + WNDCLASSW wc; + Zero(wc); + wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = IsWinVista() ? (HBRUSH)(COLOR_WINDOW+1) : (HBRUSH)NULL; + wc.lpszClassName = L"UPP-CLASS-W"; + RegisterClassW(&wc); + wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpszClassName = L"UPP-CLASS-DS-W"; + RegisterClassW(&wc); + wc.style = CS_SAVEBITS|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpszClassName = L"UPP-CLASS-SB-W"; + RegisterClassW(&wc); + wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS; + wc.lpszClassName = L"UPP-CLASS-SB-DS-W"; + RegisterClassW(&wc); + } + + ILOG("RegisterClassA"); + WNDCLASS wc; + Zero(wc); + wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)Ctrl::WndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = IsWinVista() ? (HBRUSH)(COLOR_WINDOW+1) : (HBRUSH)NULL; + wc.lpszClassName = L_("UPP-CLASS-A"); + RegisterClass(&wc); + if(IsWinXP()) { + wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpszClassName = L_("UPP-CLASS-DS-A"); + RegisterClass(&wc); + } + wc.style = CS_SAVEBITS|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wc.lpszClassName = L_("UPP-CLASS-SB-A"); + RegisterClass(&wc); + if(IsWinXP()) { + wc.style = 0x20000|CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS; + wc.lpszClassName = L_("UPP-CLASS-SB-DS-A"); + RegisterClass(&wc); + } + wc.style = 0; + wc.lpszClassName = L_("UPP-TIMER"); + wc.hCursor = NULL; + wc.lpfnWndProc = &Ctrl::UtilityProc; + RegisterClass(&wc); + + ILOG("InitTimer"); + InitTimer(); + ILOG("SetTimer"); + utilityHWND = CreateWindow(L_("UPP-TIMER"), L_(""), WS_OVERLAPPED, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, hInstance, NULL); + SetTimer(utilityHWND, 1, 10, NULL); + ILOG("Windows"); + Windows(); //?? TRC: what's the use of this? + + ChSync(); + + OleInitialize(NULL); + +/* TRC 05/11/14: moved to GuiSleep to avoid thread creation in OCX DllMain + DWORD dummy; + OverwatchThread = CreateThread(NULL, 0x100000, Win32OverwatchThread, NULL, 0, &dummy); + ExitLoopEvent().Wait(); +*/ + +// TRC 05/11/18: pSetLayeredWindowAttributes moved to GLOBAL_VAR (see below) to make OCX initialization simpler + + Csizeinit(); +#undef ILOG + + if(IsWin7()) + GlobalBackPaint(); +} + +typedef DWORD (WINAPI *PSLWA)(HWND, DWORD, BYTE, DWORD); + +static PSLWA SetLayeredWindowAttributes() +{ + static PSLWA pSet; +#ifndef PLATFORM_WINCE + static bool inited = false; + if(!inited) { + inited = true; + if(HMODULE hDLL = LoadLibrary ("user32")) + pSet = (PSLWA) GetProcAddress(hDLL, "SetLayeredWindowAttributes"); + } +#endif + return pSet; +} + +bool Ctrl::IsAlphaSupported() +{ + return SetLayeredWindowAttributes(); +} + +bool Ctrl::IsCompositedGui() +{ + return false; +} + +void Ctrl::ExitWin32() +{ + RenderAllFormats(); + + OleUninitialize(); + + sFinished = true; + + for(int i = 0; i < hotkey.GetCount(); i++) + if(hotkey[i]) + UnregisterHotKey(NULL, i); + + for(int i = 0; i < Windows().GetCount(); i++) { + HWND hwnd = Windows().GetKey(i); + if(hwnd) + ::DestroyWindow(hwnd); + } + MSG msg; + while(PeekMsg(msg)) + if(msg.message != WM_QUIT) + ::PostQuitMessage(0); +#ifndef flagDLL +#ifndef PLATFORM_WINCE + ELOG("ExitWin32 1"); + OverwatchEndSession.Set(); + ELOG("ExitWin32 2"); + PostMessage(OverwatchHWND, WM_USER, 0, 0); + ELOG("ExitWin32 3"); + LLOG("Waiting for overwatch thread to finish..."); + WaitForSingleObject(OverwatchThread, INFINITE); + ELOG("ExitWin32 4"); + LLOG("...overwatch thread finished"); +#endif +#endif +} + +void Ctrl::SetTimerGranularity(int ms) +{ + if(ms > 0) + SetTimer(utilityHWND, 1, ms, NULL); + else + KillTimer(utilityHWND, 1); +} + +VectorMap< HWND, Ptr >& Ctrl::Windows() +{ + static VectorMap< HWND, Ptr > map; + return map; +} + +Vector Ctrl::GetTopCtrls() +{ + Vector v; + VectorMap< HWND, Ptr >& w = Windows(); + for(int i = 0; i < w.GetCount(); i++) + if(w.GetKey(i) && w[i] && !w[i]->parent) + v.Add(w[i]); + return v; +} + +void Ctrl::SetMouseCursor(const Image& image) +{ + GuiLock __; +#ifndef PLATFORM_WINCE + static Image img; + if(image.GetSerialId() != img.GetSerialId()) { + img = image; + HCURSOR hc = IconWin32(img, true); + SetCursor(hc); + if(hCursor) + DestroyCursor(hCursor); + hCursor = hc; + } +#endif +} + +Ctrl *Ctrl::CtrlFromHWND(HWND hwnd) +{ + GuiLock __; + return hwnd ? Windows().Get(hwnd, NULL) : NULL; +} + +HWND Ctrl::GetOwnerHWND() const +{ + GuiLock __; + HWND hwnd = GetHWND(); + if(!hwnd) return NULL; + return GetWindow(hwnd, GW_OWNER); +} + +Ctrl *Ctrl::GetOwner() +{ + GuiLock __; + HWND hwnd = GetOwnerHWND(); + return hwnd ? CtrlFromHWND(hwnd) : NULL; +} + +Ctrl *Ctrl::GetActiveCtrl() +{ + GuiLock __; + if(focusCtrl) + return focusCtrl->GetTopCtrl(); + HWND actwnd = ::GetActiveWindow(); + Vector top = GetTopCtrls(); + for(int i = 0; i < top.GetCount(); i++) + if(top[i]->IsActiveX() && top[i]->GetHWND()) { + LLOG("-> top[" << i << "] = " << FormatIntHex(top[i]->GetHWND())); + for(HWND hwnd = top[i]->GetHWND(); hwnd; hwnd = ::GetParent(hwnd)) + if(hwnd == actwnd) { + LLOG("-> match for " < not found (NULL)"); + return NULL; +} + +UDropTarget *NewUDropTarget(Ctrl *); + +struct Ctrl::CreateBox { + HWND parent; + DWORD style; + DWORD exstyle; + bool savebits; + int show; + bool dropshadow; +}; + +void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int show, bool dropshadow) +{ + CreateBox cr; + cr.parent = parent; + cr.style = style; + cr.exstyle = exstyle; + cr.savebits = savebits; + cr.show = show; + cr.dropshadow = dropshadow; + ICall(callback1(this, &Ctrl::Create0, &cr)); +} + +#if 0 +void Ctrl::Create0(Ctrl::CreateBox *cr) +{ + GuiLock __; + ASSERT(IsMainThread()); + LLOG("Ctrl::Create(parent = " << (void *)parent << ") in " <style, FALSE, cr->exstyle); + isopen = true; + top = new Top; + ASSERT(!cr->parent || IsWindow(cr->parent)); + if(!IsWinXP()) + cr->dropshadow = false; +#ifdef PLATFORM_WINCE + if(parent) + top->hwnd = CreateWindowExW(cr->exstyle, + cr->savebits ? cr->dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W" + : cr->dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W", + L"", cr->style, r.left, r.top, r.Width(), r.Height(), + cr->parent, NULL, hInstance, this); + else + top->hwnd = CreateWindowW(L"UPP-CLASS-W", + L"", WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + cr->parent, NULL, hInstance, this); +#else + if(IsWinNT() && (!cr->parent || IsWindowUnicode(cr->parent))) + top->hwnd = CreateWindowExW(cr->exstyle, + cr->savebits ? cr->dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W" + : cr->dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W", + L"", cr->style, r.left, r.top, r.Width(), r.Height(), + cr->parent, NULL, hInstance, this); + else + top->hwnd = CreateWindowEx(cr->exstyle, + cr->savebits ? cr->dropshadow ? "UPP-CLASS-SB-DS-A" : "UPP-CLASS-SB-A" + : cr->dropshadow ? "UPP-CLASS-DS-A" : "UPP-CLASS-A", + "", cr->style, r.left, r.top, r.Width(), r.Height(), + cr->parent, NULL, hInstance, this); +#endif + + inloop = false; + + ASSERT(top->hwnd); + + ::ShowWindow(top->hwnd, visible ? cr->show : SW_HIDE); +// ::UpdateWindow(hwnd); + StateH(OPEN); + LLOG(EndIndent << "//Ctrl::Create in " <hwnd, (LPDROPTARGET) (top->dndtgt = NewUDropTarget(this))); + CancelMode(); + RefreshLayoutDeep(); +} +#else +// Fix to avoid black corners temorarily artifact +void Ctrl::Create0(Ctrl::CreateBox *cr) +{ + GuiLock __; + ASSERT(IsMainThread()); + LLOG("Ctrl::Create(parent = " << (void *)parent << ") in " <style, FALSE, cr->exstyle); + isopen = true; + top = new Top; + ASSERT(!cr->parent || IsWindow(cr->parent)); + cr->style &= ~WS_VISIBLE; + if(!IsWinXP()) + cr->dropshadow = false; +#ifdef PLATFORM_WINCE + if(parent) + top->hwnd = CreateWindowExW(cr->exstyle, + cr->savebits ? cr->dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W" + : cr->dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W", + L"", cr->style, 0, 0, 0, 0, + cr->parent, NULL, hInstance, this); + else + top->hwnd = CreateWindowW(L"UPP-CLASS-W", + L"", WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + cr->parent, NULL, hInstance, this); +#else + if(IsWinNT() && (!cr->parent || IsWindowUnicode(cr->parent))) + top->hwnd = CreateWindowExW(cr->exstyle, + cr->savebits ? cr->dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W" + : cr->dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W", + L"", cr->style, 0, 0, 0, 0, + cr->parent, NULL, hInstance, this); + else + top->hwnd = CreateWindowEx(cr->exstyle, + cr->savebits ? cr->dropshadow ? "UPP-CLASS-SB-DS-A" : "UPP-CLASS-SB-A" + : cr->dropshadow ? "UPP-CLASS-DS-A" : "UPP-CLASS-A", + "", cr->style, 0, 0, 0, 0, + cr->parent, NULL, hInstance, this); +#endif + + inloop = false; + + ASSERT(top->hwnd); + + ::MoveWindow(top->hwnd, r.left, r.top, r.Width(), r.Height(), false); // To avoid "black corners" artifact effect + ::ShowWindow(top->hwnd, visible ? cr->show : SW_HIDE); +// ::UpdateWindow(hwnd); + StateH(OPEN); + LLOG(EndIndent << "//Ctrl::Create in " <hwnd, (LPDROPTARGET) (top->dndtgt = NewUDropTarget(this))); + CancelMode(); + RefreshLayoutDeep(); +} + +#endif + +void ReleaseUDropTarget(UDropTarget *dt); + +void Ctrl::WndFree() +{ + GuiLock __; + if(!top) return; + RevokeDragDrop(GetHWND()); + ReleaseUDropTarget(top->dndtgt); + isopen = false; + if(!top) return; + HWND owner = GetWindow(top->hwnd, GW_OWNER);// CXL 31.10.2003 z DoRemove + bool focus = ::GetFocus() == top->hwnd; + LLOG("Ctrl::WndDestroy owner " << (void *)owner + << " focus " << focus + << " ::GetFocus() " << (void *)::GetFocus()); + if(owner && focus) { // CXL 7.11.2003 presun - melo by to fungovat take a neblikat... + LLOG("Ctrl::WndFree->SetFocus " << UPP::Name(Ctrl::CtrlFromHWND(owner))); + ::SetFocus(owner); + } + LLOG(EndIndent << "//Ctrl::WndFree() in " <hwnd) { + HWND hwnd = top->hwnd; + WndFree(); // CXL 2007-06-04 to avoid loosing focus with maximize box owned dialogs + ::DestroyWindow(hwnd); + } +} + +Image Ctrl::DoMouse(int e, Point p, int zd) +{ +// LLOG("Ctrl::DoMouse(" << p << ", " << e << ")"); + GuiLock __; + eventCtrl = this; + Image img = DispatchMouse(e, p, zd); + SyncCaret(); + return img; +} + +#ifdef _DEBUG + +bool Ctrl::LogMessages; + +#define x_MSG(x) { x, #x }, + +struct WinMsg { + int ID; + const char *name; +} +sWinMsg[] = { +#include "WinAltMsg.i" + {0, NULL} +}; + +#endif + +void Ctrl::NcCreate(HWND hwnd) +{ + GuiLock __; + if(!parent) + top->hwnd = hwnd; +} + +void Ctrl::NcDestroy() +{ + GuiLock __; + if(!parent) + WndFree(); +} + +LRESULT CALLBACK Ctrl::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + GuiLock __; + if(sFinished) + return DefWindowProc(hWnd, message, wParam, lParam); +#ifdef PLATFORM_WINCE + if(message == WM_CREATE) +#else + if(message == WM_NCCREATE) +#endif + { + Ctrl *w = (Ctrl *)((LPCREATESTRUCT) lParam)->lpCreateParams; + if(w) { + w->NcCreate(hWnd); + int i = Windows().Find(NULL); + if(i >= 0) { + Windows().SetKey(i, hWnd); + Windows()[i] = w; + } + else + Windows().Add(hWnd) = w; + } + } + Ctrl *w = Windows().Get(hWnd, NULL); +#ifdef PLATFORM_WINCE + if(message == WM_DESTROY) +#else + if(message == WM_NCDESTROY) +#endif + { + if(w) w->NcDestroy(); + int i = Windows().Find(hWnd); + if(i >= 0) + Windows().SetKey(i, NULL); + } + #if LOGMESSAGES + bool logblk = false; + if(message != WM_SETCURSOR && message != WM_CTLCOLORBTN && message != WM_TIMER && +#ifndef PLATFORM_WINCE + message != WM_NCHITTEST && message != WM_ENTERIDLE && +#endif + message != WM_CTLCOLORDLG && message != WM_CTLCOLOREDIT && message != WM_CTLCOLORLISTBOX && + message != WM_CTLCOLORMSGBOX && message != WM_CTLCOLORSCROLLBAR && + message != WM_CTLCOLORSTATIC && message != WM_CANCELMODE && + message != 0x0118) + for(WinMsg *m = sWinMsg; m->ID; m++) + if(m->ID == message) { + RLOG(m->name << ' ' << UPP::Name(w) << + Sprintf(", wParam = %d (0x%x), lParam = %d (0x%x)", + wParam, wParam, lParam, lParam)); + VppLog() << LOG_BEGIN; + logblk = true; + break; + } + #endif + LRESULT l = 0; + if(w) { + try + { +#if defined(_DEBUG) && LOGTIMING + int ticks = msecs(); + String wname = w->Name(); +#endif + Ptr pw = w; + l = w->WindowProc(message, wParam, lParam); + if(pw) + pw->SyncMoves(); +#if defined(_DEBUG) && LOGTIMING + String msgname; + for(WinMsg *m = sWinMsg; m->ID; m++) + if(m->ID == message) { + msgname = m->name; + break; + } + if(IsNull(msgname)) + msgname = NFormat("0x%04x", (int)message); + LLOG(NFormat("T+%d %s 0x%08x 0x%08x -> %s", msecs(ticks), msgname, (int)wParam, (int)lParam, wname)); +#endif + } + catch(Exc e) + { + LOG("Ctrl::WindowProc -> Exc: " << e); + NEVER(); + } + } + else + l = DefWindowProc(hWnd, message, wParam, lParam); +#if LOGMESSAGES + if(logblk) + VppLog() << LOG_END; +#endif + return l; +} + +bool PassWindowsKey(int wParam) +{ + return wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9 + || wParam == VK_INSERT || wParam == VK_DELETE + || wParam == VK_HOME || wParam == VK_END + || wParam == VK_PRIOR || wParam == VK_NEXT + || wParam == VK_UP || wParam == VK_DOWN + || wParam == VK_LEFT || wParam == VK_RIGHT + || wParam == VK_CLEAR || wParam == VK_SPACE + || wParam >= 0x90; // OEM keys +} + +Vector Ctrl::hotkey; + +int Ctrl::RegisterSystemHotKey(dword key, Callback cb) +{ + ASSERT(key >= K_DELTA); + int q = hotkey.GetCount(); + for(int i = 0; i < hotkey.GetCount(); i++) + if(!hotkey[i]) { + q = i; + break; + } + hotkey.At(q) = cb; + dword mod = 0; + if(key & K_ALT) + mod |= MOD_ALT; + if(key & K_SHIFT) + mod |= MOD_SHIFT; + if(key & K_CTRL) + mod |= MOD_CONTROL; + + return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1; +} + +void Ctrl::UnregisterSystemHotKey(int id) +{ + if(id >= 0 && id < hotkey.GetCount()) { + UnregisterHotKey(NULL, id); + hotkey[id].Clear(); + } +} + +void Ctrl::sProcessMSG(MSG& msg) +{ + if (msg.message == WM_HOTKEY) { + if(msg.wParam >= 0 && (int)msg.wParam < Ctrl::hotkey.GetCount()) + Ctrl::hotkey[(int)msg.wParam](); + return; + } + if(msg.message != WM_SYSKEYDOWN && msg.message != WM_SYSKEYUP + || PassWindowsKey((dword)msg.wParam) || msg.wParam == VK_MENU) //17.11 Mirek - fix to get windows menu invoked on Alt+Space + TranslateMessage(&msg); // 04/09/07: TRC fix to make barcode reader going better + if(IsWindowUnicode(msg.hwnd)) + DispatchMessageW(&msg); + else + DispatchMessage(&msg); +} + +bool Ctrl::IsWaitingEvent() +{ + MSG msg; + return PeekMsg(msg); +} + +bool Ctrl::ProcessEvent(bool *quit) +{ + ASSERT(IsMainThread()); + if(DoCall()) + return false; + if(EndSession()) + return false; + if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle()) + ReleaseCtrlCapture(); + MSG msg; + if(PeekMsg(msg)) { + if(msg.message == WM_QUIT && quit) + *quit = true; +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": sProcessMSG " << FormatIntHex(msg.message)); + sProcessMSG(msg); +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": //sProcessMSG " << FormatIntHex(msg.message)); + DefferedFocusSync(); + SyncCaret(); + return true; + } + return false; +} + +void SweepMkImageCache(); + +bool Ctrl::ProcessEvents(bool *quit) +{ + if(ProcessEvent(quit)) { + while(ProcessEvent(quit) && (!LoopCtrl || LoopCtrl->InLoop())); // LoopCtrl-MF 071008 + TimerProc(GetTickCount()); + SweepMkImageCache(); + return true; + } + SweepMkImageCache(); + TimerProc(GetTickCount()); + return false; +} + +void Ctrl::EventLoop0(Ctrl *ctrl) +{ + GuiLock __; + ASSERT(IsMainThread()); + ASSERT(LoopLevel == 0 || ctrl); + LoopLevel++; + LLOG("Entering event loop at level " << LoopLevel << BeginIndent); + Ptr ploop; + if(ctrl) { + ploop = LoopCtrl; + LoopCtrl = ctrl; + ctrl->inloop = true; + } + + bool quit = false; + ProcessEvents(&quit); + while(!EndSession() && !quit && ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount()) + { +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / GuiSleep"); + SyncCaret(); + GuiSleep(1000); + if(EndSession()) break; +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / ProcessEvents"); + ProcessEvents(&quit); +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / after ProcessEvents"); + } + + if(ctrl) + LoopCtrl = ploop; + LoopLevel--; + LLOG(EndIndent << "Leaving event loop "); +} + +void Ctrl::GuiSleep0(int ms) +{ + GuiLock __; + ASSERT(IsMainThread()); + ELOG("GuiSleep"); + if(EndSession()) + return; + ELOG("GuiSleep 2"); + int level = LeaveGMutexAll(); +#if !defined(flagDLL) && !defined(PLATFORM_WINCE) + if(!OverwatchThread) { + DWORD dummy; + OverwatchThread = CreateThread(NULL, 0x100000, Win32OverwatchThread, NULL, 0, &dummy); + ELOG("ExitLoopEventWait 1"); + ExitLoopEvent.Wait(); + } + HANDLE h[1]; + *h = ExitLoopEvent.GetHandle(); + ELOG("ExitLoopEventWait 2 " << (void *)*h); + MsgWaitForMultipleObjects(1, h, FALSE, ms, QS_ALLINPUT); +#else + MsgWaitForMultipleObjects(0, NULL, FALSE, ms, QS_ALLINPUT); +#endif + EnterGMutex(level); +} + +void Ctrl::WndDestroyCaret() +{ + LLOG("Ctrl::WndDestroyCaret()"); + ::DestroyCaret(); +} + +void Ctrl::WndCreateCaret0(const Rect& cr) +{ + GuiLock __; + LLOG("Ctrl::WndCreateCaret(" << cr << ") in " << UPP::Name(this)); + HWND hwnd = GetHWND(); + if(!hwnd) return; + Rect r; + ::GetClientRect(hwnd, r); + Point p = r.TopLeft(); + ::ClientToScreen(hwnd, p); + ::CreateCaret(hwnd, NULL, cr.Width(), cr.Height()); + ::SetCaretPos(cr.left - p.x, cr.top - p.y); + ::ShowCaret(hwnd); +} + +Rect Ctrl::GetWndUpdateRect() const +{ + GuiLock __; + HWND hwnd = GetHWND(); + if(!hwnd) return Null; + Rect r; + ::GetUpdateRect(hwnd, r, FALSE); + return r; +} + +Rect Ctrl::GetWndScreenRect() const +{ + GuiLock __; + HWND hwnd = GetHWND(); + if(!hwnd) return Null; + Rect r; + ::GetWindowRect(hwnd, r); + return r; +} + +void Ctrl::WndShow0(bool b) +{ + GuiLock __; + HWND hwnd = GetHWND(); + if(hwnd) + ::ShowWindow(hwnd, b ? SW_SHOW : SW_HIDE); +} + +void Ctrl::WndUpdate0() +{ + GuiLock __; + HWND hwnd = GetHWND(); + if(hwnd) ::UpdateWindow(hwnd); +} + +bool Ctrl::IsWndOpen() const { + GuiLock __; + return GetHWND(); +} + +void Ctrl::SetAlpha(byte alpha) +{ + GuiLock __; + HWND hwnd = GetHWND(); + if(!IsAlphaSupported() || parent || !top || !hwnd) + return; + if(alpha == 255) { + SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x80000); + return; + } + SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | 0x80000); + SetLayeredWindowAttributes() (hwnd, 0, alpha, 2); +} + +#define DLLFILENAME "User32.dll" +#define DLIMODULE MultiMon +#define DLIHEADER +#include + +Rect MonitorRectForHWND(HWND hwnd) +{ + if(hwnd && MultiMon()) + if(HMONITOR monitor = MultiMon().MonitorFromWindow(hwnd, 2/*MONITOR_DEFAULTTONEAREST*/)) { + MONITORINFO moninfo; + Zero(moninfo); + moninfo.cbSize = sizeof(moninfo); + MultiMon().GetMonitorInfo(monitor, &moninfo); + return Rect(moninfo.rcWork); + } + return Ctrl::GetPrimaryWorkArea(); +} + +Rect Ctrl::GetWorkArea() const +{ +// return MonitorRectForHWND(GetHWND()); +// mst:2008-12-08, hack for better multimonitor support. + GuiLock __; + const Ctrl *topctl = GetTopCtrl(); + HWND hwnd = topctl->GetHWND(); + if(!hwnd && !((topctl = topctl->GetOwnerCtrl()) && (hwnd = topctl->GetHWND()))) + hwnd = ::GetFocus(); + return MonitorRectForHWND(hwnd); +} + +static BOOL CALLBACK sMonEnumProc(HMONITOR monitor, HDC hdc, LPRECT lprcMonitor, LPARAM data) +{ + MONITORINFO moninfo; + Zero(moninfo); + moninfo.cbSize = sizeof(moninfo); + MultiMon().GetMonitorInfo(monitor, &moninfo); + ((Array *)data)->Add(Rect(moninfo.rcWork)); + return TRUE; +} + +void Ctrl::GetWorkArea(Array& rc) +{ + GuiLock __; + MultiMon().EnumDisplayMonitors(NULL, NULL, &sMonEnumProc, (LPARAM)&rc); +} + +Rect Ctrl::GetVirtualWorkArea() +{ + Rect out = GetPrimaryWorkArea(); + Array rc; + GetWorkArea(rc); + for(int i = 0; i < rc.GetCount(); i++) + out |= rc[i]; + return out; +} + +Rect Ctrl::GetWorkArea(Point pt) +{ + Array rc; + GetWorkArea(rc); + for(int i = 0; i < rc.GetCount(); i++) + if(rc[i].Contains(pt)) + return rc[i]; + return GetPrimaryWorkArea(); +} + +Rect Ctrl::GetVirtualScreenArea() +{ + GuiLock __; + return RectC(GetSystemMetrics(SM_XVIRTUALSCREEN), + GetSystemMetrics(SM_YVIRTUALSCREEN), + GetSystemMetrics(SM_CXVIRTUALSCREEN), + GetSystemMetrics(SM_CYVIRTUALSCREEN)); +} + +Rect Ctrl::GetPrimaryWorkArea() +{ + Rect r; + SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); + LLOG("Ctrl::GetWorkArea -> " << r); + return r; +} + +Rect Ctrl::GetPrimaryScreenArea() +{ + return Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); +} + +int Ctrl::GetKbdDelay() +{ + GuiLock __; +#ifdef PLATFORM_WINCE + return 500; +#else + int a; + SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &a, 0); + return 250 + a * 750 / 4; +#endif +} + +int Ctrl::GetKbdSpeed() +{ + GuiLock __; +#ifdef PLATFORM_WINCE + return 1000 / 32; +#else + int a; + SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &a, 0); + return 1000 / (a + 2); +#endif +} + +void Ctrl::SetWndForeground0() +{ + GuiLock __; + LLOG("Ctrl::SetWndForeground() in " << UPP::Name(this)); + HWND hwnd = GetHWND(); + if(hwnd) + ::SetForegroundWindow(hwnd); +} + +bool Ctrl::IsWndForeground() const +{ + GuiLock __; + HWND hwnd = GetHWND(); + if(!hwnd) + return false; + HWND fore = ::GetForegroundWindow(); + LLOG("Ctrl::IsWndForeground(): hwnd = " << (void *)hwnd + << ", fore = " << (void *)fore << " - " << UPP::Name(CtrlFromHWND(fore))); + if(IsActiveX()) { + while(hwnd && hwnd != fore && !!::GetParent(hwnd)) + hwnd = ::GetParent(hwnd); + } + return hwnd == fore; +} + +void Ctrl::WndEnable0(bool *b) +{ + GuiLock __; + LLOG("Ctrl::WndEnable(" << b << ") in " << UPP::Name(this) << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus()); + if(*b) + ReleaseCapture(); + LLOG("//Ctrl::WndEnable(" << b << ") -> false " < ::SetFocus(" << (void *)hwnd << ")"); +// ::SetActiveWindow(hwnd); + ::SetFocus(hwnd); + *b = true; + return; + } + LLOG("//Ctrl::SetWndFocus() in " <GetTopCtrl() : GetActiveCtrl(); + PopUpHWND(q ? q->GetHWND() : NULL, savebits, activate, dropshadow, topmost); + if(top) top->owner = owner; +} + +Rect Ctrl::GetScreenClient(HWND hwnd) +{ + Rect r; + ::GetClientRect(hwnd, r); + Point tl = r.TopLeft(); + Point br = r.BottomRight(); + ::ClientToScreen(hwnd, tl); + ::ClientToScreen(hwnd, br); + LLOG("Ctrl::GetScreenClient: hwnd = " << FormatPtr(hwnd) << ", client = " << r + << ", screen(tl) = " << tl << ", screen(br) = " << br); + return Rect(tl, br); +} + +Rect Ctrl::GetDefaultWindowRect() { +#ifdef PLATFORM_WINCE + return Rect(0, 0, 100, 100); +#else + HWND hwnd = ::CreateWindow("UPP-CLASS-A", "", WS_OVERLAPPED, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, NULL, NULL); + Rect sr; + if(hwnd) { + ::ShowWindow(hwnd, SW_HIDE); + sr = GetScreenClient(hwnd); + ::DestroyWindow(hwnd); + } + else + sr = RectC(20, 20, 500, 350); + return sr; +#endif +} + +ViewDraw::ViewDraw(Ctrl *ctrl) +{ + EnterGuiMutex(); + Ctrl *top = ctrl->GetTopCtrl(); + hwnd = top->GetHWND(); + ASSERT(hwnd); + Attach(GetDC(hwnd)); + Clipoff(ctrl->GetScreenView() - top->GetScreenRect().TopLeft()); +} + +ViewDraw::~ViewDraw() +{ + End(); + HDC hdc = Detach(); + if(hwnd && hdc) + ReleaseDC(hwnd, hdc); + LeaveGuiMutex(); +} + +Vector SplitCmdLine__(const char *cmd) +{ + Vector out; + while(*cmd) + if((byte)*cmd <= ' ') + cmd++; + else if(*cmd == '\"') { + WString quoted; + while(*++cmd && (*cmd != '\"' || *++cmd == '\"')) + quoted.Cat(FromSystemCharset(String(cmd, 1)).ToWString()); + out.Add(quoted); + } + else { + const char *begin = cmd; + while((byte)*cmd > ' ') + cmd++; + out.Add(String(begin, cmd).ToWString()); + } + return out; +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/WinAlt/init b/rainbow/WinAlt/init new file mode 100644 index 000000000..bcff0135e --- /dev/null +++ b/rainbow/WinAlt/init @@ -0,0 +1,3 @@ +#ifndef _WinAlt_icpp_init_stub +#define _WinAlt_icpp_init_stub +#endif diff --git a/rainbow/guiplatform.h b/rainbow/guiplatform.h new file mode 100644 index 000000000..a78c98292 --- /dev/null +++ b/rainbow/guiplatform.h @@ -0,0 +1,2 @@ +#define GUIPLATFORM_INCLUDE +