📄 dc.cpp
字号:
// the region coords are always the device ones, so do the translation
// manually
//
// FIXME: possible +/-1 error here, to check!
HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
LogicalToDeviceY(y),
LogicalToDeviceX(x + w),
LogicalToDeviceY(y + h));
if ( !hrgn )
{
wxLogLastError(_T("CreateRectRgn"));
}
else
{
SetClippingHrgn((WXHRGN)hrgn);
::DeleteObject(hrgn);
}
}
void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
{
SetClippingHrgn(region.GetHRGN());
}
void wxDC::DestroyClippingRegion()
{
WXMICROWIN_CHECK_HDC
if (m_clipping && m_hDC)
{
#ifdef __WXWINCE__
// On a PocketPC device (not necessarily emulator), resetting
// the clip region as per the old method causes bad display
// problems. In fact setting a null region is probably OK
// on desktop WIN32 also, since the WIN32 docs imply that the user
// clipping region is independent from the paint clipping region.
::SelectClipRgn(GetHdc(), 0);
#else
// TODO: this should restore the previous clipping region,
// so that OnPaint processing works correctly, and the update
// clipping region doesn't get destroyed after the first
// DestroyClippingRegion.
HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
::SelectClipRgn(GetHdc(), rgn);
::DeleteObject(rgn);
#endif
}
wxDCBase::DestroyClippingRegion();
}
// ---------------------------------------------------------------------------
// query capabilities
// ---------------------------------------------------------------------------
bool wxDC::CanDrawBitmap() const
{
return true;
}
bool wxDC::CanGetTextExtent() const
{
#ifdef __WXMICROWIN__
// TODO Extend MicroWindows' GetDeviceCaps function
return true;
#else
// What sort of display is it?
int technology = ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
#endif
}
int wxDC::GetDepth() const
{
WXMICROWIN_CHECK_HDC_RET(16)
return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL);
}
// ---------------------------------------------------------------------------
// drawing
// ---------------------------------------------------------------------------
void wxDC::Clear()
{
WXMICROWIN_CHECK_HDC
RECT rect;
if ( m_canvas )
{
GetClientRect((HWND) m_canvas->GetHWND(), &rect);
}
else
{
// No, I think we should simply ignore this if printing on e.g.
// a printer DC.
// wxCHECK_RET( m_selectedBitmap.Ok(), wxT("this DC can't be cleared") );
if (!m_selectedBitmap.Ok())
return;
rect.left = 0; rect.top = 0;
rect.right = m_selectedBitmap.GetWidth();
rect.bottom = m_selectedBitmap.GetHeight();
}
#ifndef __WXWINCE__
(void) ::SetMapMode(GetHdc(), MM_TEXT);
#endif
DWORD colour = ::GetBkColor(GetHdc());
HBRUSH brush = ::CreateSolidBrush(colour);
::FillRect(GetHdc(), &rect, brush);
::DeleteObject(brush);
#ifndef __WXWINCE__
int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX,
height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY;
::SetMapMode(GetHdc(), MM_ANISOTROPIC);
::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
::SetWindowExtEx(GetHdc(), width, height, NULL);
::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
#endif
}
bool wxDC::DoFloodFill(wxCoord WXUNUSED_IN_WINCE(x),
wxCoord WXUNUSED_IN_WINCE(y),
const wxColour& WXUNUSED_IN_WINCE(col),
int WXUNUSED_IN_WINCE(style))
{
#ifdef __WXWINCE__
return false;
#else
WXMICROWIN_CHECK_HDC_RET(false)
bool success = (0 != ::ExtFloodFill(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
col.GetPixel(),
style == wxFLOOD_SURFACE ? FLOODFILLSURFACE
: FLOODFILLBORDER) ) ;
if (!success)
{
// quoting from the MSDN docs:
//
// Following are some of the reasons this function might fail:
//
// * The filling could not be completed.
// * The specified point has the boundary color specified by the
// crColor parameter (if FLOODFILLBORDER was requested).
// * The specified point does not have the color specified by
// crColor (if FLOODFILLSURFACE was requested)
// * The point is outside the clipping region that is, it is not
// visible on the device.
//
wxLogLastError(wxT("ExtFloodFill"));
}
CalcBoundingBox(x, y);
return success;
#endif
}
bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
{
WXMICROWIN_CHECK_HDC_RET(false)
wxCHECK_MSG( col, false, _T("NULL colour parameter in wxDC::GetPixel") );
// get the color of the pixel
COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y));
wxRGBToColour(*col, pixelcolor);
return true;
}
void wxDC::DoCrossHair(wxCoord x, wxCoord y)
{
WXMICROWIN_CHECK_HDC
wxCoord x1 = x-VIEWPORT_EXTENT;
wxCoord y1 = y-VIEWPORT_EXTENT;
wxCoord x2 = x+VIEWPORT_EXTENT;
wxCoord y2 = y+VIEWPORT_EXTENT;
wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y));
wxDrawLine(GetHdc(), XLOG2DEV(x), YLOG2DEV(y1), XLOG2DEV(x), YLOG2DEV(y2));
CalcBoundingBox(x1, y1);
CalcBoundingBox(x2, y2);
}
void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
{
WXMICROWIN_CHECK_HDC
wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2));
CalcBoundingBox(x1, y1);
CalcBoundingBox(x2, y2);
}
// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
// and ending at (x2, y2)
void wxDC::DoDrawArc(wxCoord x1, wxCoord y1,
wxCoord x2, wxCoord y2,
wxCoord xc, wxCoord yc)
{
#ifdef __WXWINCE__
// Slower emulation since WinCE doesn't support Pie and Arc
double r = sqrt( (x1-xc)*(x1-xc) + (y1-yc)*(y1-yc) );
double sa = acos((x1-xc)/r)/M_PI*180; // between 0 and 180
if( y1>yc ) sa = -sa; // below center
double ea = atan2(yc-y2, x2-xc)/M_PI*180;
DoDrawEllipticArcRot( xc-r, yc-r, 2*r, 2*r, sa, ea );
#else
WXMICROWIN_CHECK_HDC
wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
double dx = xc - x1;
double dy = yc - y1;
double radius = (double)sqrt(dx*dx+dy*dy);
wxCoord r = (wxCoord)radius;
// treat the special case of full circle separately
if ( x1 == x2 && y1 == y2 )
{
DrawEllipse(xc - r, yc - r, 2*r, 2*r);
return;
}
wxCoord xx1 = XLOG2DEV(x1);
wxCoord yy1 = YLOG2DEV(y1);
wxCoord xx2 = XLOG2DEV(x2);
wxCoord yy2 = YLOG2DEV(y2);
wxCoord xxc = XLOG2DEV(xc);
wxCoord yyc = YLOG2DEV(yc);
wxCoord ray = (wxCoord) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1)));
wxCoord xxx1 = (wxCoord) (xxc-ray);
wxCoord yyy1 = (wxCoord) (yyc-ray);
wxCoord xxx2 = (wxCoord) (xxc+ray);
wxCoord yyy2 = (wxCoord) (yyc+ray);
if ( m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT )
{
// Have to add 1 to bottom-right corner of rectangle
// to make semi-circles look right (crooked line otherwise).
// Unfortunately this is not a reliable method, depends
// on the size of shape.
// TODO: figure out why this happens!
Pie(GetHdc(),xxx1,yyy1,xxx2+1,yyy2+1, xx1,yy1,xx2,yy2);
}
else
{
Arc(GetHdc(),xxx1,yyy1,xxx2,yyy2, xx1,yy1,xx2,yy2);
}
CalcBoundingBox(xc - r, yc - r);
CalcBoundingBox(xc + r, yc + r);
#endif
}
void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
wxCoord width, wxCoord height)
{
WXMICROWIN_CHECK_HDC
wxCoord x2 = x1 + width,
y2 = y1 + height;
#if defined(__WIN32__) && !defined(__SYMANTEC__) && !defined(__WXMICROWIN__)
RECT rect;
rect.left = x1;
rect.top = y1;
rect.right = x2;
rect.bottom = y2;
#ifdef __WXWINCE__
DrawFrameControl(GetHdc(), &rect, DFC_BUTTON, DFCS_BUTTONCHECK);
#else
DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK);
#endif
#else // Symantec-MicroWin
// draw a cross
HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH);
HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen);
HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush);
::SetROP2(GetHdc(), R2_COPYPEN);
Rectangle(GetHdc(), x1, y1, x2, y2);
MoveToEx(GetHdc(), x1, y1, NULL);
LineTo(GetHdc(), x2, y2);
MoveToEx(GetHdc(), x2, y1, NULL);
LineTo(GetHdc(), x1, y2);
::SelectObject(GetHdc(), hPenOld);
::SelectObject(GetHdc(), hBrushOld);
::DeleteObject(blackPen);
#endif // Win32/Symantec-MicroWin
CalcBoundingBox(x1, y1);
CalcBoundingBox(x2, y2);
}
void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
{
WXMICROWIN_CHECK_HDC
COLORREF color = 0x00ffffff;
if (m_pen.Ok())
{
color = m_pen.GetColour().GetPixel();
}
SetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), color);
CalcBoundingBox(x, y);
}
void wxDC::DoDrawPolygon(int n,
wxPoint points[],
wxCoord xoffset,
wxCoord yoffset,
int WXUNUSED_IN_WINCE(fillStyle))
{
WXMICROWIN_CHECK_HDC
wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
// Do things less efficiently if we have offsets
if (xoffset != 0 || yoffset != 0)
{
POINT *cpoints = new POINT[n];
int i;
for (i = 0; i < n; i++)
{
cpoints[i].x = (int)(points[i].x + xoffset);
cpoints[i].y = (int)(points[i].y + yoffset);
CalcBoundingBox(cpoints[i].x, cpoints[i].y);
}
#ifndef __WXWINCE__
int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
#endif
(void)Polygon(GetHdc(), cpoints, n);
#ifndef __WXWINCE__
SetPolyFillMode(GetHdc(),prev);
#endif
delete[] cpoints;
}
else
{
int i;
for (i = 0; i < n; i++)
CalcBoundingBox(points[i].x, points[i].y);
#ifndef __WXWINCE__
int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
#endif
(void)Polygon(GetHdc(), (POINT*) points, n);
#ifndef __WXWINCE__
SetPolyFillMode(GetHdc(),prev);
#endif
}
}
void
wxDC::DoDrawPolyPolygon(int n,
int count[],
wxPoint points[],
wxCoord xoffset,
wxCoord yoffset,
int fillStyle)
{
#ifdef __WXWINCE__
wxDCBase::DoDrawPolyPolygon(n, count, points, xoffset, yoffset, fillStyle);
#else
WXMICROWIN_CHECK_HDC
wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
int i, cnt;
for (i = cnt = 0; i < n; i++)
cnt += count[i];
// Do things less efficiently if we have offsets
if (xoffset != 0 || yoffset != 0)
{
POINT *cpoints = new POINT[cnt];
for (i = 0; i < cnt; i++)
{
cpoints[i].x = (int)(points[i].x + xoffset);
cpoints[i].y = (int)(points[i].y + yoffset);
CalcBoundingBox(cpoints[i].x, cpoints[i].y);
}
#ifndef __WXWINCE__
int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
#endif
(void)PolyPolygon(GetHdc(), cpoints, count, n);
#ifndef __WXWINCE__
SetPolyFillMode(GetHdc(),prev);
#endif
delete[] cpoints;
}
else
{
for (i = 0; i < cnt; i++)
CalcBoundingBox(points[i].x, points[i].y);
#ifndef __WXWINCE__
int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
#endif
(void)PolyPolygon(GetHdc(), (POINT*) points, count, n);
#ifndef __WXWINCE__
SetPolyFillMode(GetHdc(),prev);
#endif
}
#endif
// __WXWINCE__
}
void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
{
WXMICROWIN_CHECK_HDC
// Do things less efficiently if we have offsets
if (xoffset != 0 || yoffset != 0)
{
POINT *cpoints = new POINT[n];
int i;
for (i = 0; i < n; i++)
{
cpoints[i].x = (int)(points[i].x + xoffset);
cpoints[i].y = (int)(points[i].y + yoffset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -