Windows程序设计3(资源、绘图、坐标系)

一、RC资源的使用

  • 资源相关

资源脚本文件:*.rc文件

编译器:RC.EXE

  • 菜单资源的使用

1 添加菜单资源:通过菜单栏中插入(rc)菜单资源。或直接添加资源脚本到工程中。

2 加载菜单资源

2.1 在注册时设置菜单资源

2.2 加载菜单资源,设置到窗口

HMENU LoadMenu(

HINSTANCE hInstance,  //应用程序句柄

LPCTSTR lpMenuName  //菜单字符串资源(或菜单资源ID

);

MAKEINTRESOURCE宏,可以使得数字形式的资源ID,转化为字符串形式的资源ID。

宏原型:

LPTSTR  MAKEINTRESOURCE(

  WORD   wInteger  // 转化的整数

);

 

使用地方:

1. CreateWindow/Ex 创建窗口时。

如:wndclass.lpszMenuName =MAKEINTRESOURCE(IDR_MENU1);

2.  在WM_CREATE时,通过SetMenu():

函数原型:BOOL  SetMenu(

  HWND hWnd,  // 窗口句柄

  HMENU hMenu // 菜单句柄,可以通过LoadMenu()获得。

);

如:

HMENU hMenu=LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_MENU1));

SetMenu( hWnd , hMenu );

获取子菜单: GetSubMenu() ;

HMENU   GetSubMenu(

    HMENU   hMenu,  // 窗口句柄

   int   nPos      // 菜单位置,索引

);

二、ICO图标资源

一个图标文件是由多个不同大小的图像组成的复合文件。(注意图标的大小)

1 添加资源:通过新建资源文件,并在菜单栏中插入(icon)图标资源。

2 加载

HICON   LoadIcon(

  HINSTANCE   hInstance, // 应用程序句柄

  LPCTSTR    lpIconName   // 字符串或资源ID

); 成功,返回HICON句柄,hInstanceNULL,则加载需为标准的系统自带图标。

如:wndclass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_WINICON));

wndclass.hIconSm=NULL;//注意此处小图标若为NULL,这样是自动加载小图标的,否则大小图标都变成了大图标了。

3 设置

3.1 注册窗口类时设置。

3.2  WM_SETICON消息中设置。

SendMessage(hWnd,WM_SETICON,wParam,lParam);

如:

//大图标

SendMessage(hWnd,WM_SETICON,ICON_BIG,(LPARAM)hIcon);

//小图标

SendMessage(hWnd,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);

  参数:

wParam  -图标的类型,ICON_BIG/ICON_SMALL

lParam   -图标句柄

4 绘制图标  :DrawIcon

BOOL   DrawIcon(

  HDC   hDC,      //设备上下文句柄

  int   X,        // 左上角坐标x

  int   Y,        // 左上角坐标y

  HICON hIcon   // 将绘制的图标句柄,可通过LoadIcon or LoadImage 获取。

);//成功返回TRUE,失败返回FALSE

BOOL DrawIconEx(

  HDC  hdc,                    // 设备上下文句柄

  int  xLeft,                  //左上角坐标x

  int  yTop,                   //左上角坐标y

  HICON  hIcon,                // 图标句柄

  int  cxWidth,                // 图标宽度

  int  cyWidth,                // 图标高度

  UINT  istepIfAniCur,         // 动画图标的帧数,不支持,置0.

  HBRUSH  hbrFlickerFreeDraw,  // 系统绘制,置NULL.

  UINT  diFlags                // 绘制标识

);

diFlagsDI_NORMAL   正常绘制(DI_IMAGE and DI_MASK的组合或运算)

  DI_IMAGE      图像部分

  DI_MASK       掩码部分

三、CURSOR光标资源

1  添加光标的资源

同添加图标资源,光标的大小默认是32X32像素,每个光标有HotSpot,是当前鼠标的热点

2  使用资源

HCURSOR   LoadCursor(

     HINSTANCE  hInstance,  // 应用程序实例句柄

      LPCTSTR   lpCursorName  //光标资源ID

);  //成功,返回光标句柄,失败返回NULL

hInstance - 可以为NULL,获取系统默认的Cursor

2.1 在注册窗口时,设置光标:(根据此窗口类创建的所有窗口都是使用此光标)

如:

wndclass.hCursor=LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CIRCLE));

2.2 使用SetCursor设置光标,

HCURSOR   SetCursor(

   HCURSOR hCursor   // handle to cursor

);

3  WM_SETCURSOR 动态设置光标通过SetCursor()(有鼠标动作且鼠标未捕获时受到此消息)

消息参数

WPARAM  -  当前使用的光标句柄

LPARAM    - LOWORD 当前区域的代码(Hit-Test code )

          HIWORD - 当前鼠标消息ID

HCURSOR  SetCursor(

HCURSOR  hCursor  ///光标句柄

);//返回原光标句柄。

4   (**.cur)文件加载光标

HCURSOR   LoadCursorFromFile(

LPCTSTR   lpFileName;   //文件指针或系统光标ID

);

如:hcurs=LoadCursorFromFile("G:/5000ICO图标文件/生活用品/sword.ani");hcurs=LoadCursorFromFile("G:\\5000ICO图标文件\\生活用品\\sword.ani");

四、字符串资源

1.添加字符串表资源,在表中添加字符串

2.加载字符串资源

int   LoadString(

HINSTANCE   hInstance,     // 应用程序实例句柄

UINT   uID,               //字符串ID

LPTSTR  lpBuffer,  //存放字符串缓冲区(BUFF)

Int   nBufferMax // 字符串缓冲区(BUFF)长度(以字符为单位,含空字符)

); 成功返回字符串长度,失败返回0.

五、字符串资源

1  添加    添加加速键表,增加命令ID对应的加速键。

2  使用

    2.1 加载加速键

    HACCEL  LoadAccelerators(

    HINSTANCE   hInstance,  // 模块、实例句柄

    LPCTSTR    lpTableName   // 加速键表名

     ); 成功,则返回加速键句柄,失败则返回NULL

    2.2 处理(翻译)加速键消息

    int  TranslateAccelerator(

    HWND   hWnd,       //处理消息的窗口句柄

    HACCEL   hAccTable,  //加速键句柄

    LPMSG   lpMsg       //消息

     ); 如果是加速键,返回非零。

     2.3 WM_COMMAND中响应消息,消息参数

      WPARAM - HIWORD 1表示加速键,为0表示菜单

                 LWORD  为命令ID

处理加速键消息过程:

TranslateAccelerator(HWND  hWnd,HACCEL   hAccTable ,LPMSG  lpMsg)

{

if(lpMsg->message==WM_KEYDOWN||lpMsg->message==WM_SYSKEYDOWN)

{

lpMsg提取按键消息;

if(hAccTable加速键表中存在与所按键相对应的命令ID)

{

PostMessage(hWnd,WM_COMMAND,MAKELONG(命令ID1)NULL)

return 1;

}

}

}

用在:

MSG   msg={0};

while(GetMessage(&msg,NULL,0,0))

{

if(!TranslateAccelerator(msg.hwnd,  AccTable   ,&msg))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

/////最好让加速键的ID和相应菜单ID对应。另外快捷键也可以不与菜单对应,一样的做其他功能。

六、版本资源

通过添加VERSION资源。修改其中内容。

七、Windows 绘图

  1. 设备上下文(Device  ContextDC)

HDC -  DC句柄,表示绘图设备,对绘图设备的抽象。

GDI - Windows graphics device interface   Win32提供的绘图API.

Case WM_PAINT:

……….

HDC  hdc=BeginPaint(hWnd,  &ps);//与窗口相关联

Case WM_PRINT:

…………

HDC   hdc=BeginPaint(hPrinter,   &ps);//与打印机相关联的,

2. 图形设备接口(Graphics Device InterfaceGDI)

Win32的绘图API,封装在gdi32.dll中,通过该接口给设备上下文下达绘制命令。它是一个在Windows应用程序中执行与设备无关的函数库,这些函数在不同的输出设备上产生图形以及文字输出。

3. 颜色空间的使用

     1.RGB  :电脑显示器,每一个点颜色是3个字节24位保存 0-2^24

R - 0255

G - 0255

B - 0255

    2.CMYK  浅青(--),洋红(绿),黄(),黑。(作减法)打印机上。

颜色深度:位/像素

1/像素    2种颜色(黑,白)

4/像素    16种颜色

8/像素    256种颜色,调色板

16/像素    R5G5B6,增强色,( R5G5B6表示红色5位绿色5,6)

24/像素    R8G8B8,真彩色

32位/像素    A8R8G8B8增加透明度(A8)

   颜色处理和使用

COLORREF - 实际为DWORD类型,OxAABBGGRR.

例如:

Ox00000000   黑色

Ox000000FF   纯红

Ox0000FF00   纯绿

Ox00FF0000   纯蓝

Ox00FFFF00   浅青

使用16进制挺麻烦,常使用颜色宏

颜色的组合宏:

RGB(r,g,b); // R/G/B  0~255

COLORREF nColor = 0;

赋值使用RGB宏,例如:

nColor = RGB( 255, 0, 0 );

获取RGB分解值,

GetRValue/GetGValue/GetBValue

例如:

BYTE  nRed = GetRValue( nColor );

BYTE   ----无符号8位整型

4. 点的使用

GetPixel 获取指定坐标像素点的颜色

COLORREF  GetPixel(

HDC  hdc,    // handle to DC

int  nXPos,  // x-coordinate of pixel

int  nYPos   // y-coordinate of pixel

);

SetPixel 设置指定坐标像素点的颜色

COLORREF  SetPixel(

HDC  hdc,//DC句柄

int  X,//X坐标

int  Y,//Y坐标

COLORREF  crColor //设置的颜色

); 返回点原来的颜色

5. 直线的使用(直线、圆形、弧线)

当前点:上一次绘图时的最后一点,初始为(00)点。

1.从当前点移动到目标点,并使目标点成为新的当前点。

(MoveTo扩展为MoveToEx(),)  

BOOL  MoveToEx(

HDC  hdc,    //设备上下文

Int  x, //新的坐标位置

Int  y,

LPPOINT  lpPoint   //当前位置

);

2.从当前点到指定点绘制一条直线.

BOOL  LineTo(

  HDC  hdc,    //设备上下文 

  int  nXEnd,  //  终点坐标位置

int  nYEnd //

);

3.绘制(椭)圆弧

(绘制圆弧,只要控制好外切矩形使得为正方形即可,与画圆同样方式)

BOOL     Arc(

  HDC  hdc,      // 设备上下文

  int  nLeftRect,   // 外切矩形左上角

  int  nTopRect,   //

  int  nRightRect,  //外切矩形右下角

int  nBottomRect, //  

int  nXStartArc,  //起点坐标

  int  nYStartArc,  //

  int  nXEndArc,   // 终点坐标

  int  nYEndArc    //

);

设置截弧方向:

Int   SetArcDirection(

  HDC   hdc,         //设备上下文

  int   ArcDirection   // 指定截弧方向

);//成功返回原截弧方向,失败返回0

/// ArcDirection截弧方向:(默认为逆时针)

AD_COUNTERCLOCKWISE(逆时针)AD_CLOCKWISE(顺时针)

4.绘制封闭图形

1.封闭图形:可被画刷填充的图形,由直线弧线围起的不是封闭图形。

2.矩形:

BOOL   Rectangle(

  HDC   hdc,         // 设备上下文

  int     nLeftRect,   // 矩形左上角

  int    nTopRect,    //

  int    nRightRect,  // 矩形右下角

  int    nBottomRect  //

);

3.椭圆

BOOL    Ellipse(

HDC hdc,        // 设备上下文

int nLeftRect,  //外切矩形左上角

int nTopRect,   //

int nRightRect, //外切矩形右下角

int nBottomRect //

);

4.圆角矩形

BOOL   RoundRect(

  HDC   hdc,         //设备上下文

  int   nLeftRect,   // 左上角坐标

  int   nTopRect,    //

  int   nRightRect,  // 右下角坐标

  int   nBottomRect, //

  int   nWidth,      // 圆角椭圆的两个轴(分布于四个角上)

  int   nHeight      //

);

6.画笔的作用

线的颜色、线型、线粗。

HPEN - 画笔句柄

1 创建画笔

HPEN   CreatePen(

Int  fnPenStyle, //画笔的样式

int   nWidth, //画笔的粗细

COLORREF   crColor //画笔的颜色

);创建成功返回句柄,失败返回NULL

fnPenStyle样式,

PS_SOILD - 实心线,可以支持多个像素宽,其他线型只能是一个像素宽。

PS_DASH   虚线

PS_DOT   点线

PS_DASHDOT- --点划线

PS_DASHDOTDOT----双点划线

PS_NULL    不可见的线

nWidth 线宽进对PS_SOLID实线起作用。若nWidth>1,则无论fnPenStyle,去何值画出来的都是实线的了。

2 将画笔应用到设备上下文中,同时得到设备上下文中原画笔

HGDIOBJ   SelectObject(

HDC    hdc,//绘图设备句柄

HGDIOBJ   hgdiobj //GDI绘图对象句柄,画笔句柄

);返回原来的GDI绘图对象句柄

//注意保存原来DC当中画笔。用以恢复原画笔。

3 绘图

4 恢复原画笔(取出DC中的画笔)

将原来的画笔,使用SelectObject函数,放入到设备DC中,就会将我们创建的画笔取出。SelectObject(hDc, hpenOld);//恢复原画笔

5 释放(删除)画笔

BOOL   DeleteObject(

HGDIOBJ   hObject   //GDI绘图对象句柄,画笔句柄

);//成功返回TRUE,失败返回FALSE

过程:建立->载入->画图->取出->删除

: HGDIOBJ  hpenOld=SelectObject(hDc, CreatePen(….));

……

DeleteObject( SelectObject( hDc, hpenOld);

//注意:永远不要删除设备上下文正在持有的GDI对象。

//只能删除不被DC使用的画笔,所以在释放前,必须将画笔从DC中取出。

7 画刷的使用

画刷 - 封闭图形的填充的颜色、图案

HBRUSH - 画刷句柄

画刷的使用

1 创建画刷

CreateSolidBrush - 创建实心画刷

HBRUSH CreateSolidBrush(

       COLORREF crColor   //画刷颜色值

);//成功返回画刷句柄,失败返回NULL

CreateHatchBrush - 创建填充画刷

HBRUSH CreateHatchBrush(

    int   fnStyle,      // 阴影线风格

    COLORREF   clrref   // 阴影线颜色

);//成功返回填充画刷,失败返回NULL

fnStyle风格:

HS_BDIAGONAL

45-degree downward left-to-right hatch

HS_CROSS

Horizontal and vertical crosshatch

HS_DIAGCROSS

45-degree crosshatch

HS_FDIAGONAL

45-degree upward left-to-right hatch

HS_HORIZONTAL

Horizontal hatch

HS_VERTICAL

Vertical hatch

 

2 将画刷应用到DC中

SelectObject

3 绘图

4 将画刷从DC中取出

SelectObject

5 删除画刷

DeleteObject

纹理画刷:

创建:

HBRUSH   CreatePatternBrush(

      HBITMAP   hbmp   //位图句柄

);//成返回画刷句柄,失败返回NULL

其他:

可以使用 GetStockObject 函数获取系统维护的画刷、画笔等。

如果不使用画刷填充,需要使用NULL_BRUSH参数,获取不填充的画刷。

GetStockObject返回的画刷不需要DeleteObject。

9.位图的使用

计算机图像分为:

光栅图形 - 记录图像中每一像素点的颜色和透明度等信息。

矢量图形 - 记录图像渲染算法、绘图指令,几何坐标等。

Windows中的位图是一种光栅图像。

HBITMAP - 位图句柄

位图使用:

1) 在资源中添加位图

2) 从资源中加载位图

HBITMAP LoadBitmap(

   HINSTANCE   hInstance,  //应用程序句柄

   LPCTSTR   lpBitmapName  //位图资源名

);//成功返回位图句柄,失败返回NULL

3) 创建与窗口设备上下文匹配的内存设备上下文

HDC CreateCompatibleDC(

   HDC hdc   // 匹配的源设备上下文句柄

);//成功返回内存设备上下文句柄,失败返回NULL

4) 将位图选入内存设备上下文

HGDIOBJ hbmpOld=SelectObject(hdcMem, hbmpNew);

5) 将内存设备上下文中的位图成像到目标设备上下文中

BOOL BitBlt(

  HDC hdcDest, // 目标设备上下文句柄

  int nXDest,  //目标图像左上角坐标 

  int nYDest,  //

int nWidth,  //目标图像的宽度和高度

int nHeight, //

  HDC hdcSrc,  // 源设备上下文句柄

  int nXSrc,   // 源图像左上角坐标

  int nYSrc,   //

DWORD dwRop  //光栅操作码(ROP),源像素与目标像素的位运算

);

缩放成像:

BOOL  StretchBlt  (

  HDC hdcDest, // 目标设备上下文句柄

  int nXDest,  //目标图像左上角坐标 

  int nYDest,  //

int nWidth,  //目标图像的宽度和高度

int nHeight, //

  HDC hdcSrc,  // 源设备上下文句柄

  int nXSrc,   // 源图像左上角坐标

  int nYSrc,   //

DWORD dwRop  //光栅操作码(ROP),源像素与目标像素的位运算

);

6) 恢复内存设备上下文的原位图

SelectObject(hdcMem, hbmpOld);

7) 删除新位图

DeleteDC(hbmpNew);

8) 释放内存设备上下文

DeleteDC(hdcMem);

//获取位图的信息:

GetObject(…,…);//可获取位图相关信息

八、坐标系

1. 坐标系分类:

设备坐标系

以像素为单位,即一个单位就是一个像素,以设备左上角为原点,X轴向右为正,Y轴向下为正的坐标系。(像素大小与成像设备有关,成像设备分辨率越高,像素点越多)

1 屏幕坐标系 - 以当前屏幕左上角为原点坐标系。

2 窗口坐标系 - 以窗口左上角为原点坐标系。

3 客户区坐标系 - 以窗口的客户区左上角为原点的坐标系。

逻辑坐标系

GDI绘图中,都是使用逻辑坐标绘图,坐标单位、坐标原点、坐标轴的方向都可以设置。

默认情况下,逻辑坐标系与设备坐标系重合。1逻辑=1设备,显示器:1设备=1像素,打印机:1设备=1/1440英寸(0.018毫米)

2. 坐标系映射:

1)映射模式

A.确定了逻辑坐标系与设备坐标系之间的映射关系。

B.设备做你奥西的单位不能通过代码修改但是逻辑坐标系可修改。

Int  SetMapMode(

HDC    hdc,    ///DC句柄

Int fnMapMode///映射模式

);//返回原先的映射模式

fnMapMode 映射模式如下:

MM_TEXT-默认(正文)模式,1逻辑单位对应1设备单位(显示器为像素),X右为正,Y下为正。

MM_LOENGLISH-低英制模式,1逻辑单位 = 0.01英寸,X右为正,Y上为正。

MM_HIENGLISH-高英制单位,1逻辑单位=0.001英寸,X右为正,Y上为正。

MM_LOMETRIC-低公制单位,1逻辑单位=0.1毫米,X右为正,Y上为正。

MM_HIMETRIC-高公制模式,1个逻辑单位=0.01毫米,X右为正,Y上为正。

MM_TWIPS-打印机模式,1个逻辑单位=1/1440英寸,打印机使用单位。

MM_ISOTROPIC-各向同性模式,1逻辑单位=自定义,X和Y正方向、原点可自定义,逻辑单位与设备单位的比例在水平和垂直方向上取一致。

MM_ANISOTROPIC-各向异性模式,1逻辑单位=自定义,X和Y正方向,原点可自定义,逻辑单位与设备单位的比例在水平和垂直方向上可不一致。

X的1个逻辑单位 = 自定义1

Y的1个逻辑单位 = 自定义2

2)设置逻辑单位与设备单位的比例(MM_ISOTROPIC/MM_ANISOTROPIC)

设置逻辑:

BOOL   SetViewportExtEx(

HDC   hdc,//设备上下文句柄

int   nXExtent,///设备单位X尺度

int   nYExtent,////设备单位Y尺度

LPSIZE  lpSize///设备单位元尺度旧比例,可为NULL

);//成功返回TRUE,失败返回FALSE。

设置设备:

BOOL   SetWindowExtEx(

HDC   hdc,//设备上下文句柄

int   nXExtent,///逻辑单位X尺度

int   nYExtent,////逻辑单位Y尺度

LPSIZE  lpSize///逻辑单位元尺度旧比例,可为NULL

);//成功返回TRUE,失败返回FALSE。

SetViewportExtEx(hdc,1,1,NULL);

SetWindowExtEx(hdc,2,3,NULL);

即:X方向:1逻辑=2设备

Y方向:1逻辑=3设备

也等价于(只要成比例):

SetViewportExtEx(hdc,1000,1000,NULL);

SetWindowExtEx(hdc,2000,3000,NULL);

另外:若设置有负值,意味自身轴方向改变了,但还是成比例。

SetViewportExtEx(hdc,-1,1,NULL);

SetWindowExtEx(hdc,2,-3,NULL);

 

设置逻辑坐标原点位置:

SetViewportOrgEx(hdc,0,32,NULL);//逻辑原点位置(0,32)。

设置窗口(设备)坐标显示原点位置:

SetWindowOrgEx(hdc,0,32,NULL);//设备原点位置(0,32)(仍是左上角位置)。

posted @ 2019-10-10 13:29  浩月星空  阅读(495)  评论(0编辑  收藏  举报