程序简介
这个程序模拟了刮刮乐的刮卡操作,按下鼠标左键并移动可以刮开刮卡层。
刮卡操作是通过掩码图实现的,一张隐藏的待刮开背景图,一张掩码图。
刮卡的时候,是在黑色的掩码图上画线,显示的时候,通过掩码图将背景图显示出来。
现在具体说一下显示方式:
首先,背景图就是普通的 IMAGE 对象,不做任何处理。
其次,掩码图中,未刮开区域对应的是黑色,已刮开区域对应的是白色。
显示的步骤:
1. 将背景图中未刮开的区域置为黑色:
操作目标(D):背景图
 操作源(S):掩码图
 操作:背景图 AND 掩码图
 ⇒ 操作目标 AND 操作源 ⇒ D a S ⇒ DSa(后缀表达式),可以在三元光栅操作码中找到 DSa 对应的操作码是 008800C6(SRCAND)。
2. 将覆盖层中已刮开的区域置为黑色:
操作目标(D):覆盖层
 操作源(S):掩码图
 操作:覆盖层 AND (NOT 掩码图)
 ⇒ 操作目标 AND (NOT 操作源) ⇒ D a (n S) ⇒ DSna(后缀表达式),可以在三元光栅操作码中找到 DSna 对应的操作码是 00220326。
3. 将背景图合并到覆盖层中,就是将前两步的 IMAGE 图像进行 OR 操作合并:
操作目标(D):覆盖层
 操作源(S):背景图
 操作:覆盖层 OR 背景图
 ⇒ 操作目标 OR 操作源 ⇒ D o S ⇒ DSo(后缀表达式),可以在三元光栅操作码中找到 DSo 对应的操作码是 00EE0086(SRCPAINT)。
以上步骤,就是显示刮卡效果的函数的原理:
  
   - 
    
     
    
    
     
      // 显示刮卡效果
     
    
- 
    
     
    
    
     
      void Show()
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     
      	IMAGE tmp = imgContent;
     
    
- 
    
     
    
    
     
      	SetWorkingImage(&tmp);
     
    
- 
    
     
    
    
     
      	putimage(
      0, 
      0, &imgMask, SRCAND);					
      // 将背景图中未刮开的区域置为黑色
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      	SetWorkingImage();
     
    
- 
    
     
    
    
     
      	putimage(offsetx, offsety, &imgMask, 
      0x00220326);	
      // 将覆盖层中已刮开的区域置为黑色
     
    
- 
    
     
    
    
     
      	putimage(offsetx, offsety, &tmp, SRCPAINT);			
      // 将背景图合并到覆盖层中
     
    
- 
    
     
    
    
     
      }
     
    
同时,该程序还使用了用图像填充区域的技术,以及输出字符符号的技术。
程序执行效果:

友情提示:更换一下刮奖区的文字,可能是一件有趣的事情。
完整源代码:
  
   - 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      //
     
    
- 
    
     
    
    
     
      // 程序名称:C语言刮刮乐(掩码图的范例)
     
    
- 
    
     
    
    
     
      // 编译环境:Visual C++ 6.0 ~ 2019,EasyX_20220116
     
    
- 
    
     
    
    
     
      //
     
    
- 
    
     
    
    
     
      #include <graphics.h>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      const 
      int offsetx = 
      170;		
      // 刮奖区的偏移 x 坐标
     
    
- 
    
     
    
    
     
      const 
      int offsety = 
      260;		
      // 刮奖区的偏移 y 坐标
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      IMAGE imgContent(300, 100);		
      // 刮开后的内容
     
    
- 
    
     
    
    
     
      IMAGE imgMask(300, 100);		
      // 已刮部分的掩码层
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 绘制刮刮卡
     
    
- 
    
     
    
    
     
      void DrawCard()
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     	
      // 白色背景
     
    
- 
    
     
    
    
     
      	setbkcolor(
      0xf0f0f0);
     
    
- 
    
     
    
    
     
      	cleardevice();
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
      // 设置刮刮卡填充单元
     
    
- 
    
     
    
    
     	
      IMAGE unit(32, 32);
     
    
- 
    
     
    
    
     
      	SetWorkingImage(&unit);						
      // 设置绘图设备为 unit 对象
     
    
- 
    
     
    
    
     
      	setbkcolor(
      0x1a3bf0);						
      // 设置背景色
     
    
- 
    
     
    
    
     
      	cleardevice();
     
    
- 
    
     
    
    
     
      	settextstyle(
      20, 
      0, _T(
      "Webdings"), 
      0, 
      0, 
      400, 
      false, 
      false, 
      false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH);	
      // 设置图标字体
     
    
- 
    
     
    
    
     
      	settextcolor(
      0x152fe5);
     
    
- 
    
     
    
    
     
      	outtextxy(
      0, 
      16, 
      0x59);						
      // 输出两个心
     
    
- 
    
     
    
    
     
      	outtextxy(
      16, 
      0, 
      0x59);
     
    
- 
    
     
    
    
     
      	settextcolor(
      0x284ff5);
     
    
- 
    
     
    
    
     
      	outtextxy(
      0, 
      0, 
      0x73);						
      // 输出两个问号
     
    
- 
    
     
    
    
     
      	outtextxy(
      16, 
      16, 
      0x73);
     
    
- 
    
     
    
    
     
      	SetWorkingImage();
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
      // 用 IMAGE 对象填充矩形区域
     
    
- 
    
     
    
    
     
      	setfillstyle(BS_DIBPATTERN, NULL, &unit);	
      // 设置填充模式
     
    
- 
    
     
    
    
     
      	solidrectangle(
      150, 
      30, 
      490, 
      450);			
      // 画填充矩形
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      	TCHAR s[] = _T(
      "刮刮乐");
     
    
- 
    
     
    
    
     
      	settextstyle(
      80, 
      0, _T(
      "黑体"), 
      0, 
      0, 
      400, 
      false, 
      false, 
      false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH);
     
    
- 
    
     
    
    
     
      	setbkmode(TRANSPARENT);
     
    
- 
    
     
    
    
     
      	settextcolor(
      0x034089);
     
    
- 
    
     
    
    
     
      	outtextxy(offsetx + (
      300 - textwidth(s)) / 
      2 + 
      5, 
      105, s);
     
    
- 
    
     
    
    
     
      	settextcolor(
      0x10c2fe);
     
    
- 
    
     
    
    
     
      	outtextxy(offsetx + (
      300 - textwidth(s)) / 
      2, 
      100, s);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
      // 设置覆盖层填充单元
     
    
- 
    
     
    
    
     	
      IMAGE unit2(80, 50);
     
    
- 
    
     
    
    
     
      	SetWorkingImage(&unit2);					
      // 设置绘图设备为 unit 对象
     
    
- 
    
     
    
    
     
      	setbkcolor(LIGHTGRAY);
     
    
- 
    
     
    
    
     
      	cleardevice();
     
    
- 
    
     
    
    
     
      	settextstyle(
      20, 
      0, _T(
      "黑体"), 
      150, 
      150, 
      400, 
      false, 
      false, 
      false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH);
     
    
- 
    
     
    
    
     
      	settextcolor(
      0x606060);
     
    
- 
    
     
    
    
     
      	outtextxy(
      10, 
      20, _T(
      "刮奖区"));
     
    
- 
    
     
    
    
     
      	SetWorkingImage();
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
      // 用 IMAGE 对象填充矩形区域
     
    
- 
    
     
    
    
     
      	setfillstyle(BS_DIBPATTERN, NULL, &unit2);	
      // 设置填充模式
     
    
- 
    
     
    
    
     
      	solidrectangle(offsetx, offsety, offsetx + 
      300, offsety + 
      100);		
      // 画填充矩形
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 初始化刮奖区内容
     
    
- 
    
     
    
    
     
      void InitContent()
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     	
      // 绘制刮奖区内容
     
    
- 
    
     
    
    
     
      	SetWorkingImage(&imgContent);
     
    
- 
    
     
    
    
     
      	setbkcolor(
      0x05d5ff);
     
    
- 
    
     
    
    
     
      	cleardevice();
     
    
- 
    
     
    
    
     
      	settextcolor(
      0x0024b8);
     
    
- 
    
     
    
    
     
      	TCHAR s1[] = _T(
      "EasyX");
     
    
- 
    
     
    
    
     
      	TCHAR s2[] = _T(
      "点亮你的创造力");
     
    
- 
    
     
    
    
     
      	settextstyle(
      40, 
      0, _T(
      "黑体"), 
      0, 
      0, 
      900, 
      false, 
      false, 
      false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH);
     
    
- 
    
     
    
    
     
      	outtextxy((
      300 - textwidth(s1)) / 
      2, 
      10, s1);
     
    
- 
    
     
    
    
     
      	outtextxy((
      300 - textwidth(s2)) / 
      2, 
      50, s2);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
      // 绘制刮卡的掩码图
     
    
- 
    
     
    
    
     
      	SetWorkingImage(&imgMask);
     
    
- 
    
     
    
    
     
      	setbkcolor(BLACK);
     
    
- 
    
     
    
    
     
      	cleardevice();
     
    
- 
    
     
    
    
     
      	setlinestyle(PS_SOLID, 
      10);		
      // 设置刮卡操作的粗细
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      	SetWorkingImage();
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 实现刮卡操作
     
    
- 
    
     
    
    
     
      void Scrape(int x1, int y1, int x2, int y2)
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     
      	SetWorkingImage(&imgMask);
     
    
- 
    
     
    
    
     
      	line(x1, y1, x2, y2);
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 显示刮卡效果
     
    
- 
    
     
    
    
     
      void Show()
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     
      	IMAGE tmp = imgContent;
     
    
- 
    
     
    
    
     
      	SetWorkingImage(&tmp);
     
    
- 
    
     
    
    
     
      	putimage(
      0, 
      0, &imgMask, SRCAND);					
      // 将背景图中未刮开的区域置为黑色
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      	SetWorkingImage();
     
    
- 
    
     
    
    
     
      	putimage(offsetx, offsety, &imgMask, 
      0x00220326);	
      // 将覆盖层中已刮开的区域置为黑色
     
    
- 
    
     
    
    
     
      	putimage(offsetx, offsety, &tmp, SRCPAINT);			
      // 将背景图合并到覆盖层中
     
    
- 
    
     
    
    
     
      }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 主函数
     
    
- 
    
     
    
    
     
      int main()
     
    
- 
    
     
    
    
     
      {
     
    
- 
    
     
    
    
     
      	initgraph(
      640, 
      480);	
      // 初始化图形窗口
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      	DrawCard();				
      // 绘制刮刮乐卡片
     
    
- 
    
     
    
    
     
      	InitContent();			
      // 初始化刮奖区内容
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
      // 获取鼠标消息,实现刮卡操作
     
    
- 
    
     
    
    
     
      	ExMessage msg;
     
    
- 
    
     
    
    
     	
      int x, y, oldx, oldy;
     
    
- 
    
     
    
    
     	
      bool scrape = 
      false;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
      while(
      true)
     
    
- 
    
     
    
    
     
      	{
     
    
- 
    
     
    
    
     
      		msg = getmessage(EM_MOUSE);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     		
      switch(msg.message)
     
    
- 
    
     
    
    
     
      		{
     
    
- 
    
     
    
    
     			
      case WM_LBUTTONDOWN:
     
    
- 
    
     
    
    
     
      				scrape = 
      true;
     
    
- 
    
     
    
    
     
      				x = oldx = msg.x - offsetx;
     
    
- 
    
     
    
    
     
      				y = oldy = msg.y - offsety;
     
    
- 
    
     
    
    
     
      				Scrape(oldx, oldy, x, y);
     
    
- 
    
     
    
    
     				
      break;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     			
      case WM_LBUTTONUP:
     
    
- 
    
     
    
    
     
      				scrape = 
      false;
     
    
- 
    
     
    
    
     				
      break;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     			
      case WM_MOUSEMOVE:
     
    
- 
    
     
    
    
     				
      if (scrape)
     
    
- 
    
     
    
    
     
      				{
     
    
- 
    
     
    
    
     
      					oldx = x;
     
    
- 
    
     
    
    
     
      					oldy = y;
     
    
- 
    
     
    
    
     
      					x = msg.x - offsetx;
     
    
- 
    
     
    
    
     
      					y = msg.y - offsety;
     
    
- 
    
     
    
    
     
      					Scrape(oldx, oldy, x, y);
     
    
- 
    
     
    
    
     
      				}
     
    
- 
    
     
    
    
     				
      break;
     
    
- 
    
     
    
    
     
      		}
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     		
      // 显示当前结果
     
    
- 
    
     
    
    
     
      		Show();
     
    
- 
    
     
    
    
     
      	}
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     	
      return 
      0;
     
    
- 
    
     
    
    
     
      }
     
    
 转载:https://blog.csdn.net/yx5666/article/details/128631621
 
					
 https://space.bilibili.com/1827181878?spm_id_from=333.788.0.0
https://space.bilibili.com/1827181878?spm_id_from=333.788.0.0