我们今天继续涂鸦,实践证明,涂鸦是人生一大乐趣。

首先,我们写一个程序骨架子,以便做实验。

  1. #include <Windows.h>
  2. LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  3. int WINAPI WinMain(
  4. HINSTANCE hThisApp,
  5. HINSTANCE hPrevApp,
  6. LPSTR lpsCmdln,
  7. int iShow)
  8. {
  9. WNDCLASS wc;
  10. wc.cbClsExtra = 0;
  11. wc.cbWndExtra = 0;
  12. wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));
  13. // 默认光标类型为箭头
  14. wc.hCursor = LoadCursor(hThisApp, IDC_ARROW);
  15. // 默认应用程序图标
  16. wc.hIcon = LoadIcon(hThisApp, IDI_APPLICATION);
  17. wc.hInstance = hThisApp;
  18. wc.lpfnWndProc = MainWinProc;
  19. wc.lpszClassName = L"MyAppTest";
  20. wc.lpszMenuName = NULL;
  21. wc.style = CS_HREDRAW | CS_VREDRAW;
  22. // 注册窗口类
  23. RegisterClass(&wc);
  24. // 创建窗口
  25. HWND hwnd = CreateWindow(
  26. L"MyAppTest",
  27. L"绘画课",
  28. /* 使用 WS_VISIBLE 就不用调用ShowWindow了 */
  29. WS_VISIBLE | WS_OVERLAPPEDWINDOW,
  30. 100,
  31. 45,
  32. 500,
  33. 380,
  34. NULL,
  35. NULL,
  36. hThisApp,
  37. NULL);
  38. // 消息循环
  39. MSG msg;
  40. while(GetMessage(&msg, NULL, 0, 0))
  41. {
  42. TranslateMessage(&msg);
  43. DispatchMessage(&msg);
  44. }
  45. return 0;
  46. }
  47. LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  48. {
  49. switch(msg)
  50. {
  51. case WM_DESTROY:
  52. PostQuitMessage(0);
  53. return 0;
  54. case WM_PAINT:
  55. PAINTSTRUCT ps;
  56. BeginPaint(hwnd, &ps);
  57. /*
  58. 待实现
  59. */
  60. EndPaint(hwnd, &ps);
  61. return 0;
  62. }
  63. return DefWindowProc(hwnd, msg, wParam, lParam);
  64. }

CreatePen函数

我们要进行素描画创作,所以我们必须想清楚要使用什么样的钢笔,画出什么样的线条。故,画图之前得创建一支钢笔,不然,巧妇难为无米之炊。

  1. HPEN  CreatePen(
  2. int iStyle, //钢笔的样式,如虚线、实线
  3. int cWidth, //线条宽度
  4. COLORREF color //线条是啥颜色的
  5. );

第一个参数指定线条的样式,如

  1. /* Pen Styles */
  2. #define PS_SOLID            0
  3. #define PS_DASH             1       /* -------  */
  4. #define PS_DOT              2       /* .......  */
  5. #define PS_DASHDOT          3       /* _._._._  */
  6. #define PS_DASHDOTDOT       4       /* _.._.._  */
  7. #define PS_NULL             5
  8. #define PS_INSIDEFRAME      6
  9. #define PS_USERSTYLE        7
  10. #define PS_ALTERNATE        8

函数成功创建钢笔后就会返回HPEN,H开头的你就要知道它表示句柄。Pen也是系统资源,所以创建笔后系统要为它一个标识。

SelectObject函数

上过美术课,你会知道,有了用于进行素描创作的钢笔还不能动手干活,我们还需要有纸。接下来,调用SelectObject函数,把刚才创建的钢笔与绘图纸关联,就等于把我们创建的绘图资源放进DC工具箱中,

  1. HGDIOBJ WINAPI SelectObject(
  2. HDC hdc, //设备描述表的句柄
  3. HGDIOBJ h //要放到DC中的资源的句柄
  4. );

调用成功后,返回原先的资源句柄。

MoveToEx和LineTo

MoveToEx是设置绘制的起点,下次绘图将从这个点开始。它的最后一个参数将被设置为当前点,即Move后的坐标。LineTo从当前坐标开始,到指定坐标之间绘制一条线段。

  1. // 创建钢笔
  2. HPEN pen = CreatePen(PS_DASH, 1, RGB(0,255,50));
  3. // 把笔选到DC中
  4. SelectObject(ps.hdc, pen);
  5. // 设定线段的起点
  6. MoveToEx(ps.hdc, 15, 25, NULL);
  7. // 绘制线条
  8. LineTo(ps.hdc, 65, 49);
  9. LineTo(ps.hdc, 12, 120);
  10. LineTo(ps.hdc, 250, 78);
  11. LineTo(ps.hdc, 312, 185);
  12. DeleteObject(pen);

记住,只要是我们创建的句柄,用完后调用DeleteObject函数将其销毁。

PolyBezier函数和PolyBezierTo函数

两个函数都是用来绘制贝塞尔曲线的,不同的是,PolyBezier函数包含指定的起点和终点,PolyBezierTo是从当前点开始绘制贝塞尔曲线。

  1. // 绘制贝塞尔曲线
  2. pen = CreatePen(PS_DOT, 1, RGB(0,3,255));
  3. SelectObject(ps.hdc, pen);
  4. POINT* pts = new POINT[4];
  5. pts[0].x = 421;
  6. pts[0].y = 16;
  7. pts[1].x = 7;
  8. pts[1].y = 197;
  9. pts[2].x = 480;
  10. pts[2].y = 320;
  11. pts[3].x = 30;
  12. pts[3].y = 350;
  13. PolyBezier(ps.hdc, pts, 4);
  14. delete [] pts;
  15. // 第二段贝塞尔曲线
  16. POINT* pts2 = new POINT[3];
  17. pts2[0].x = 176;
  18. pts2[0].y = 84;
  19. pts2[1].x = 17;
  20. pts2[1].y = 247;
  21. pts2[2].x = 400;
  22. pts2[2].y = 490;
  23. // 移动当前点
  24. MoveToEx(ps.hdc, 395, 270, NULL);
  25. PolyBezierTo(ps.hdc, pts2, 3);
  26. delete [] pts2;

PolyPolyline绘制复合线条

PolyPolyline函数可以绘制多段复合线条。它的声明如下:

  1. BOOL PolyPolyline(
  2. HDC hdc,
  3. const POINT *lppt,
  4. const DWORD *lpdwPolyPoints,
  5. DWORD cCount
  6. );

lppt参数指向一个POINT的数组,它包含绘制复合线条所需的所有点;lpdwPolyPoints指向一个数组,这个数字数组指明如何分配点数组。

例如,lppt有7个点,我计划,前2个点绘制第一条线,接着3个点绘制第二条线,最后2个点绘制第三条线,这样一来,lpdwPolyPolyPoints得值应为:

{  2, 3, 2 }

nCount里包含lpdwPolyPolyPoints中的数量,我们上面的例子是3.

由于两点决定一条线段,因此,lpdwPolyPolyPoints里面的值记得要>=2。

  1. // 复杂图形
  2. pen = CreatePen(PS_DASHDOTDOT, 1, RGB(80,20,160));
  3. SelectObject(ps.hdc, pen);
  4. POINT plpts[10] =
  5. {
  6. {47,3}, {11,46}, {28,199}, {203,305}, {94,22},
  7. {402,377}, {21,45}, {237,7}, {300,398}, {175,25}
  8. };
  9. DWORD arr[4] = { 2, 3, 3, 2};
  10. PolyPolyline(ps.hdc, &plpts[0], &arr[0], 4);

上面的代码将画出以下图形。

完整的代码清单如下:

    1. #include <Windows.h>
    2. LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    3. int WINAPI WinMain(
    4. HINSTANCE hThisApp,
    5. HINSTANCE hPrevApp,
    6. LPSTR lpsCmdln,
    7. int iShow)
    8. {
    9. WNDCLASS wc;
    10. wc.cbClsExtra = 0;
    11. wc.cbWndExtra = 0;
    12. wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));
    13. // 默认光标类型为箭头
    14. wc.hCursor = LoadCursor(hThisApp, IDC_ARROW);
    15. // 默认应用程序图标
    16. wc.hIcon = LoadIcon(hThisApp, IDI_APPLICATION);
    17. wc.hInstance = hThisApp;
    18. wc.lpfnWndProc = MainWinProc;
    19. wc.lpszClassName = L"MyAppTest";
    20. wc.lpszMenuName = NULL;
    21. wc.style = CS_HREDRAW | CS_VREDRAW;
    22. // 注册窗口类
    23. RegisterClass(&wc);
    24. // 创建窗口
    25. HWND hwnd = CreateWindow(
    26. L"MyAppTest",
    27. L"绘画课",
    28. /* 使用 WS_VISIBLE 就不用调用ShowWindow了 */
    29. WS_VISIBLE | WS_OVERLAPPEDWINDOW,
    30. 100,
    31. 45,
    32. 500,
    33. 380,
    34. NULL,
    35. NULL,
    36. hThisApp,
    37. NULL);
    38. // 消息循环
    39. MSG msg;
    40. while(GetMessage(&msg, NULL, 0, 0))
    41. {
    42. TranslateMessage(&msg);
    43. DispatchMessage(&msg);
    44. }
    45. return 0;
    46. }
    47. LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    48. {
    49. switch(msg)
    50. {
    51. case WM_DESTROY:
    52. PostQuitMessage(0);
    53. return 0;
    54. case WM_PAINT:
    55. PAINTSTRUCT ps;
    56. BeginPaint(hwnd, &ps);
    57. // 创建钢笔
    58. HPEN pen = CreatePen(PS_DASH, 1, RGB(0,255,50));
    59. // 把笔选到DC中
    60. SelectObject(ps.hdc, pen);
    61. // 设定线段的起点
    62. MoveToEx(ps.hdc, 15, 25, NULL);
    63. // 绘制线条
    64. LineTo(ps.hdc, 65, 49);
    65. LineTo(ps.hdc, 12, 120);
    66. LineTo(ps.hdc, 250, 78);
    67. LineTo(ps.hdc, 312, 185);
    68. // 绘制贝塞尔曲线
    69. pen = CreatePen(PS_DOT, 1, RGB(0,3,255));
    70. SelectObject(ps.hdc, pen);
    71. POINT* pts = new POINT[4];
    72. pts[0].x = 421;
    73. pts[0].y = 16;
    74. pts[1].x = 7;
    75. pts[1].y = 197;
    76. pts[2].x = 480;
    77. pts[2].y = 320;
    78. pts[3].x = 30;
    79. pts[3].y = 350;
    80. PolyBezier(ps.hdc, pts, 4);
    81. delete [] pts;
    82. // 第二段贝塞尔曲线
    83. POINT* pts2 = new POINT[3];
    84. pts2[0].x = 176;
    85. pts2[0].y = 84;
    86. pts2[1].x = 17;
    87. pts2[1].y = 247;
    88. pts2[2].x = 400;
    89. pts2[2].y = 490;
    90. // 移动当前点
    91. MoveToEx(ps.hdc, 395, 270, NULL);
    92. PolyBezierTo(ps.hdc, pts2, 3);
    93. delete [] pts2;
    94. // 复杂图形
    95. pen = CreatePen(PS_DASHDOTDOT, 1, RGB(80,20,160));
    96. SelectObject(ps.hdc, pen);
    97. POINT plpts[10] =
    98. {
    99. {47,3}, {11,46}, {28,199}, {203,305}, {94,22},
    100. {402,377}, {21,45}, {237,7}, {300,398}, {175,25}
    101. };
    102. DWORD arr[4] = { 2, 3, 3, 2};
    103. PolyPolyline(ps.hdc, &plpts[0], &arr[0], 4);
    104. DeleteObject(pen);
    105. EndPaint(hwnd, &ps);
    106. return 0;
    107. }
    108. return DefWindowProc(hwnd, msg, wParam, lParam);
    109. }

跟我一起玩Win32开发(9):绘图(B)的更多相关文章

  1. 跟我一起玩Win32开发(转自CSDN-东邪独孤)

    跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4):创建菜单 跟我一起玩W ...

  2. 跟我一起玩Win32开发(17):启动和结束进程

    这里我再次说明一下,我不知道为什么,现在的人那么喜欢走极端,估计是价值观都“升级”了的缘故吧. 我撰写这一系列Win32相关的文章,并不是叫大家一定要用Win32去开发项目,仅仅是给大家了解一下,Wi ...

  3. 跟我一起玩Win32开发(18):使用对话框的两个技巧

    相信大家知道对话框怎么用了,就是先用“资源编辑器”设计一个对话框,然后在代码中加载处理.今天,我向大家分享两个使用对话框的技巧,还是比较实用的.不用担心,先喝杯茶,很简单的,一点也不复杂,总之,看俺写 ...

  4. 跟我一起玩Win32开发(10):绘图(C)

    今天我们来欣赏一下用于填充图形的函数,当然我不会逐个去介绍,因为我们参考MSDN直接套参数就可以了. SetDCBrushColor函数有必要扯一下,它的声明如下: COLORREF SetDCBru ...

  5. 跟我一起玩Win32开发(8):绘图(A)

    从本篇开始,我就不吹牛皮,那就吹吹兔皮吧.说说与绘图有关的东东. 要进行绘制,首先要得到一个DC,啥是DC呢?按字面翻译叫设备上下文,也可以翻译为设备描述表,它主要指API为我们封装了一些与显示设备相 ...

  6. 跟我一起玩Win32开发(19):浏览和打开文件

    在应用程序中,我们很经常要实现的功能,是Open文件或保存文件对话框,让用户来选择一个或N个文件.本文我将介绍两种思路,第一种方法较为复杂,第二种方法较为简单. 方法一:老规矩 这是一种传统方法,使用 ...

  7. 跟我一起玩Win32开发(12):使用控件——单选按钮

    今天,咱们还是接着玩“控件斗地主”,这是我原创的超级游戏,有益身心健康,玩一朝,十年少. 哦,对,脑细胞极速运动了一下,想起了一个问题,这个破问题虽然网上有很多种解决方案,但是,并没有让所有人都解决问 ...

  8. 跟我一起玩Win32开发(23):渐变颜色填充

    GradientFill函数可以对特定的矩形区域或者三角形区域进行渐变颜色的填充.我们先来看看GradientFill函数到底长得什么样子,帅不帅. BOOL GradientFill( _In_   ...

  9. 跟我一起玩Win32开发(21):复制&粘贴&剪贴板操作

    我要提醒一下大家,看了我的博文学到的知识,千万不要用于实际开发,不然你会被你的上司骂:“妈的,这些东西哪来的,从来没有人这样做过.”不信你试试,脑细胞被冻结的经理或者技术总监们肯定会这样说的. 如果是 ...

随机推荐

  1. Android 代码写控件

    1.设置dialog弹出anthor public static SearchDialog getSearchDialog(Context context,OnDismissListener list ...

  2. 2016/06/13 phpexcel 未完待续

    ①准备工作: 1,php版本不能太低 2,去官网下载PHPExcel插件    http://phpexcel.codeplex.com/ 3,解压后提取classes文件夹到工作目录,并重命名为PH ...

  3. bash_action

    https://stackoverflow.com/questions/12076326/how-to-install-maven2-on-redhat-linux #!/bin/bash # Tar ...

  4. 记录001:AS11 BAPI

    未知元素(174657434)  15:05:41AS11有没有BAPI呀?有做过的吗 BAPI_FIXEDASSET_OVRTAKE_CREATE

  5. HDU 5687 Problem C

    Problem C Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total ...

  6. (linux)SD卡初始化-mmc_sd_init_card函数

      为了学习SD/SDIO协议,看了一下linux中初始化SD卡的流程,结合代码更容易SD初始化是怎么做的. 下面图截自:"SD Specifications Part 1 Physical ...

  7. 关于谷歌浏览器默认字体12px的解决方案

    1. * Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示, 可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决. 超链接访问 ...

  8. Caused by: java.lang.IllegalArgumentException: Result Maps collection already contains value for com.st.mapper.UserMapper.userBaseMap

    mybatis出现此异常,可能是因为 ***Mapper.xml 文件中存在重名对象,一不小心重复启动了mybatis的逆向工程. 以为会覆盖掉以前生成的,没想到是新生成的和之前生成的重复了 解决:把 ...

  9. html5--6-4 CSS选择器

    html5--6-4 CSS选择器 实例 学习要点 掌握常用的CSS选择器 了解不太常用的CSS选择器 什么是选择器 当我们定义一条样式时候,这条样式会作用于网页当中的某些元素,所谓选择器就是样式作用 ...

  10. 调节音量的各个方法——AudioManager的使用

    AudioManager类位于android.Media包中,该类提供访问控制音量和铃声模式的操作. //获取AudioManager实例对象 AudioManager audioManage = ( ...