📄 canvas.html
字号:
<html>
<head>
<title>Canvas</title>
<meta name="description" content="Reliable software Win32 Tutorial: Device Contexts">
<meta name="keywords" content="reliable, software, windows, cplusplus, source code, example, tutorial, canvas, graphics, DeviceContext, BeginPaint, GetDC">
</head>
<body background="../images/grid.gif" bgcolor="white" text="black">
<script language="JAVASCRIPT">
<!--
if (navigator.onLine){
document.write("<!-- Spidersoft WebZIP Ad Banner Insert -->");
document.write("<TABLE width=100% border=0 cellpadding=0 cellspacing=0>");
document.write("<TR>");
document.write("<TD>");
document.write("<ILAYER id=ad1 visibility=hidden height=60></ILAYER>");
document.write("<NOLAYER>");
document.write("<IFRAME SRC='http://www.spidersoft.com/ads/bwz468_60.htm' width=100% height=60 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no></IFRAME>");
document.write("</NOLAYER>");
document.write("</TD>");
document.write("</TR>");
document.write("</TABLE>");
document.write("<!-- End of Spidersoft WebZIP Ad Banner Insert-->");
}
//-->
</script>
<table cellpadding=10 width="100%">
<tr>
<td width=100 align=center valign=middle>
<a href="../index.htm">
<img src="../images/rsbullet.gif" alt="RS" border=0 width=39 height=39>
<br>Home</a>
<td><font face="arial" color="#009966">
<h1 align=center>Canvas, or Windows Device Context</h1>
</font>
</table>
<p>
<table width="100%">
<tr>
<td width=80> <!-- Left margin -->
<td> <!-- Middle column, there is also the right margin at the end -->
<table cellpadding=10 cellspacing=0 width="100%">
<tr>
<td bgcolor="#ffffff">
<hr>
<font size="+1"><b>To paint, draw or print</b></font> in a window you need a device context, DC for short. A DC is a resource that you borrow from Windows and you're supposed to return it immediately after you're done. That's where the Canvas object comes. The Canvas' constructor obtains the DC and the Canvas' destructor releases it. It is important that you create Canvas objects as autmatic (stack) variables. That will guarantee that their destructor is always called when the program exits the local scope where they are defined (this class is an example of a more general <a href="../resource/index.htm">Resource Management</a> methodology). The typical use of the Canvas object is as follows (as you've already seen in the Generic program):
<hr>
<pre><font face="courier">void <font color="#cc0066"><b>Controller::Paint</b></font> ()
{
<font color="#cc0066">// prepare the canvas and let View do the rest</font>
PaintCanvas canvas (_hwnd);
_view.Paint (canvas, _model);
<font color="#cc0066">// Notice: The destructor of PaintCanvas called automatically!</font>
}
</font></pre>
<hr>
All the various types of Canvas share the common ancestor-- the Canvas class. Notice that Canvas' constructor is protected. You can't actually instantiate an object of this class. However, the derived classes are free to provide their own constructors. By the way, you can keep adding new methods to Canvas as the need arises.
<hr>
<pre><font face="courier">class <font color="#cc0066"><b>Canvas</b></font>
{
public:
<font color="#cc0066">// operator cast to HDC
// (used when passing Canvas to Windows API)</font>
operator HDC () { return _hdc; }
void Point (int x, int y, COLORREF color)
{
::<font color="#000099"><b>SetPixel</b></font> (_hdc, x, y, color);
}
void MoveTo (int x, int y)
{
::<font color="#000099"><b>MoveToEx</b></font> (_hdc, x, y, 0);
}
void Line ( int x1, int y1, int x2, int y2 )
{
<font color="#000099"><b>MoveToEx</b></font> (_hdc, x1, y1, 0);
<font color="#000099"><b>LineTo</b></font> (_hdc, x2, y2);
}
void Rectangle (int left, int top, int right, int bottom)
{
<font color="#cc0066">// draw rectangle using current pen
// and fill it using current brush</font>
::<font color="#000099"><b>Rectangle</b></font> (_hdc, left, top, right, bottom);
}
void GetTextSize (int & cxChar, int & cyChar)
{
TEXTMETRIC tm;
<font color="#000099"><b>GetTextMetrics</b></font> (_hdc, & tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight + tm.tmExternalLeading;
}
void Text (int x, int y, char const * buf, int cBuf)
{
::<font color="#000099"><b>TextOut</b></font> ( _hdc, x, y, buf, cBuf );
}
void Char (int x, int y, char c)
{
<font color="#000099"><b>TextOut</b></font> (_hdc, x, y, & c, 1);
}
void SelectObject (void* pObj)
{
::<font color="#000099"><b>SelectObject</b></font> (_hdc, pObj);
}
protected:
Canvas (HDC hdc): _hdc (hdc) {}
HDC _hdc;
};
</font></pre>
<hr>
In response to the WM_PAINT message one should construct the PaintCanvas object. Notice the way PaintCanvas obtains and releases the DC.
<hr>
<pre><font face="courier">class <font color="#cc0066"><b>PaintCanvas</b></font>: public <font color="#cc0066"><b>Canvas</b></font>
{
public:
<font color="#cc0066">// Constructor obtains the DC</font>
PaintCanvas (HWND hwnd)
: Canvas (<font color="#000099"><b>BeginPaint</b></font> (hwnd, & _paint)),
_hwnd (hwnd)
{}
<font color="#cc0066">// Destructor releases the DC</font>
~PaintCanvas ()
{
<font color="#000099"><b>EndPaint</b></font> (_hwnd, & _paint);
}
protected:
PAINTSTRUCT _paint;
HWND _hwnd;
};
</font></pre>
<hr>
Another important example is the UpdateCanvas which is used for graphical operations outside of the context of WM_PAINT processing. Of course, your program may always force the repainting by calling <font face="courier" color="#000099"><b>InvalidateRect</b></font>, but in many cases it would be an overkill. If your program keeps painting new things as it executes or in response to user actions, you can update the window using UpdateCanvas.
<hr>
<pre><font face="courier">class <font color="#cc0066"><b>UpdateCanvas</b></font>: public <font color="#cc0066"><b>Canvas</b></font>
{
public:
UpdateCanvas (HWND hwnd)
: Canvas (<font color="#000099"><b>GetDC</b></font> (hwnd)),
_hwnd(hwnd)
{}
~UpdateCanvas ()
{
<font color="#000099"><b>ReleaseDC</b></font> (_hwnd, _hdc);
}
protected:
HWND _hwnd;
};
</font></pre>
<hr>
There are other types of Canvas: DrawItemCanvas used for owner-draw controls, MemCanvas for drawing on a piece of memory, etc.
<p>Use <a href="pens.html">pens and brushes</a> to draw and paint on your canvas.
<hr>
</table>
<td width=60>
</table>
<layer src="http://www.spidersoft.com/ads/bwz468_60.htm" visibility=hidden id=a1 width=600 onload="moveToAbsolute(ad1.pageX,ad1.pageY); a1.clip.height=60;visibility='show';"></layer>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -