📄 dc.cpp
字号:
// including the coresoponding character in text.
bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
{
static int maxLenText = -1;
static int maxWidth = -1;
int fit = 0;
SIZE sz = {0,0};
int stlen = text.Length();
if (maxLenText == -1)
{
// Win9x and WinNT+ have different limits
int version = wxGetOsVersion();
maxLenText = version == wxWINDOWS_NT ? 65535 : 8192;
maxWidth = version == wxWINDOWS_NT ? INT_MAX : 32767;
}
widths.Empty();
widths.Add(0, stlen); // fill the array with zeros
if (stlen == 0)
return true;
if (!::GetTextExtentExPoint(GetHdc(),
text.c_str(), // string to check
wxMin(stlen, maxLenText),
maxWidth,
&fit, // [out] count of chars
// that will fit
&widths[0], // array to fill
&sz))
{
// API failed
wxLogLastError(wxT("GetTextExtentExPoint"));
return false;
}
return true;
}
void wxDC::SetMapMode(int mode)
{
WXMICROWIN_CHECK_HDC
m_mappingMode = mode;
if ( mode == wxMM_TEXT )
{
m_logicalScaleX =
m_logicalScaleY = 1.0;
}
else // need to do some calculations
{
int pixel_width = ::GetDeviceCaps(GetHdc(), HORZRES),
pixel_height = ::GetDeviceCaps(GetHdc(), VERTRES),
mm_width = ::GetDeviceCaps(GetHdc(), HORZSIZE),
mm_height = ::GetDeviceCaps(GetHdc(), VERTSIZE);
if ( (mm_width == 0) || (mm_height == 0) )
{
// we can't calculate mm2pixels[XY] then!
return;
}
double mm2pixelsX = (double)pixel_width / mm_width,
mm2pixelsY = (double)pixel_height / mm_height;
switch (mode)
{
case wxMM_TWIPS:
m_logicalScaleX = twips2mm * mm2pixelsX;
m_logicalScaleY = twips2mm * mm2pixelsY;
break;
case wxMM_POINTS:
m_logicalScaleX = pt2mm * mm2pixelsX;
m_logicalScaleY = pt2mm * mm2pixelsY;
break;
case wxMM_METRIC:
m_logicalScaleX = mm2pixelsX;
m_logicalScaleY = mm2pixelsY;
break;
case wxMM_LOMETRIC:
m_logicalScaleX = mm2pixelsX / 10.0;
m_logicalScaleY = mm2pixelsY / 10.0;
break;
default:
wxFAIL_MSG( _T("unknown mapping mode in SetMapMode") );
}
}
// VZ: it seems very wasteful to always use MM_ANISOTROPIC when in 99% of
// cases we could do with MM_TEXT and in the remaining 0.9% with
// MM_ISOTROPIC (TODO!)
#ifndef __WXWINCE__
::SetMapMode(GetHdc(), MM_ANISOTROPIC);
int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX,
height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY;
::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
::SetWindowExtEx(GetHdc(), width, height, NULL);
::SetViewportOrgEx(GetHdc(), m_deviceOriginX, m_deviceOriginY, NULL);
::SetWindowOrgEx(GetHdc(), m_logicalOriginX, m_logicalOriginY, NULL);
#endif
}
void wxDC::SetUserScale(double x, double y)
{
WXMICROWIN_CHECK_HDC
if ( x == m_userScaleX && y == m_userScaleY )
return;
m_userScaleX = x;
m_userScaleY = y;
this->SetMapMode(m_mappingMode);
}
void wxDC::SetAxisOrientation(bool WXUNUSED_IN_WINCE(xLeftRight),
bool WXUNUSED_IN_WINCE(yBottomUp))
{
WXMICROWIN_CHECK_HDC
#ifndef __WXWINCE__
int signX = xLeftRight ? 1 : -1,
signY = yBottomUp ? -1 : 1;
if ( signX != m_signX || signY != m_signY )
{
m_signX = signX;
m_signY = signY;
SetMapMode(m_mappingMode);
}
#endif
}
void wxDC::SetSystemScale(double x, double y)
{
WXMICROWIN_CHECK_HDC
if ( x == m_scaleX && y == m_scaleY )
return;
m_scaleX = x;
m_scaleY = y;
#ifndef __WXWINCE__
SetMapMode(m_mappingMode);
#endif
}
void wxDC::SetLogicalOrigin(wxCoord x, wxCoord y)
{
WXMICROWIN_CHECK_HDC
if ( x == m_logicalOriginX && y == m_logicalOriginY )
return;
m_logicalOriginX = x;
m_logicalOriginY = y;
#ifndef __WXWINCE__
::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
#endif
}
void wxDC::SetDeviceOrigin(wxCoord x, wxCoord y)
{
WXMICROWIN_CHECK_HDC
if ( x == m_deviceOriginX && y == m_deviceOriginY )
return;
m_deviceOriginX = x;
m_deviceOriginY = y;
::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
}
// ---------------------------------------------------------------------------
// coordinates transformations
// ---------------------------------------------------------------------------
wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
{
return DeviceToLogicalXRel(x - m_deviceOriginX)*m_signX + m_logicalOriginX;
}
wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
{
// axis orientation is not taken into account for conversion of a distance
return (wxCoord)(x / (m_logicalScaleX*m_userScaleX*m_scaleX));
}
wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
{
return DeviceToLogicalYRel(y - m_deviceOriginY)*m_signY + m_logicalOriginY;
}
wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
{
// axis orientation is not taken into account for conversion of a distance
return (wxCoord)( y / (m_logicalScaleY*m_userScaleY*m_scaleY));
}
wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
{
return LogicalToDeviceXRel(x - m_logicalOriginX)*m_signX + m_deviceOriginX;
}
wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
{
// axis orientation is not taken into account for conversion of a distance
return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_scaleX);
}
wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
{
return LogicalToDeviceYRel(y - m_logicalOriginY)*m_signY + m_deviceOriginY;
}
wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
{
// axis orientation is not taken into account for conversion of a distance
return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_scaleY);
}
// ---------------------------------------------------------------------------
// bit blit
// ---------------------------------------------------------------------------
bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
wxCoord width, wxCoord height,
wxDC *source, wxCoord xsrc, wxCoord ysrc,
int rop, bool useMask,
wxCoord xsrcMask, wxCoord ysrcMask)
{
wxCHECK_MSG( source, false, _T("wxDC::Blit(): NULL wxDC pointer") );
WXMICROWIN_CHECK_HDC_RET(false)
// if either the source or destination has alpha channel, we must use
// AlphaBlt() as other function don't handle it correctly
const wxBitmap& bmpSrc = source->m_selectedBitmap;
if ( bmpSrc.Ok() && (bmpSrc.HasAlpha() ||
(m_selectedBitmap.Ok() && m_selectedBitmap.HasAlpha())) )
{
if ( AlphaBlt(GetHdc(), xdest, ydest, width, height,
xsrc, ysrc, GetHdcOf(*source), bmpSrc) )
return true;
}
wxMask *mask = NULL;
if ( useMask )
{
mask = bmpSrc.GetMask();
if ( !(bmpSrc.Ok() && mask && mask->GetMaskBitmap()) )
{
// don't give assert here because this would break existing
// programs - just silently ignore useMask parameter
useMask = false;
}
}
if (xsrcMask == -1 && ysrcMask == -1)
{
xsrcMask = xsrc; ysrcMask = ysrc;
}
COLORREF old_textground = ::GetTextColor(GetHdc());
COLORREF old_background = ::GetBkColor(GetHdc());
if (m_textForegroundColour.Ok())
{
::SetTextColor(GetHdc(), m_textForegroundColour.GetPixel() );
}
if (m_textBackgroundColour.Ok())
{
::SetBkColor(GetHdc(), m_textBackgroundColour.GetPixel() );
}
DWORD dwRop;
switch (rop)
{
case wxXOR: dwRop = SRCINVERT; break;
case wxINVERT: dwRop = DSTINVERT; break;
case wxOR_REVERSE: dwRop = 0x00DD0228; break;
case wxAND_REVERSE: dwRop = SRCERASE; break;
case wxCLEAR: dwRop = BLACKNESS; break;
case wxSET: dwRop = WHITENESS; break;
case wxOR_INVERT: dwRop = MERGEPAINT; break;
case wxAND: dwRop = SRCAND; break;
case wxOR: dwRop = SRCPAINT; break;
case wxEQUIV: dwRop = 0x00990066; break;
case wxNAND: dwRop = 0x007700E6; break;
case wxAND_INVERT: dwRop = 0x00220326; break;
case wxCOPY: dwRop = SRCCOPY; break;
case wxNO_OP: dwRop = DSTCOPY; break;
case wxSRC_INVERT: dwRop = NOTSRCCOPY; break;
case wxNOR: dwRop = NOTSRCCOPY; break;
default:
wxFAIL_MSG( wxT("unsupported logical function") );
return false;
}
bool success = false;
if (useMask)
{
#ifdef __WIN32__
// we want the part of the image corresponding to the mask to be
// transparent, so use "DSTCOPY" ROP for the mask points (the usual
// meaning of fg and bg is inverted which corresponds to wxWin notion
// of the mask which is also contrary to the Windows one)
// On some systems, MaskBlt succeeds yet is much much slower
// than the wxWidgets fall-back implementation. So we need
// to be able to switch this on and off at runtime.
#if wxUSE_SYSTEM_OPTIONS
if (wxSystemOptions::GetOptionInt(wxT("no-maskblt")) == 0)
#endif
{
success = ::MaskBlt
(
GetHdc(),
xdest, ydest, width, height,
GetHdcOf(*source),
xsrc, ysrc,
(HBITMAP)mask->GetMaskBitmap(),
xsrcMask, ysrcMask,
MAKEROP4(dwRop, DSTCOPY)
) != 0;
}
if ( !success )
#endif // Win32
{
// Blit bitmap with mask
HDC dc_mask ;
HDC dc_buffer ;
HBITMAP buffer_bmap ;
#if wxUSE_DC_CACHEING
// create a temp buffer bitmap and DCs to access it and the mask
wxDCCacheEntry* dcCacheEntry1 = FindDCInCache(NULL, source->GetHDC());
dc_mask = (HDC) dcCacheEntry1->m_dc;
wxDCCacheEntry* dcCacheEntry2 = FindDCInCache(dcCacheEntry1, GetHDC());
dc_buffer = (HDC) dcCacheEntry2->m_dc;
wxDCCacheEntry* bitmapCacheEntry = FindBitmapInCache(GetHDC(),
width, height);
buffer_bmap = (HBITMAP) bitmapCacheEntry->m_bitmap;
#else // !wxUSE_DC_CACHEING
// create a temp buffer bitmap and DCs to access it and the mask
dc_mask = ::CreateCompatibleDC(GetHdcOf(*source));
dc_buffer = ::CreateCompatibleDC(GetHdc());
buffer_bmap = ::CreateCompatibleBitmap(GetHdc(), width, height);
#endif // wxUSE_DC_CACHEING/!wxUSE_DC_CACHEING
HGDIOBJ hOldMaskBitmap = ::SelectObject(dc_mask, (HBITMAP) mask->GetMaskBitmap());
HGDIOBJ hOldBufferBitmap = ::SelectObject(dc_buffer, buffer_bmap);
// copy dest to buffer
if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
GetHdc(), xdest, ydest, SRCCOPY) )
{
wxLogLastError(wxT("BitBlt"));
}
// copy src to buffer using selected raster op
if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
GetHdcOf(*source), xsrc, ysrc, dwRop) )
{
wxLogLastError(wxT("BitBlt"));
}
// set masked area in buffer to BLACK (pixel value 0)
COLORREF prevBkCol = ::SetBkColor(GetHdc(), RGB(255, 255, 255));
COLORREF prevCol = ::SetTextColor(GetHdc(), RGB(0, 0, 0));
if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
dc_mask, xsrcMask, ysrcMask, SRCAND) )
{
wxLogLastError(wxT("BitBlt"));
}
// set unmasked area in dest to BLACK
::SetBkColor(GetHdc(), RGB(0, 0, 0));
::SetTextColor(GetHdc(), RGB(255, 255, 255));
if ( !::BitBlt(GetHdc(), xdest, ydest, (int)width, (int)height,
dc_mask, xsrcMask, ysrcMask, SRCAND) )
{
wxLogLastError(wxT("BitBlt"));
}
::SetBkColor(GetHdc(), prevBkCol); // restore colours to original values
::SetTextColor(GetHdc(), prevCol);
// OR buffer to dest
success = ::BitBlt(GetHdc(), xdest, ydest,
(int)width, (int)height,
dc_buffer, 0, 0, SRCPAINT) != 0;
if ( !success )
{
wxLogLastError(wxT("BitBlt"));
}
// tidy up temporary DCs and bitmap
::SelectObject(dc_mask, hOldMaskBitmap);
::SelectObject(dc_buffer, hOldBufferBitmap);
#if !wxUSE_DC_CACHEING
{
::DeleteDC(dc_mask);
::DeleteDC(dc_buffer);
::DeleteObject(buffer_bmap);
}
#endif
}
}
else // no mask, just BitBlt() it
{
// if we already have a DIB, draw it using StretchDIBits(), otherwise
// use StretchBlt() if available and finally fall back to BitBlt()
// FIXME: use appropriate WinCE functions
#ifndef __WXWINCE__
const int caps = ::GetDeviceCaps(GetHdc(), RASTERCAPS);
if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -