【翻译】Use a bitmap as a background image

自绘制列表控件背景
本文介绍如何在自绘制列表控件中设置背景图片,包括增加成员变量保存位图信息、创建逻辑调色板、修改DrawItem函数绘制背景图片等步骤。

原文链接

1: 使用自绘制列表控件

自定义的列表控件必须是自绘制的,因此需要在资源编辑器中设置LVS_OWNERDRAWFIXED标志,而且还必须在自定义的控件类中实现DrawItem函数。

2: 增加成员变量

当每一项都需要重绘的时候去重新加载位图或重新创建逻辑调色板的话,效率不高。因此我们增加成员变量来保存位图,逻辑调色板以及位图的尺寸信息。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> protected :
CPalettem_pal;
CBitmapm_bitmap;
int m_cxBitmap,b_cyBitmap;

3: 增加成员函数来设置背景图片

SetBkImage函数首先做的是,如果位图和调色板已经被创建的话,就删除位图和调色板GDI对象(说明不是第一次调用)。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> if (m_bitmap.m_hObject != NULL)
m_bitmap.DeleteObject();
if (m_pal.m_hObject != NULL)
m_pal.DeleteObject();

然后加载位图并且将位图连接到CBitmap对象上。在这里我们使用全局的::LoadImage()而不是CBitmap::LoadBitmap(),原因是我们需要访问到位图的DIBSECTION,而之所以需要DIBSECTION是因为我们要创建一个与位图使用的颜色相匹配的逻辑调色板。为什么要调色板?呵呵,如果你不建立并使用一个逻辑调色板的话,那么图片在256色的显示器上就会显得很阴暗。此外,为了后面的使用,我们也保存了位图的尺寸信息。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> HBITMAPhBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
lpszResourceName,IMAGE_BITMAP,
0 , 0 ,LR_CREATEDIBSECTION);
if (hBmp == NULL)
return FALSE;
m_bitmap.Attach(hBmp);
BITMAPbm;
m_bitmap.GetBitmap(
& bm);
m_cxBitmap
= bm.bmWidth;
m_cyBitmap
= bm.bmHeight;

一旦我们有了位图集,我们就开始创建逻辑调色板。我们通过调用CBitmap::GetObject()函数来获得对DIBSECTION的访问,从而得到位图所使用的颜色数目。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> // Createalogicalpaletteforthebitmap
DIBSECTIONds;
BITMAPINFOHEADER
& bmInfo = ds.dsBmih;
m_bitmap.GetObject(
sizeof (ds), & ds);

有的时候DIBSECTION 中的BITMAPINFOHEADER字段并没有指明它所使用的颜色数目,在这种情况下我们可以从它每个像素使用的位数来推断它的颜色数目,比如说,8位可以代表256个不同值,因此也就代表了256种颜色。类似的,16位就表明有64K种颜色.

颜色数目多于256的位图并没有颜色表。这种情况下我们简单地创建一个与设备环境兼容的halftone 调色板。一个halftone调色板就是一个包含各种不同颜色的一个样本集。这并不是最好的,但却是最简单的方法。

如果位图的颜色数目少于或等于256,我们就创建调色板。我们为位图分配足够的空间来保存它的颜色表,并且调用函数:: GetDIBColorTable来从位图中获得这个颜色表。我们还分配足够的内存来创建逻辑调色板,并且从位图的颜色表中拷贝所有的颜色实体。

在创建完调色板对象后,我们提前释放掉分配的内存块,并且让窗口无效,从而窗口可以使用新的图片来重画自己。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> // Createahalftonepaletteifcolors>256.
CClientDCdc(NULL); // DesktopDC
if (nColors > 256 )
m_pal.CreateHalftonePalette(
& dc);
else
{
// Createthepalette
RGBQUAD * pRGB = new RGBQUAD[nColors];
CDCmemDC;
memDC.CreateCompatibleDC(
& dc);
memDC.SelectObject(
& m_bitmap);
::GetDIBColorTable(memDC,
0 ,nColors,pRGB);
UINTnSize
= sizeof (LOGPALETTE) + ( sizeof (PALETTEENTRY) * nColors);
LOGPALETTE
* pLP = (LOGPALETTE * ) new BYTE[nSize];
pLP
-> palVersion = 0x300 ;
pLP
-> palNumEntries = nColors;
for ( int i = 0 ;i < nColors;i ++ )
{
pLP
-> palPalEntry[i].peRed = pRGB[i].rgbRed;
pLP
-> palPalEntry[i].peGreen = pRGB[i].rgbGreen;
pLP
-> palPalEntry[i].peBlue = pRGB[i].rgbBlue;
pLP
-> palPalEntry[i].peFlags = 0 ;
}
m_pal.CreatePalette(pLP);
delete[]pLP;
delete[]pRGB;
}
Invalidate();

4: 修改DrawItem() 来处理图片

DrawItem()函数是用于绘制列表中的每一项的。我们在这个函数中绘制背景图片。由于背景图片应该完全地覆盖掉整个客户区,因此我们对剪切区域进行调整,使得它延展到客户区的右边缘。同样地,如果画列表的最后一项,剪切区域就应该扩展到客户区的下边缘。

然后是选择调色板(这只在设备支持调色板时有意义)。

背景图片是以一种平铺地方式进行绘制的,绘制图片时总是使用列表的第一项的左上角来作为参照。这就使得图片产生这样的效果:随着列表控件的内容的变化而滚动。

对原来的DrawItem()函数的另一个改变是只有当背景图片没有绘制时才绘制未被选中的项的背景

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> // Drawbitmapinthebackgroundifonehasbeenset
if (m_bitmap.m_hObject != NULL)
{
CDCtempDC;
tempDC.CreateCompatibleDC(pDC);
tempDC.SelectObject(
& m_bitmap);
GetClientRect(
& rcClient);
CRgnrgnBitmap;
CRectrcTmpBmp(rcItem);
rcTmpBmp.right
= rcClient.right;
// Wealsoneedtocheckwhetheritisthelastitem
// Theupdateregionhastobeextendedtothebottomifitis
if (nItem == GetItemCount() - 1 )
rcTmpBmp.bottom
= rcClient.bottom;
rgnBitmap.CreateRectRgnIndirect(
& rcTmpBmp);
pDC
-> SelectClipRgn( & rgnBitmap);
rgnBitmap.DeleteObject();
if (pDC -> GetDeviceCaps(RASTERCAPS) & RC_PALETTE && m_pal.m_hObject != NULL)
{
pDC
-> SelectPalette( & m_pal,FALSE);
pDC
-> RealizePalette();
}
CRectrcFirstItem;
GetItemRect(
0 ,rcFirstItem,LVIR_BOUNDS);
for ( int i = rcFirstItem.left;i < rcClient.right;i += m_cxBitmap)
for ( int j = rcFirstItem.top;j < rcClient.bottom;j += m_cyBitmap)
pDC
-> BitBlt(i,j,m_cxBitmap,m_cyBitmap, & tempDC,
0 , 0 ,SRCCOPY);
}
// Drawthebackgroundcolor
if (bHighlight)
{
pDC
-> SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC
-> SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
pDC
-> FillRect(rcHighlight, & CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
}
else if (m_bitmap.m_hObject == NULL)
pDC
-> FillRect(rcHighlight, & CBrush(::GetSysColor(COLOR_WINDOW)));

5: WM_ERASEBKGND增加处理

当一张图片用作背景时,由于图片会画在背景上面,所以擦除背景并没有什么意义。擦除背景只会导致屏幕的闪烁,我们对WM_ERASEBKGND处理时,当位图对象合法时就返回true;

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> BOOLCMyListCtrl::OnEraseBkgnd(CDC * pDC)
{
if (m_bitmap.m_hObject != NULL)
return TRUE;
return CListCtrl::OnEraseBkgnd(pDC);
}

6: 重写 OnNotify() 并处理列宽变化

当一列被resize后,只有新扩展出来的地方需要重新绘制,这就在背景图片上产生一个不好的效果。因此,当任何一列被resize后,我们应该在OnNotify函数中使控件的右边无效。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> BOOLCMyListCtrl::OnNotify(WPARAMwParam,LPARAMlParam,LRESULT * pResult)
{
HD_NOTIFY
* pHDN = (HD_NOTIFY * )lParam;

// Thiscodeisforusingbitmapinthebackground
// Invalidatetherightsideofthecontrolwhenacolumnisresized
if (pHDN -> hdr.code == HDN_ITEMCHANGINGW || pHDN -> hdr.code == HDN_ITEMCHANGINGA)
{
if (m_bitmap.m_hObject != NULL)
{
CRectrcClient;
GetClientRect(
& rcClient);
DWORDdwPos
= GetMessagePos();
CPointpt(LOWORD(dwPos),HIWORD(dwPos));
ScreenToClient(
& pt);
rcClient.left
= pt.x;
InvalidateRect(
& rcClient);
}
}
return CListCtrl::OnNotify(wParam,lParam,pResult);
}

7:处理WM_QUERYNEWPALETTE & WM_PALETTECHANGED

当一个窗口准备开始接收输入焦点的时候,WM_QUERYNEWPALETTE消息就发送给它。这给窗口一个实现其逻辑调色板的机会,这样它就可以以最佳的形式展现自己。当系统调色板被改变时WM_PALETTECHANGED就被发送给窗口。如果我们不处理这些消息,而恰好另一个应用程序改变了系统调色板,那么我们的背景图片就会变得很难看。不幸地是,这两个消息都是发给顶层的窗口的。

OnQueryNewPalette首先检查它是否需要重新选择调色板。一旦它实现了逻辑调色板,它就让窗口无效。如果列表控件自己负责处理消息,那么就返回,不做进一步处理,否则OnPaletteChanged函数调用OnQueryNewPalette来实现调色板。

8:从顶层窗口转发调色板消息

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> void CListViewDlg::OnPaletteChanged(CWnd * pFocusWnd)
{
CDialog::OnPaletteChanged(pFocusWnd);
m_listctrl.SendMessage(WM_PALETTECHANGED,(WPARAM)pFocusWnd
-> m_hWnd);
}
BOOLCListViewDlg::OnQueryNewPalette()
{
CDialog::OnQueryNewPalette();
return m_listctrl.SendMessage(WM_QUERYNEWPALETTE);
}


class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has access to protected members //--------------------------------------- public ------------------------------------// public: TFT_eSPI(int16_t _W = TFT_WIDTH, int16_t _H = TFT_HEIGHT); // init() and begin() are equivalent, begin() included for backwards compatibility // Sketch defined tab colour option is for ST7735 displays only void init(uint8_t tc = TAB_COLOUR), begin(uint8_t tc = TAB_COLOUR); // These are virtual so the TFT_eSprite class can override them with sprite specific functions virtual void drawPixel(int32_t x, int32_t y, uint32_t color), drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint32_t color), drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); virtual int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), drawChar(uint16_t uniCode, int32_t x, int32_t y), height(void), width(void); // Read the colour of a pixel at x,y and return value in 565 format virtual uint16_t readPixel(int32_t x, int32_t y); virtual void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); // Note: start + end coordinates // Push (aka write pixel) colours to the set window virtual void pushColor(uint16_t color); // These are non-inlined to enable override virtual void begin_nin_write(); virtual void end_nin_write(); void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3 uint8_t getRotation(void); // Read the current rotation // Change the origin position from the default top left // Note: setRotation, setViewport and resetViewport will revert origin to top left corner of screen/sprite void setOrigin(int32_t x, int32_t y); int32_t getOriginX(void); int32_t getOriginY(void); void invertDisplay(bool i); // Tell TFT to invert all displayed colours // The TFT_eSprite class inherits the following functions (not all are useful to Sprite class void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); // Note: start coordinates + width and height // Viewport commands, see "Viewport_Demo" sketch void setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum = true); bool checkViewport(int32_t x, int32_t y, int32_t w, int32_t h); int32_t getViewportX(void); int32_t getViewportY(void); int32_t getViewportWidth(void); int32_t getViewportHeight(void); bool getViewportDatum(void); void frameViewport(uint16_t color, int32_t w); void resetViewport(void); // Clip input window to viewport bounds, return false if whole area is out of bounds bool clipAddrWindow(int32_t* x, int32_t* y, int32_t* w, int32_t* h); // Clip input window area to viewport bounds, return false if whole area is out of bounds bool clipWindow(int32_t* xs, int32_t* ys, int32_t* xe, int32_t* ye); // Push (aka write pixel) colours to the TFT (use setAddrWindow() first) void pushColor(uint16_t color, uint32_t len), // Deprecated, use pushBlock() pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option pushColors(uint8_t *data, uint32_t len); // Deprecated, use pushPixels() // Write a solid block of a single colour void pushBlock(uint16_t color, uint32_t len); // Write a set of pixels stored in memory, use setSwapBytes(true/false) function to correct endianess void pushPixels(const void * data_in, uint32_t len); // Support for half duplex (bi-directional SDA) SPI bus where MOSI must be switched to input #ifdef TFT_SDA_READ #if defined (TFT_eSPI_ENABLE_8_BIT_READ) uint8_t tft_Read_8(void); // Read 8-bit value from TFT command register #endif void begin_SDA_Read(void); // Begin a read on a half duplex (bi-directional SDA) SPI bus - sets MOSI to input void end_SDA_Read(void); // Restore MOSI to output #endif // Graphics drawing void fillScreen(uint32_t color), drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color), fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color); void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2); void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2); void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color), drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color), fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color), fillCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, int32_t delta, uint32_t color), drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color), fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color), // Corner 1 Corner 2 Corner 3 drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color), fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color); // Smooth (anti-aliased) graphics drawing // Draw a pixel blended with the background pixel colour (bg_color) specified, return blended colour // If the bg_color is not specified, the background pixel colour will be read from TFT or sprite uint16_t drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color = 0x00FFFFFF); // Draw an anti-aliased (smooth) arc between start and end angles. Arc ends are anti-aliased. // By default the arc is drawn with square ends unless the "roundEnds" parameter is included and set true // Angle = 0 is at 6 o'clock position, 90 at 9 o'clock etc. The angles must be in range 0-360 or they will be clipped to these limits // The start angle may be larger than the end angle. Arcs are always drawn clockwise from the start angle. void drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds = false); // As per "drawSmoothArc" except the ends of the arc are NOT anti-aliased, this facilitates dynamic arc length changes with // arc segments and ensures clean segment joints. // The sides of the arc are anti-aliased by default. If smoothArc is false sides will NOT be anti-aliased void drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool smoothArc = true); // Draw an anti-aliased filled circle at x, y with radius r // Note: The thickness of line is 3 pixels to reduce the visible "braiding" effect of anti-aliasing narrow lines // this means the inner anti-alias zone is always at r-1 and the outer zone at r+1 void drawSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t fg_color, uint32_t bg_color); // Draw an anti-aliased filled circle at x, y with radius r // If bg_color is not included the background pixel colour will be read from TFT or sprite void fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF); // Draw a rounded rectangle that has a line thickness of r-ir+1 and bounding box defined by x,y and w,h // The outer corner radius is r, inner corner radius is ir // The inside and outside of the border are anti-aliased void drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t w, int32_t h, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF, uint8_t quadrants = 0xF); // Draw a filled rounded rectangle , corner radius r and bounding box defined by x,y and w,h void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, uint32_t bg_color = 0x00FFFFFF); // Draw a small anti-aliased filled circle at ax,ay with radius r (uses drawWideLine) // If bg_color is not included the background pixel colour will be read from TFT or sprite void drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); // Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2) // If bg_color is not included the background pixel colour will be read from TFT or sprite void drawWideLine(float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); // Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with radiused ends // If bg_color is not included the background pixel colour will be read from TFT or sprite void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); // Image rendering // Swap the byte order for pushImage() and pushPixels() - corrects endianness void setSwapBytes(bool swap); bool getSwapBytes(void); // Draw bitmap void drawBitmap( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), drawBitmap( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), setBitmapColor(uint16_t fgcolor, uint16_t bgcolor); // Define the 2 colours for 1bpp sprites // Set TFT pivot point (use when rendering rotated sprites) void setPivot(int16_t x, int16_t y); int16_t getPivotX(void), // Get pivot x getPivotY(void); // Get pivot y // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location // Read a block of pixels to a data buffer, buffer is 16-bit and the size must be at least w * h void readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); // Write a block of pixels to the screen which have been read by readRect() void pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); // These are used to render images or sprites stored in RAM arrays (used by Sprite class for 16bpp Sprites) void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transparent); // These are used to render images stored in FLASH (PROGMEM) void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent); void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data); // These are used by Sprite class pushSprite() member function for 1, 4 and 8 bits per pixel (bpp) colours // They are not intended to be used with user sketches (but could be) // Set bpp8 true for 8bpp sprites, false otherwise. The cmap pointer must be specified for 4bpp void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8 = true, uint16_t *cmap = nullptr); void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true, uint16_t *cmap = nullptr); // FLASH version void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap = nullptr); // Render a 16-bit colour image with a 1bpp mask void pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask); // This next function has been used successfully to dump the TFT screen to a PC for documentation purposes // It reads a screen area and returns the 3 RGB 8-bit colour values of each pixel in the buffer // Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data); // Text rendering - value returned is the pixel width of the rendered text int16_t drawNumber(long intNumber, int32_t x, int32_t y, uint8_t font), // Draw integer using specified font number drawNumber(long intNumber, int32_t x, int32_t y), // Draw integer using current font // Decimal is the number of decimal places to render // Use with setTextDatum() to position values on TFT, and setTextPadding() to blank old displayed values drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y, uint8_t font), // Draw float using specified font number drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y), // Draw float using current font // Handle char arrays // Use with setTextDatum() to position string on TFT, and setTextPadding() to blank old displayed strings drawString(const char *string, int32_t x, int32_t y, uint8_t font), // Draw string using specified font number drawString(const char *string, int32_t x, int32_t y), // Draw string using current font drawString(const String& string, int32_t x, int32_t y, uint8_t font),// Draw string using specified font number drawString(const String& string, int32_t x, int32_t y), // Draw string using current font drawCentreString(const char *string, int32_t x, int32_t y, uint8_t font), // Deprecated, use setTextDatum() and drawString() drawRightString(const char *string, int32_t x, int32_t y, uint8_t font), // Deprecated, use setTextDatum() and drawString() drawCentreString(const String& string, int32_t x, int32_t y, uint8_t font),// Deprecated, use setTextDatum() and drawString() drawRightString(const String& string, int32_t x, int32_t y, uint8_t font); // Deprecated, use setTextDatum() and drawString() // Text rendering and font handling support functions void setCursor(int16_t x, int16_t y), // Set cursor for tft.print() setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print() int16_t getCursorX(void), // Read current cursor x position (moves with tft.print()) getCursorY(void); // Read current cursor y position void setTextColor(uint16_t color), // Set character (glyph) color only (background not over-written) setTextColor(uint16_t fgcolor, uint16_t bgcolor, bool bgfill = false), // Set character (glyph) foreground and background colour, optional background fill for smooth fonts setTextSize(uint8_t size); // Set character size multiplier (this increases pixel size) void setTextWrap(bool wrapX, bool wrapY = false); // Turn on/off wrapping of text in TFT width and/or height void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 5 above uint8_t getTextDatum(void); void setTextPadding(uint16_t x_width); // Set text padding (background blanking/over-write) width in pixels uint16_t getTextPadding(void); // Get text padding 给我添加中文备注,了解功能
09-14
我做了一个安卓画板app现在添加了一个从url下载图片并设置成画板背板的功能。我把代码给你看,在我输入了https://www.nottingham.edu.cn/image-library/campus-news/signofnottingham.jpg的网站后提示下载失败 /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cn.edu.nottingham.jianxingwang.fingerpainter; import android.content.ContentResolver; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.Button; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Stack; /** * Created by pszmdf on 13/10/16. * * Derived from android graphics API sample com.example.android.apis.graphics.Fingerpaint * android.googlesource.com/platform/development/+/master/samples/ApiDemos/src/com/example/android/apis/graphics/FingerPaint.java * */ public class FingerPainterView extends View { private Context context; private Canvas canvas; private Paint paint; private Bitmap bitmap; private Path path; private Uri uri; private Stack<Bitmap> undoStack = new
03-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值