设为首页 收藏本站
查看: 953|回复: 0

[经验分享] Windows的图形设备接口与Windows绘图

[复制链接]

尚未签到

发表于 2017-6-28 12:20:28 | 显示全部楼层 |阅读模式
  本次学习目标
  理解DC, 映像模式, 坐标系统, 窗口和视口; 学习获取绘图工具(画笔/画刷)的句柄, 设置颜色, 能定义映像模式; 会使用常用的绘图函数.
  编写程序: 在屏幕上出现一个圆心沿正弦曲线轨迹移动的实心圆.
  1. 理解DC, 映像模式, 坐标系统, 窗口和视口;
  编写基本的windows绘图程序,获取DC并绘图,然后改变其映射模式、坐标、窗口和视口原点,观察图像输出的变化,理解DC, 映像模式, 坐标系统, 窗口和视口的工作方式。
  程序代码如下:
  #include<windows.h>
  #include<stdlib.h>
  #include<string.h>
  long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam);
  BOOL InitWindowsClass(HINSTANCE hInstance);
  BOOL InitWindows(HINSTANCE hInstance,int nCmdShow);
  int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
  {
  MSG Message;
  if(!InitWindowsClass(hInstance))
  return FALSE;
  if(!InitWindows(hInstance,nCmdShow))
  return FALSE;
  while(GetMessage(&Message,0,0,0))        //消息循环
  {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
  }
  return Message.wParam;
  }
  long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam)
  {
  HDC hDC;             //定义指向设备上下文的句柄
  HPEN hPen;            //定义指向画笔的句柄
  PAINTSTRUCT PtStr;     //定义指向包含绘图信息的结构体变量
  switch(iMessage)     //处理消息
  {
  case WM_PAINT:                             //处理绘图消息
  hDC=BeginPaint(hWnd,&PtStr);
  SetMapMode(hDC,MM_ANISOTROPIC);         //设置映射模式为MM_ANISOTROPIC
  hPen=(HPEN)GetStockObject(BLACK_PEN);//设置画笔为系统预定定义的黑色画笔
  
  SelectObject(hDC,hPen);             //选择画笔
  RoundRect(hDC,50,120,200,-200,15,15); //圆角矩形
  Ellipse(hDC,100,50,200,100);          //椭圆
  EndPaint(hWnd,&PtStr);         //结束绘图
  return 0;
  case WM_DESTROY:                          //结束应用程序
  PostQuitMessage(0);
  return 0;
  default:                                    //其他消息处理程序
  return(DefWindowProc(hWnd,iMessage,wParam,lParam)) ;
  }
  }
  BOOL InitWindows(HINSTANCE hInstance,int nCmdShow)        //初始化窗口
  {
  HWND hWnd;
  hWnd=CreateWindow("WinFill",                         //生成窗口
  "填充示例程序",
  WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT,
  0,
  CW_USEDEFAULT,
  0,
  NULL,
  NULL,
  hInstance,
  NULL);
  if(!hWnd)
  return FALSE;
  ShowWindow(hWnd,nCmdShow);                    //显示窗口
  UpdateWindow(hWnd);
  return TRUE;
  }
  BOOL InitWindowsClass(HINSTANCE hInstance)             //定义窗口类
  {
  WNDCLASS WndClass;
  WndClass.cbClsExtra=0;
  WndClass.cbWndExtra=0;
  WndClass.hbrBackground=(HBRUSH)(GetStockObject(WHITE_BRUSH));
  WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
  WndClass.hIcon=LoadIcon(NULL,"END");
  WndClass.hInstance=hInstance;
  WndClass.lpfnWndProc=WndProc;
  WndClass.lpszClassName="WinFill";
  WndClass.lpszMenuName=NULL;
  WndClass.style=CS_HREDRAW|CS_VREDRAW;
  return RegisterClass(&WndClass);
  }
  编译并调试程序,
  分别改变其映射模式、坐标、窗口和视口原点,观察图像输出的变化
  2. 获取绘图工具(画笔/画刷)的句柄, 设置颜色
  修改绘图代码为:
  hPen=(HPEN)GetStockObject(BLACK_PEN);//设置画笔为系统预定定义的黑色画笔
  hBrush=(HBRUSH)GetStockObject(DKGRAY_BRUSH); //采用系统预定义的深灰色画刷
  SelectObject(hDC,hBrush);             //选择画刷
  SelectObject(hDC,hPen);             //选择画笔
  RoundRect(hDC,50,120,200,-200,15,15); //圆角矩形
  hBrush=CreateSolidBrush(RGB(220,32,70));
  SelectObject(hDC,hBrush);             //选择画刷
  Ellipse(hDC,100,50,200,100);         //椭圆
  编译并调试程序
  3.在屏幕上绘制一个圆心沿正弦曲线轨迹移动的实心圆
  程序源代码如下:
  #include <windows.h>
  #include <stdlib.h>
  #include <string.h>
  #include <math.h>
  #define Pi 3.1415926
  long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam);                    //消息处理函数声明.
  double dfTheta=0,dfRange=100.0;                        //正弦曲线的角度变量.
  long i=0,j=0;
  long lCentreX=0,lCentreY=0,lRadious=(long)(0.5*dfRange);
  //定义圆心坐标和圆坐标.
  POINT lpSin[100];    //定义正弦曲线的点坐标.
  int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)            //主函数
  {
  MSG Message;            //定义消息变量.
  HWND hWnd;                //定义窗口句柄.
  WNDCLASS WndClass;        //定义窗口类.
  WndClass.cbClsExtra=0;        //无窗口类扩展.
  WndClass.cbWndExtra=0;        //无窗口实例扩展.
  WndClass.hbrBackground=(HBRUSH)(GetStockObject(WHITE_BRUSH));//背景为白色.
  WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);    //窗口采用箭头光标.
  WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);    //采用缺省图标.
  WndClass.hInstance=hInstance;                    //当前应用程序句柄.
  WndClass.lpfnWndProc=WndProc;                    //窗口处理函数.
  WndClass.lpszClassName="SIN";                    //窗口类名称.
  WndClass.lpszMenuName=NULL;                        //无窗口菜单.
  WndClass.style=0;                                //窗口类型为缺省类型.
  if(!RegisterClass(&WndClass))            //注册窗口.
  {
  MessageBeep(0);
  return FALSE;
  }
  
  hWnd=CreateWindow("SIN",                //窗口类名.
  "yuan",                    //标题名.
  WS_OVERLAPPEDWINDOW,    //带标题栏,最大和最小按钮的窗口.
  CW_USEDEFAULT,            //窗口左上角坐标.
  0,                        
  CW_USEDEFAULT,            //采用缺省的宽度和高度.
  0,
  NULL,                    //无父窗口.
  NULL,                    //无主菜单.
  hInstance,                //当前实例句柄.
  NULL);                    //不要此参数.
  ShowWindow(hWnd,nCmdShow);            //显示窗口.
  UpdateWindow(hWnd);                    //更新并绘制用户区.
  for(int j=0;j<100;j++)        //生成正弦曲线的点坐标.
  {
  lpSin[j].x=(long)(j*2*Pi/100*60);
  lpSin[j].y=(long)(dfRange*sin(j*2*Pi/100));
  }
  
  while(GetMessage(&Message,0,0,0))
  {
  TranslateMessage(&Message);            //消息循环.
  DispatchMessage(&Message);
  }
  return Message.wParam;
  }
  long WINAPI WndProc(HWND hWnd,
  UINT iMessage,
  UINT wParam,
  LONG lParam)            //消息处理函数.
  {
  HDC hDC;                //定义设备环境句柄.
  HBRUSH hBrush;            //定义画刷句柄
  HPEN hPen;                //定义画笔句柄
  PAINTSTRUCT PtStr;        //定义包含绘图信息的结构体变量
  switch(iMessage)
  {
  case WM_PAINT:                            //处理绘图消息.
  hDC=BeginPaint(hWnd,&PtStr);        //获得设备环境指针.
  SetWindowOrgEx(hDC,-200,-200,NULL);    //设置原点坐标为(-200,-200).
  Polyline(hDC,lpSin,100);                //绘制正弦曲线.
  hPen=(HPEN)GetStockObject(BLACK_PEN);//设置画笔为系统预定定义的黑色画笔
  hBrush=(HBRUSH)GetStockObject(DKGRAY_BRUSH); //采用系统预定义的深灰色画刷
  SelectObject(hDC,hBrush);    //选入画刷.
  SelectObject(hDC,hPen);        //选入画笔.
  lCentreX=lpSin.x;        //圆心x坐标.
  lCentreY=lpSin.y;        //圆心y坐标.
  Ellipse(hDC,lCentreX-lRadious,lCentreY-lRadious,
  lCentreX+lRadious,lCentreY+lRadious);    //画圆.
  i++;
  if(i>=100)
  i=0;
  DeleteObject(hPen);        //删除画笔.
  DeleteObject(hBrush);    //删除画刷.
  EndPaint(hWnd,&PtStr);    //删除设备环境指针.
  Sleep(100);                //停0.1秒.
  if(i<100) InvalidateRect(hWnd,NULL,1);    //刷新用户区.
  return 0;
  case WM_DESTROY:    //关闭窗口.
  PostQuitMessage(0);
  return 0;
  default:
  return(DefWindowProc(hWnd,iMessage,wParam,lParam));
  }
  }
  编译并调试程序,
  1.DC, 映像模式, 坐标系统, 窗口和视口程序运行结果:
  初始图像:
DSC0000.png

  改变映射模式为MM_LOMETRIC后:
DSC0001.png

  Y向上,X向右,将一个逻辑单位映射为0.1毫米
  恢复映射模式为MM_ANISOTROPIC并设置setWindowExtEx(hDC,2,2,0);后:
DSC0002.png

  图形相对于之前缩小
  设置SetViewportExtEx(hDC,2,2,0);后
DSC0003.png

  SetViewportExtEx(hDC,2,2,0);与setWindowExtEx(hDC,2,2,0);比例设置的映射比例相同,图像大小与初始一样。
  此时图像上面部分不可见,设置SetViewportOrgEx(hDC,300,300,0);将视口原点往右下移动,此时图像输出为:
DSC0004.png

  图像随视口往右下移动,此时可以看见整个图像。
  同样再上一步步骤中视口原点不变,改变窗口原点SetWindowOrgEx(hDC,-300,-300,0);此时图像输出与上图相同。
  现在,恢复窗口与视口原点并设置SetViewportExtEx(hDC,1,-1,0);此时图像输出为:
DSC0005.png

  图像绕X翻转180°。此时为了能够让图像完全显示,依旧需要将视口原点往下移动即    SetViewportOrgEx(hDC,0,300,0);此时输出如图:
DSC0006.png

  或者移动窗口原点SetWindowOrgEx(hDC,0,300,0);此时输出和上图相同
  设置SetWindowExtEx(hDC,1,-1,0);与设置SetViewportExtEx(hDC,1,-1,0)的情况相同。
  2. 获取绘图工具(画笔/画刷)的句柄, 设置颜色的运行结果
DSC0007.png

  3.在屏幕上绘制一个圆心沿正弦曲线轨迹移动的实心圆运行结果
DSC0008.png

  总结:
  DC, 映像模式, 坐标系统, 窗口和视口;
  不同映射模式的逻辑单位映射成的设备单位不同,ANISOTROPIC与ISOTROPIC模式可以通过SetWindowExtEx与SetViewportExtEx函数来确定,其余的为固定尺寸。
  不同映射模式的坐标系设定也不同,ANISOTROPIC与ISOTROPIC模式可以通过SetWindowExtEx与SetViewportExtEx函数来确定,其余的有自己固定方向。其中ISOTROPIC模式X轴与Y轴单位比例固定为1:1。
  注意在改变视口与窗口原点使图像能够全部显示时,分清窗口在逻辑坐标系中移动的方向和视口在设备坐标系移动的方向!
  窗口与视口的映射关系具体可以参考:从窗口到视口的映射.pdf
  获取绘图工具(画笔/画刷)的句柄并设置颜色;
  可以直接调用函数GetStockObject获取Windows系统提供的8种画刷,也可以调用函数CreateSolidBrush或CreateHatchBrush来创建具有指定颜色的单色画刷或具有指定阴影图案和颜色的画刷。
  创建好的画刷记得选入设备环境,不再使用后记得删除。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-388973-1-1.html 上篇帖子: redis(一)Windows下安装redis服务、搭建redis主从复制 下篇帖子: Windows,caffe 仅cpu
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表