<span>目录结构<br />windows</span>
<br />
<span>1.windows hello world。</span>
<br />
<span>2.windows程序消息队列机制。<br />GDI<br />1.画一个点。<br />2.设备环境DC。<br />3.画线、矩形、圆角矩形、椭圆。<br />4.画笔。<br />5.画刷。<br />6.GDI对象还原。<br />GDI+<br />1.使用GDI+。<br />2.GDI和GDI+绘制对比。<br />3.GDI+渐变填充、位图填充。<br />内存DC<br /><br /></span>
<span>微软Windows子系统负责在称为图形设备接口(Graphics Device Interface, GDI)的视频显示器和打印机上显示图形。
——《Windows程序设计(第五版)》</span>
<strong>
<span>
<span> </span>
</span>
</strong>
GDI+是早期Windows版本中包括的图形设备接口GDI的继任者。GDI+将GDI的很多功能进行了优化,而且提供了新的附加功能。
——《精通GDI+编程》
1.windows程序运行hello world。只需要在vs下新建一个空项目,输入以下代码,即可出现hello world。
<span>
<span> 1</span> #include <Windows.h>
<span> 2</span><span> 3</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 4</span><span> 5</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 6</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span> 7</span><span>{
</span><span> 8</span><span> 9</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>10</span><span> WNDCLASS wndclass;
</span><span>11</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>12</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>13</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>14</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>15</span> wndclass.hInstance =<span> hInstance;
</span><span>16</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>17</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>18</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(BLACK_BRUSH);
</span><span>19</span> wndclass.lpszMenuName =<span> NULL;
</span><span>20</span> wndclass.lpszClassName =<span> szAppName;
</span><span>21</span><span>22</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>23</span><span> {
</span><span>24</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>25</span><span>return</span><span>0</span><span>;
</span><span>26</span><span> }
</span><span>27</span><span>28</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>29</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>30</span><span> WS_OVERLAPPEDWINDOW,
</span><span>31</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>32</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>33</span><span> NULL,
</span><span>34</span><span> NULL,
</span><span>35</span><span> hInstance,
</span><span>36</span><span> NULL);
</span><span>37</span><span>38</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>39</span><span> UpdateWindow(hwnd);
</span><span>40</span><span>41</span><span> MSG msg;
</span><span>42</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>43</span><span> {
</span><span>44</span> TranslateMessage(&<span>msg);
</span><span>45</span> DispatchMessage(&<span>msg);
</span><span>46</span><span> }
</span><span>47</span><span>return</span><span> msg.wParam;
</span><span>48</span><span>}
</span><span>49</span><span>50</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>51</span><span>{
</span><span>52</span><span> HDC hdc;
</span><span>53</span><span> PAINTSTRUCT ps;
</span><span>54</span> TCHAR text[<span>30</span><span>];
</span><span>55</span><span>switch</span><span> (msg)
</span><span>56</span><span> {
</span><span>57</span><span>case</span><span> WM_CREATE:
</span><span>58</span><span>return</span><span>0</span><span>;
</span><span>59</span><span>case</span><span> WM_PAINT:
</span><span>60</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>61</span> TextOut(hdc, <span>100</span>, <span>100</span>, text, wsprintf(text, TEXT(<span>"</span><span>HELLO WORLD</span><span>"</span><span>)));
</span><span>62</span> EndPaint(hwnd, &<span>ps);
</span><span>63</span><span>return</span><span>0</span><span>;
</span><span>64</span><span>case</span><span> WM_DESTROY:
</span><span>65</span> PostQuitMessage(<span>0</span><span>);
</span><span>66</span><span>return</span><span>0</span><span>;
</span><span>67</span><span> }
</span><span>68</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>69</span> }</span>
2.windows程序的运行本质是消息队列机制。
<span>
<span>1</span>
<span>MSG msg;
</span>
<span>2</span>
<span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>3</span><span> {
</span><span>4</span> TranslateMessage(&<span>msg);
</span><span>5</span> DispatchMessage(&<span>msg);
</span><span>6</span> }</span>
windows程序不停地检测消息队列中是否有新的消息,
while (GetMessage(&msg, NULL, 0, 0)),若消息队列中没有消息,则程序会阻塞;
若消息队列中有消息:
对于所有非WM_QUIT消息,GetMessage函数都将返回非零值,
而对WM_QUIT消息,GetMessage将返回0,则退出消息循环。
在此模型中,其实有两个队列。
一个是操作系统队列,事件发生时(比如按键盘的某个键),在操作系统的队列会插入一个相应的事件消息。
接着操作系统队列会把此消息传递给windows程序的消息队列。
GDI
1.首先我们往窗口上画一个点。
<span>
<span> 1</span> #include <Windows.h>
<span> 2</span><span> 3</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 4</span><span> 5</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 6</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span> 7</span><span>{
</span><span> 8</span><span> 9</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>10</span><span> WNDCLASS wndclass;
</span><span>11</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>12</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>13</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>14</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>15</span> wndclass.hInstance =<span> hInstance;
</span><span>16</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>17</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>18</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(BLACK_BRUSH);
</span><span>19</span> wndclass.lpszMenuName =<span> NULL;
</span><span>20</span> wndclass.lpszClassName =<span> szAppName;
</span><span>21</span><span>22</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>23</span><span> {
</span><span>24</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>25</span><span>return</span><span>0</span><span>;
</span><span>26</span><span> }
</span><span>27</span><span>28</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>29</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>30</span><span> WS_OVERLAPPEDWINDOW,
</span><span>31</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>32</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>33</span><span> NULL,
</span><span>34</span><span> NULL,
</span><span>35</span><span> hInstance,
</span><span>36</span><span> NULL);
</span><span>37</span><span>38</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>39</span><span> UpdateWindow(hwnd);
</span><span>40</span><span>41</span><span> MSG msg;
</span><span>42</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>43</span><span> {
</span><span>44</span> TranslateMessage(&<span>msg);
</span><span>45</span> DispatchMessage(&<span>msg);
</span><span>46</span><span> }
</span><span>47</span><span>return</span><span> msg.wParam;
</span><span>48</span><span>}
</span><span>49</span><span>50</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>51</span><span>{
</span><span>52</span><span> HDC hdc;
</span><span>53</span><span> PAINTSTRUCT ps;
</span><span>54</span><span>switch</span><span> (msg)
</span><span>55</span><span> {
</span><span>56</span><span>case</span><span> WM_CREATE:
</span><span>57</span><span>return</span><span>0</span><span>;
</span><span>58</span><span>case</span><span> WM_PAINT:
</span><span>59</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>60</span> SetPixel(hdc, <span>400</span>, <span>400</span>, <span>0x000000ff</span><span>);
</span><span>61</span> EndPaint(hwnd, &<span>ps);
</span><span>62</span><span>return</span><span>0</span><span>;
</span><span>63</span><span>case</span><span> WM_DESTROY:
</span><span>64</span> PostQuitMessage(<span>0</span><span>);
</span><span>65</span><span>return</span><span>0</span><span>;
</span><span>66</span><span> }
</span><span>67</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>68</span> }</span>
核心GDI函数是SetPixel,函数的参数列表依次是设备环境句柄,x,y坐标和颜色。
这里颜色是一个DWORD的数值。(0x00bbggrr,从右往左依次为rgb值,如红色是0x000000ff)
<span>
<span>1</span>
<span>COLORREF SetPixel(
</span>
<span>2</span>
<span> HDC hdc,
</span>
<span>3</span>
<span>int</span>
<span> X,
</span>
<span>4</span>
<span>int</span>
<span> Y,
</span>
<span>5</span>
<span> COLORREF crColor
</span>
<span>6</span> );</span>
2.设备环境DC
SetPixel写在WM_PAINT消息的处理中,WM_PAINT处理处有成对出现的
hdc = BeginPaint(hwnd, &ps);
// other code
EndPaint(hwnd, &ps);
这便是使用GDI函数时必经的一个步骤,获取设备环境句柄(HDC),可见GDI函数的参数列表中都有一个HDC。
除了在WM_PAINT中的BeginPaint和EndPaint,在非WM_PAINT消息中获取DC的常用方式还有:
hdc = GetDC(hwnd);
// other code
ReleaseDC(hwnd, hdc);
比如点击鼠标的时候画一个红点,此操作不在WM_PAINT消息中处理,在WM_LBUTTONDOWN消息中处理:
<span> 1</span> #include <Windows.h>
<span> 2</span><span> 3</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 4</span><span> 5</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 6</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span> 7</span><span>{
</span><span> 8</span><span> 9</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>10</span><span> WNDCLASS wndclass;
</span><span>11</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>12</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>13</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>14</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>15</span> wndclass.hInstance =<span> hInstance;
</span><span>16</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>17</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>18</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(BLACK_BRUSH);
</span><span>19</span> wndclass.lpszMenuName =<span> NULL;
</span><span>20</span> wndclass.lpszClassName =<span> szAppName;
</span><span>21</span><span>22</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>23</span><span> {
</span><span>24</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>25</span><span>return</span><span>0</span><span>;
</span><span>26</span><span> }
</span><span>27</span><span>28</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>29</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>30</span><span> WS_OVERLAPPEDWINDOW,
</span><span>31</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>32</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>33</span><span> NULL,
</span><span>34</span><span> NULL,
</span><span>35</span><span> hInstance,
</span><span>36</span><span> NULL);
</span><span>37</span><span>38</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>39</span><span> UpdateWindow(hwnd);
</span><span>40</span><span>41</span><span> MSG msg;
</span><span>42</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>43</span><span> {
</span><span>44</span> TranslateMessage(&<span>msg);
</span><span>45</span> DispatchMessage(&<span>msg);
</span><span>46</span><span> }
</span><span>47</span><span>return</span><span> msg.wParam;
</span><span>48</span><span>}
</span><span>49</span><span>50</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>51</span><span>{
</span><span>52</span><span> HDC hdc;
</span><span>53</span><span> PAINTSTRUCT ps;
</span><span>54</span><span>int</span> x = <span>0</span>, y = <span>0</span><span>;
</span><span>55</span><span>switch</span><span> (msg)
</span><span>56</span><span> {
</span><span>57</span><span>case</span><span> WM_CREATE:
</span><span>58</span><span>return</span><span>0</span><span>;
</span><span>59</span><span>case</span><span> WM_PAINT:
</span><span>60</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>61</span><span>//</span><span> SetPixel(hdc, 400, 400, 0x000000ff);</span><span>62</span> EndPaint(hwnd, &<span>ps);
</span><span>63</span><span>return</span><span>0</span><span>;
</span><span>64</span><span>case</span><span> WM_LBUTTONDOWN:
</span><span>65</span> hdc =<span> GetDC(hwnd);
</span><span>66</span> x =<span> LOWORD(lParam);
</span><span>67</span> y =<span> HIWORD(lParam);
</span><span>68</span> SetPixel(hdc, x, y, <span>0x000000ff</span><span>);
</span><span>69</span><span> ReleaseDC(hwnd, hdc);
</span><span>70</span><span>return</span><span>0</span><span>;
</span><span>71</span><span>case</span><span> WM_DESTROY:
</span><span>72</span> PostQuitMessage(<span>0</span><span>);
</span><span>73</span><span>return</span><span>0</span><span>;
</span><span>74</span><span> }
</span><span>75</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>76</span> }
有了以上的基础,接着可以来看下一些画线的GDI函数:
3.画线、矩形、圆角矩形、椭圆。
画直线MoveToEx,LineTo:
<span> 1</span> #include <Windows.h>
<span> 2</span><span> 3</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 4</span><span> 5</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 6</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span> 7</span><span>{
</span><span> 8</span><span> 9</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>10</span><span> WNDCLASS wndclass;
</span><span>11</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>12</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>13</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>14</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>15</span> wndclass.hInstance =<span> hInstance;
</span><span>16</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>17</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>18</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(WHITE_BRUSH);
</span><span>19</span> wndclass.lpszMenuName =<span> NULL;
</span><span>20</span> wndclass.lpszClassName =<span> szAppName;
</span><span>21</span><span>22</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>23</span><span> {
</span><span>24</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>25</span><span>return</span><span>0</span><span>;
</span><span>26</span><span> }
</span><span>27</span><span>28</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>29</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>30</span><span> WS_OVERLAPPEDWINDOW,
</span><span>31</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>32</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>33</span><span> NULL,
</span><span>34</span><span> NULL,
</span><span>35</span><span> hInstance,
</span><span>36</span><span> NULL);
</span><span>37</span><span>38</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>39</span><span> UpdateWindow(hwnd);
</span><span>40</span><span>41</span><span> MSG msg;
</span><span>42</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>43</span><span> {
</span><span>44</span> TranslateMessage(&<span>msg);
</span><span>45</span> DispatchMessage(&<span>msg);
</span><span>46</span><span> }
</span><span>47</span><span>return</span><span> msg.wParam;
</span><span>48</span><span>}
</span><span>49</span><span>50</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>51</span><span>{
</span><span>52</span><span> HDC hdc;
</span><span>53</span><span> PAINTSTRUCT ps;
</span><span>54</span><span>static</span><span>int</span> cxClient = <span>0</span>, cyClient = <span>0</span><span>;
</span><span>55</span><span>switch</span><span> (msg)
</span><span>56</span><span> {
</span><span>57</span><span>case</span><span> WM_CREATE:
</span><span>58</span><span>return</span><span>0</span><span>;
</span><span>59</span><span>case</span><span> WM_SIZE:
</span><span>60</span> cxClient =<span> LOWORD(lParam);
</span><span>61</span> cyClient =<span> HIWORD(lParam);
</span><span>62</span><span>return</span><span>0</span><span>;
</span><span>63</span><span>case</span><span> WM_PAINT:
</span><span>64</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>65</span> MoveToEx(hdc, <span>0</span>, cyClient / <span>2</span><span>, NULL);
</span><span>66</span> LineTo(hdc, cxClient, cyClient / <span>2</span><span>);
</span><span>67</span> EndPaint(hwnd, &<span>ps);
</span><span>68</span><span>return</span><span>0</span><span>;
</span><span>69</span><span>case</span><span> WM_LBUTTONDOWN:
</span><span>70</span><span>return</span><span>0</span><span>;
</span><span>71</span><span>case</span><span> WM_DESTROY:
</span><span>72</span> PostQuitMessage(<span>0</span><span>);
</span><span>73</span><span>return</span><span>0</span><span>;
</span><span>74</span><span> }
</span><span>75</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>76</span> }
画一个由多个点的数组组成的折线PolyLine:
<span> 1</span> #include <Windows.h>
<span> 2</span> #include <math.h>
<span> 3</span><span> 4</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 5</span><span> 6</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 7</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span> 8</span><span>{
</span><span> 9</span><span>10</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>11</span><span> WNDCLASS wndclass;
</span><span>12</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>13</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>14</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>15</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>16</span> wndclass.hInstance =<span> hInstance;
</span><span>17</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>18</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>19</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(WHITE_BRUSH);
</span><span>20</span> wndclass.lpszMenuName =<span> NULL;
</span><span>21</span> wndclass.lpszClassName =<span> szAppName;
</span><span>22</span><span>23</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>24</span><span> {
</span><span>25</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>26</span><span>return</span><span>0</span><span>;
</span><span>27</span><span> }
</span><span>28</span><span>29</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>30</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>31</span><span> WS_OVERLAPPEDWINDOW,
</span><span>32</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>33</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>34</span><span> NULL,
</span><span>35</span><span> NULL,
</span><span>36</span><span> hInstance,
</span><span>37</span><span> NULL);
</span><span>38</span><span>39</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>40</span><span> UpdateWindow(hwnd);
</span><span>41</span><span>42</span><span> MSG msg;
</span><span>43</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>44</span><span> {
</span><span>45</span> TranslateMessage(&<span>msg);
</span><span>46</span> DispatchMessage(&<span>msg);
</span><span>47</span><span> }
</span><span>48</span><span>return</span><span> msg.wParam;
</span><span>49</span><span>}
</span><span>50</span><span>51</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>52</span><span>{
</span><span>53</span><span> HDC hdc;
</span><span>54</span><span> PAINTSTRUCT ps;
</span><span>55</span><span>static</span><span>int</span> cxClient = <span>0</span>, cyClient = <span>0</span><span>;
</span><span>56</span><span>const</span><span>static</span><span>int</span> NUM = <span>1000</span><span>;
</span><span>57</span><span>const</span><span>static</span><span>float</span> TWOPI = <span>2</span> * <span>3.1415926</span><span>;
</span><span>58</span><span> POINT apt[NUM];
</span><span>59</span><span>switch</span><span> (msg)
</span><span>60</span><span> {
</span><span>61</span><span>case</span><span> WM_CREATE:
</span><span>62</span><span>return</span><span>0</span><span>;
</span><span>63</span><span>case</span><span> WM_SIZE:
</span><span>64</span> cxClient =<span> LOWORD(lParam);
</span><span>65</span> cyClient =<span> HIWORD(lParam);
</span><span>66</span><span>return</span><span>0</span><span>;
</span><span>67</span><span>case</span><span> WM_PAINT:
</span><span>68</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>69</span> MoveToEx(hdc, <span>0</span>, cyClient / <span>2</span><span>, NULL);
</span><span>70</span> LineTo(hdc, cxClient, cyClient / <span>2</span><span>);
</span><span>71</span><span>72</span><span>for</span> (<span>int</span> i = <span>0</span>; i < NUM; ++<span>i)
</span><span>73</span><span> {
</span><span>74</span> apt[i].x = i * cxClient /<span> NUM;
</span><span>75</span> apt[i].y = (<span>int</span>)(cyClient / <span>2</span> * (<span>1</span> - sin(TWOPI * i /<span> NUM)));
</span><span>76</span><span> }
</span><span>77</span><span>78</span><span> Polyline(hdc, apt, NUM);
</span><span>79</span> EndPaint(hwnd, &<span>ps);
</span><span>80</span><span>return</span><span>0</span><span>;
</span><span>81</span><span>case</span><span> WM_LBUTTONDOWN:
</span><span>82</span><span>return</span><span>0</span><span>;
</span><span>83</span><span>case</span><span> WM_DESTROY:
</span><span>84</span> PostQuitMessage(<span>0</span><span>);
</span><span>85</span><span>return</span><span>0</span><span>;
</span><span>86</span><span> }
</span><span>87</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>88</span> }
画一个矩形Rectangle,圆角矩形RoundRect,椭圆Ellipse:
<span> 1</span> #include <Windows.h>
<span> 2</span><span> 3</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 4</span><span> 5</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 6</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span> 7</span><span>{
</span><span> 8</span><span> 9</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>10</span><span> WNDCLASS wndclass;
</span><span>11</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>12</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>13</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>14</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>15</span> wndclass.hInstance =<span> hInstance;
</span><span>16</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>17</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>18</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(WHITE_BRUSH);
</span><span>19</span> wndclass.lpszMenuName =<span> NULL;
</span><span>20</span> wndclass.lpszClassName =<span> szAppName;
</span><span>21</span><span>22</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>23</span><span> {
</span><span>24</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>25</span><span>return</span><span>0</span><span>;
</span><span>26</span><span> }
</span><span>27</span><span>28</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>29</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>30</span><span> WS_OVERLAPPEDWINDOW,
</span><span>31</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>32</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>33</span><span> NULL,
</span><span>34</span><span> NULL,
</span><span>35</span><span> hInstance,
</span><span>36</span><span> NULL);
</span><span>37</span><span>38</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>39</span><span> UpdateWindow(hwnd);
</span><span>40</span><span>41</span><span> MSG msg;
</span><span>42</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>43</span><span> {
</span><span>44</span> TranslateMessage(&<span>msg);
</span><span>45</span> DispatchMessage(&<span>msg);
</span><span>46</span><span> }
</span><span>47</span><span>return</span><span> msg.wParam;
</span><span>48</span><span>}
</span><span>49</span><span>50</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>51</span><span>{
</span><span>52</span><span> HDC hdc;
</span><span>53</span><span> PAINTSTRUCT ps;
</span><span>54</span><span>static</span><span>int</span> cxClient = <span>0</span>, cyClient = <span>0</span><span>;
</span><span>55</span><span>switch</span><span> (msg)
</span><span>56</span><span> {
</span><span>57</span><span>case</span><span> WM_CREATE:
</span><span>58</span><span>return</span><span>0</span><span>;
</span><span>59</span><span>case</span><span> WM_SIZE:
</span><span>60</span> cxClient =<span> LOWORD(lParam);
</span><span>61</span> cyClient =<span> HIWORD(lParam);
</span><span>62</span><span>return</span><span>0</span><span>;
</span><span>63</span><span>case</span><span> WM_PAINT:
</span><span>64</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>65</span><span>66</span> Rectangle(hdc, cxClient / <span>8</span>, cyClient / <span>8</span>, <span>7</span> * cxClient / <span>8</span>, <span>7</span> * cyClient / <span>8</span><span>);
</span><span>67</span> Ellipse(hdc, cxClient / <span>8</span>, cyClient / <span>8</span>, <span>7</span> * cxClient / <span>8</span>, <span>7</span> * cyClient / <span>8</span><span>);
</span><span>68</span> RoundRect(hdc, cxClient / <span>4</span>, cyClient / <span>4</span>, <span>3</span> * cxClient / <span>4</span>, <span>3</span> * cyClient / <span>4</span>, cxClient / <span>4</span>, cyClient / <span>4</span><span>);
</span><span>69</span><span>70</span> EndPaint(hwnd, &<span>ps);
</span><span>71</span><span>return</span><span>0</span><span>;
</span><span>72</span><span>case</span><span> WM_LBUTTONDOWN:
</span><span>73</span><span>return</span><span>0</span><span>;
</span><span>74</span><span>case</span><span> WM_DESTROY:
</span><span>75</span> PostQuitMessage(<span>0</span><span>);
</span><span>76</span><span>return</span><span>0</span><span>;
</span><span>77</span><span> }
</span><span>78</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>79</span> }
还有其余的用法都是类似,有需要去查msdn就行。
4.画笔
前面画线使用的都是默认的画笔。Windows提供了三种备用画笔:WHITE_PEN,BLACK_PEN,NULL_PEN。
如果想要其他类型的画笔,则需要自己创建,使用CreatePen或CreatePenIndirect。
还是前面的画矩形、画圆角矩形、画椭圆的例子。这次用绿色的虚线来画。
<span> 1</span> #include <Windows.h>
<span> 2</span><span> 3</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 4</span><span> 5</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 6</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span> 7</span><span>{
</span><span> 8</span><span> 9</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>10</span><span> WNDCLASS wndclass;
</span><span>11</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>12</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>13</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>14</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>15</span> wndclass.hInstance =<span> hInstance;
</span><span>16</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>17</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>18</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(WHITE_BRUSH);
</span><span>19</span> wndclass.lpszMenuName =<span> NULL;
</span><span>20</span> wndclass.lpszClassName =<span> szAppName;
</span><span>21</span><span>22</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>23</span><span> {
</span><span>24</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>25</span><span>return</span><span>0</span><span>;
</span><span>26</span><span> }
</span><span>27</span><span>28</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>29</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>30</span><span> WS_OVERLAPPEDWINDOW,
</span><span>31</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>32</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>33</span><span> NULL,
</span><span>34</span><span> NULL,
</span><span>35</span><span> hInstance,
</span><span>36</span><span> NULL);
</span><span>37</span><span>38</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>39</span><span> UpdateWindow(hwnd);
</span><span>40</span><span>41</span><span> MSG msg;
</span><span>42</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>43</span><span> {
</span><span>44</span> TranslateMessage(&<span>msg);
</span><span>45</span> DispatchMessage(&<span>msg);
</span><span>46</span><span> }
</span><span>47</span><span>return</span><span> msg.wParam;
</span><span>48</span><span>}
</span><span>49</span><span>50</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>51</span><span>{
</span><span>52</span><span> HDC hdc;
</span><span>53</span><span> PAINTSTRUCT ps;
</span><span>54</span><span>static</span><span>int</span> cxClient = <span>0</span>, cyClient = <span>0</span><span>;
</span><span>55</span><span>static</span><span> HPEN hPen;
</span><span>56</span><span>switch</span><span> (msg)
</span><span>57</span><span> {
</span><span>58</span><span>case</span><span> WM_CREATE:
</span><span>59</span><span>return</span><span>0</span><span>;
</span><span>60</span><span>case</span><span> WM_SIZE:
</span><span>61</span> cxClient =<span> LOWORD(lParam);
</span><span>62</span> cyClient =<span> HIWORD(lParam);
</span><span>63</span><span>return</span><span>0</span><span>;
</span><span>64</span><span>case</span><span> WM_PAINT:
</span><span>65</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>66</span> hPen = CreatePen(PS_DASH, <span>1</span>, <span>0x0000ff00</span><span>);
</span><span>67</span><span> SelectObject(hdc, hPen);
</span><span>68</span> Rectangle(hdc, cxClient / <span>8</span>, cyClient / <span>8</span>, <span>7</span> * cxClient / <span>8</span>, <span>7</span> * cyClient / <span>8</span><span>);
</span><span>69</span> Ellipse(hdc, cxClient / <span>8</span>, cyClient / <span>8</span>, <span>7</span> * cxClient / <span>8</span>, <span>7</span> * cyClient / <span>8</span><span>);
</span><span>70</span> RoundRect(hdc, cxClient / <span>4</span>, cyClient / <span>4</span>, <span>3</span> * cxClient / <span>4</span>, <span>3</span> * cyClient / <span>4</span>, cxClient / <span>4</span>, cyClient / <span>4</span><span>);
</span><span>71</span><span> DeleteObject(hPen);
</span><span>72</span> EndPaint(hwnd, &<span>ps);
</span><span>73</span><span>return</span><span>0</span><span>;
</span><span>74</span><span>case</span><span> WM_LBUTTONDOWN:
</span><span>75</span><span>return</span><span>0</span><span>;
</span><span>76</span><span>case</span><span> WM_DESTROY:
</span><span>77</span> PostQuitMessage(<span>0</span><span>);
</span><span>78</span><span>return</span><span>0</span><span>;
</span><span>79</span><span> }
</span><span>80</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>81</span> }
创建了画笔要记得删除画笔。
hPen = CreatePen(PS_DASH, 1, 0x0000ff00);
SelectObject(hdc, hPen);
// other code
DeleteObject(hPen);
5.画刷。
前面类似圆角矩形的区域,用到的画刷都是默认的画刷。Windows提供了6种备用画刷。
如果想要给一片区域填充某一种颜色,比如一片绿色的圆角矩形区域。此时用到画刷。
<span> 1</span> #include <Windows.h>
<span> 2</span><span> 3</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 4</span><span> 5</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 6</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span> 7</span><span>{
</span><span> 8</span><span> 9</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>10</span><span> WNDCLASS wndclass;
</span><span>11</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>12</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>13</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>14</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>15</span> wndclass.hInstance =<span> hInstance;
</span><span>16</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>17</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>18</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(WHITE_BRUSH);
</span><span>19</span> wndclass.lpszMenuName =<span> NULL;
</span><span>20</span> wndclass.lpszClassName =<span> szAppName;
</span><span>21</span><span>22</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>23</span><span> {
</span><span>24</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>25</span><span>return</span><span>0</span><span>;
</span><span>26</span><span> }
</span><span>27</span><span>28</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>29</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>30</span><span> WS_OVERLAPPEDWINDOW,
</span><span>31</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>32</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>33</span><span> NULL,
</span><span>34</span><span> NULL,
</span><span>35</span><span> hInstance,
</span><span>36</span><span> NULL);
</span><span>37</span><span>38</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>39</span><span> UpdateWindow(hwnd);
</span><span>40</span><span>41</span><span> MSG msg;
</span><span>42</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>43</span><span> {
</span><span>44</span> TranslateMessage(&<span>msg);
</span><span>45</span> DispatchMessage(&<span>msg);
</span><span>46</span><span> }
</span><span>47</span><span>return</span><span> msg.wParam;
</span><span>48</span><span>}
</span><span>49</span><span>50</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>51</span><span>{
</span><span>52</span><span> HDC hdc;
</span><span>53</span><span> PAINTSTRUCT ps;
</span><span>54</span><span>static</span><span>int</span> cxClient = <span>0</span>, cyClient = <span>0</span><span>;
</span><span>55</span><span>static</span><span> HBRUSH hBrush;
</span><span>56</span><span>switch</span><span> (msg)
</span><span>57</span><span> {
</span><span>58</span><span>case</span><span> WM_CREATE:
</span><span>59</span><span>return</span><span>0</span><span>;
</span><span>60</span><span>case</span><span> WM_SIZE:
</span><span>61</span> cxClient =<span> LOWORD(lParam);
</span><span>62</span> cyClient =<span> HIWORD(lParam);
</span><span>63</span><span>return</span><span>0</span><span>;
</span><span>64</span><span>case</span><span> WM_PAINT:
</span><span>65</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>66</span> hBrush = CreateSolidBrush(<span>0x0000ff00</span><span>);
</span><span>67</span><span> SelectObject(hdc, hBrush);
</span><span>68</span> RoundRect(hdc, cxClient / <span>4</span>, cyClient / <span>4</span>, <span>3</span> * cxClient / <span>4</span>, <span>3</span> * cyClient / <span>4</span>, cxClient / <span>4</span>, cyClient / <span>4</span><span>);
</span><span>69</span><span> DeleteObject(hBrush);
</span><span>70</span> EndPaint(hwnd, &<span>ps);
</span><span>71</span><span>return</span><span>0</span><span>;
</span><span>72</span><span>case</span><span> WM_LBUTTONDOWN:
</span><span>73</span><span>return</span><span>0</span><span>;
</span><span>74</span><span>case</span><span> WM_DESTROY:
</span><span>75</span> PostQuitMessage(<span>0</span><span>);
</span><span>76</span><span>return</span><span>0</span><span>;
</span><span>77</span><span> }
</span><span>78</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>79</span> }
注意到也使用了SelectObject这个函数,此时可以把GDI对象关联到设备。
一个程序可以创建6个GDI对象,分别是画笔,画刷,位图,区域,字体和调色板。
6.还原GDI对象。
当使用了一种新的GDI对象后,希望还原原有的GDI环境,应该如何做呢?
SelectObject返回值是旧的GDI对象,因此可以设置新GDI对象的时候将旧的GDI对象记录下来。
HPen hOldPen = (HPen)SelectObject(hdc, hPen);
最后删除新GDI环境之前,再把旧的GDI对象选入环境。
SelectObject(hdc, hOldPen);
GDI+
GDI+用一个“无状态模型”取代了GDI种把选中项目放到设备环境(DC)对象上的“状态模型”,
在GDI+种的每一个绘图操作都是相互独立的。图形对象(Graphics object)是绘图操作种唯一保留的对象。
1.使用GDI+的方法。
1)头文件引入#include <gdiplus.h>。
2)项目附加依赖项gdiplus.lib。
3)在程序开始时初始化GDI+环境。
ULONG_PTR uToken = 0;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&uToken, &gdiplusStartupInput, NULL);
4)在程序结束时释放GDI+环境。
GdiplusShutdown(uToken);
2.GDI和GDI+的绘制对比。
有了以上的准备,直接来看画一条线的方法:
<span> 1</span> #include <Windows.h>
<span> 2</span> #include <gdiplus.h>
<span> 3</span><span> 4</span><span>using</span><span>namespace</span><span> Gdiplus;
</span><span> 5</span><span> 6</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
</span><span> 7</span><span> 8</span><span>int</span><span> WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
</span><span> 9</span> PSTR szCmdLine, <span>int</span><span> iCmdShow)
</span><span>10</span><span>{
</span><span>11</span><span>12</span> ULONG_PTR uToken = <span>0</span><span>;
</span><span>13</span><span> GdiplusStartupInput gdiplusStartupInput;
</span><span>14</span> GdiplusStartup(&uToken, &<span>gdiplusStartupInput, NULL);
</span><span>15</span><span>16</span> TCHAR szAppName[] = TEXT(<span>"</span><span>Hello</span><span>"</span><span>);
</span><span>17</span><span> WNDCLASS wndclass;
</span><span>18</span> wndclass.style = CS_HREDRAW |<span> CS_VREDRAW;
</span><span>19</span> wndclass.lpfnWndProc =<span> WndProc;
</span><span>20</span> wndclass.cbClsExtra = <span>0</span><span>;
</span><span>21</span> wndclass.cbWndExtra = <span>0</span><span>;
</span><span>22</span> wndclass.hInstance =<span> hInstance;
</span><span>23</span> wndclass.hIcon =<span> LoadIcon(NULL, IDI_APPLICATION);
</span><span>24</span> wndclass.hCursor =<span> LoadCursor(NULL, IDC_ARROW);
</span><span>25</span> wndclass.hbrBackground =<span> (HBRUSH)GetStockObject(WHITE_BRUSH);
</span><span>26</span> wndclass.lpszMenuName =<span> NULL;
</span><span>27</span> wndclass.lpszClassName =<span> szAppName;
</span><span>28</span><span>29</span><span>if</span> (!RegisterClass(&<span>wndclass))
</span><span>30</span><span> {
</span><span>31</span> MessageBox(NULL, TEXT(<span>"</span><span>error</span><span>"</span><span>), szAppName, MB_ICONERROR);
</span><span>32</span><span>return</span><span>0</span><span>;
</span><span>33</span><span> }
</span><span>34</span><span>35</span> HWND hwnd =<span> CreateWindow(szAppName,
</span><span>36</span> TEXT(<span>"</span><span>Hello</span><span>"</span><span>),
</span><span>37</span><span> WS_OVERLAPPEDWINDOW,
</span><span>38</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>39</span><span> CW_USEDEFAULT, CW_USEDEFAULT,
</span><span>40</span><span> NULL,
</span><span>41</span><span> NULL,
</span><span>42</span><span> hInstance,
</span><span>43</span><span> NULL);
</span><span>44</span><span>45</span><span> ShowWindow(hwnd, iCmdShow);
</span><span>46</span><span> UpdateWindow(hwnd);
</span><span>47</span><span>48</span><span> MSG msg;
</span><span>49</span><span>while</span> (GetMessage(&msg, NULL, <span>0</span>, <span>0</span><span>))
</span><span>50</span><span> {
</span><span>51</span> TranslateMessage(&<span>msg);
</span><span>52</span> DispatchMessage(&<span>msg);
</span><span>53</span><span> }
</span><span>54</span><span>55</span><span> GdiplusShutdown(uToken);
</span><span>56</span><span>return</span><span> msg.wParam;
</span><span>57</span><span>}
</span><span>58</span><span>59</span><span>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
</span><span>60</span><span>{
</span><span>61</span><span> HDC hdc;
</span><span>62</span><span> PAINTSTRUCT ps;
</span><span>63</span><span>static</span><span>int</span> cxClient = <span>0</span>, cyClient = <span>0</span><span>;
</span><span>64</span><span>65</span><span>switch</span><span> (msg)
</span><span>66</span><span> {
</span><span>67</span><span>case</span><span> WM_CREATE:
</span><span>68</span><span>return</span><span>0</span><span>;
</span><span>69</span><span>case</span><span> WM_SIZE:
</span><span>70</span> cxClient =<span> LOWORD(lParam);
</span><span>71</span> cyClient =<span> HIWORD(lParam);
</span><span>72</span><span>return</span><span>0</span><span>;
</span><span>73</span><span>case</span><span> WM_PAINT:
</span><span>74</span><span> {
</span><span>75</span> hdc = BeginPaint(hwnd, &<span>ps);
</span><span>76</span><span> Graphics graphics(hdc);
</span><span>77</span> Pen greenPen(Color(<span>255</span>, <span>0</span>, <span>255</span>, <span>0</span><span>));
</span><span>78</span> graphics.DrawLine(&greenPen, <span>0</span>, cyClient / <span>2</span>, cxClient, cyClient / <span>2</span><span>);
</span><span>79</span><span>80</span> EndPaint(hwnd, &<span>ps);
</span><span>81</span><span> }
</span><span>82</span><span>return</span><span>0</span><span>;
</span><span>83</span><span>case</span><span> WM_LBUTTONDOWN:
</span><span>84</span><span>return</span><span>0</span><span>;
</span><span>85</span><span>case</span><span> WM_DESTROY:
</span><span>86</span> PostQuitMessage(<span>0</span><span>);
</span><span>87</span><span>return</span><span>0</span><span>;
</span><span>88</span><span> }
</span><span>89</span><span>90</span><span>91</span><span>return</span><span> DefWindowProc(hwnd, msg, wParam, lParam);
</span><span>92</span> }
Graphics graphics(hdc);
Pen greenPen(Color(255, 0, 255, 0));
graphics.DrawLine(&greenPen, 0, cyClient / 2, cxClient, cyClient / 2);
无需再像GDI一样,将画笔选入设备环境,而是直接用Graphics对象的对应函数,画笔也是函数的一个参数。
为了让代码更清晰,把画线、画矩形单独写成一个函数,传入一个hdc。
以下是使用GDI绘制和使用GDI+绘制的各种对比。
<span> 1</span>
<span>void</span>
<span> paintLine(HDC hdc)
</span>
<span> 2</span>
<span>{
</span>
<span> 3</span>
<span>//</span>
<span> GDI</span>
<span> 4</span> HPEN hPen = CreatePen(PS_SOLID, <span>1</span>, <span>0x0000ff00</span><span>);
</span><span> 5</span> HPEN hOldPen =<span> (HPEN)SelectObject(hdc, hPen);
</span><span> 6</span> MoveToEx(hdc, <span>0</span>, cyClient / <span>2</span><span>, NULL);
</span><span> 7</span> LineTo(hdc, cxClient, cyClient / <span>2</span><span>);
</span><span> 8</span><span> DeleteObject(hPen);
</span><span> 9</span><span> SelectObject(hdc, hOldPen);
</span><span>10</span><span>11</span><span>//</span><span> GDI+</span><span>12</span><span> Graphics graphics(hdc);
</span><span>13</span> Pen greenPen(Color(<span>255</span>, <span>0</span>, <span>255</span>, <span>0</span><span>));
</span><span>14</span> graphics.DrawLine(&greenPen, <span>0</span>, cyClient / <span>2</span>, cxClient, cyClient / <span>2</span><span>);
</span><span>15</span> }
<span> 1</span>
<span>void</span>
<span> paintRec(HDC hdc)
</span>
<span> 2</span>
<span>{
</span>
<span> 3</span>
<span>//</span>
<span> GDI</span>
<span> 4</span> HBRUSH hBrush = CreateSolidBrush(<span>0x0000ff00</span><span>);
</span><span> 5</span> HBRUSH hOldBrush =<span> (HBRUSH)SelectObject(hdc, hBrush);
</span><span> 6</span><span> 7</span> Rectangle(hdc, cxClient / <span>8</span>, cyClient / <span>8</span>, <span>7</span> * cxClient / <span>8</span>, <span>7</span> * cyClient / <span>8</span><span>);
</span><span> 8</span><span> 9</span><span> DeleteObject(hBrush);
</span><span>10</span><span> SelectObject(hdc, hOldBrush);
</span><span>11</span><span>12</span><span>//</span><span> GDI+</span><span>13</span><span> Graphics graphics(hdc);
</span><span>14</span> Pen blackPen(Color(<span>255</span>, <span>0</span>, <span>0</span>, <span>0</span><span>));
</span><span>15</span> SolidBrush greenBrush(Color(<span>255</span>, <span>0</span>, <span>255</span>, <span>0</span><span>));
</span><span>16</span> graphics.DrawRectangle(&blackPen, Rect(cxClient / <span>8</span>, cyClient / <span>8</span>, <span>6</span> * cxClient / <span>8</span>, <span>6</span> * cyClient / <span>8</span><span>));
</span><span>17</span> graphics.FillRectangle(&greenBrush, Rect(cxClient / <span>8</span> + <span>1</span>, cyClient / <span>8</span> + <span>1</span>, <span>6</span> * cxClient / <span>8</span> - <span>1</span>, <span>6</span> * cyClient / <span>8</span> - <span>1</span><span>));
</span><span>18</span> }
GDI+绘制矩形的后两个参数是高度、宽度和GDI的决定坐标有区别。
另外GDI+填充用的是Fill系列的函数,想要达到和GDI一样的效果需要考虑边框的一个像素。
3.GDI+的渐变画刷。
GDI+实现了一个渐变画刷,这在GDI是没有的。
<span>1</span>
<span>Graphics graphics(hdc);
</span>
<span>2</span> LinearGradientBrush linearBrush(Point(cxClient / <span>8</span>, cyClient / <span>8</span>), Point(<span>7</span> * cxClient / <span>8</span>, <span>7</span> * cyClient / <span>8</span>), Color(<span>255</span>, <span>0</span>, <span>0</span>, <span>255</span>), Color(<span>255</span>, <span>255</span>, <span>0</span>, <span>0</span><span>));
</span><span>3</span> graphics.FillRectangle(&linearBrush, Rect(cxClient / <span>8</span> + <span>1</span>, cyClient / <span>8</span> + <span>1</span>, <span>6</span> * cxClient / <span>8</span> - <span>1</span>, <span>6</span> * cyClient / <span>8</span> - <span>1</span>));
内存DC
当需要绘制的图形、位图过多时,屏幕可能出现闪烁问题。
原因是WM_PAINT消息中每次绘制都是直接往目标DC绘制,有大量操作。
可以首先创建一个内存DC,一个位图选入此内存DC,所需绘制的内容先在新建的内存DC中绘制,再最后一次拷贝到目标DC。
此操作可称为双缓冲。
<span> 1</span> HDC hMemDc =<span> CreateCompatibleDC(hdc);
</span><span> 2</span> HBITMAP hbitmap =<span> CreateCompatibleBitmap(hdc, cxClient, cyClient);
</span><span> 3</span> HBITMAP hOldBitmap =<span> (HBITMAP)SelectObject(hMemDc, hbitmap);
</span><span> 4</span><span> 5</span><span>//</span><span> paint code</span><span> 6</span><span>paintLine(hMemDc);
</span><span> 7</span><span>paintRec(hMemDc);
</span><span> 8</span><span>paintEllipse(hMemDc);
</span><span> 9</span><span>paintRoundRec(hMemDc);
</span><span>10</span><span>11</span> BitBlt(hdc, <span>0</span>, <span>0</span>, cxClient, cyClient, hMemDc, <span>0</span>, <span>0</span><span>, SRCCOPY);
</span><span>12</span><span>SelectObject(hMemDc, hOldBitmap);
</span><span>13</span><span>DeleteObject(hbitmap);
</span><span>14</span> DeleteDC(hMemDc);
原文:https://www.cnblogs.com/yao2yaoblog/p/13208639.html
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!