当前位置:首页 > 操作系统 > Windows

windows GDI和GDI+对比小结

        <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>
            
windows hello world

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程序消息队列

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>
            
SetPixel原型

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> }
GDI+画线

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> }
GDI和GDI+画线区别
技术分享图片 技术分享图片
                <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+绘制矩形的后两个参数是高度、宽度和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);
双缓冲、内存DC解决闪烁

 

原文:https://www.cnblogs.com/yao2yaoblog/p/13208639.html


【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!

相关教程推荐

其他课程推荐