C语言 实现带透明度的鼠标光标 .cur 编辑器

2024-04-20 06:12

本文主要是介绍C语言 实现带透明度的鼠标光标 .cur 编辑器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

操作参考: 

.cur 鼠标光标编辑器-CSDN博客

增加了滑块修改透明度

有一个bug,就是取色在绘图板上取色时,取到的颜色的透明度是0,也就是说,同样的颜色,有的是透明出来的,有的就是本身的颜色。但是不打算改了,这样的具有启发的BUG就留作纪念,如果想取色带透明度,可以在直接定位到代码里的 mesh 数组,这个数组里存着网格的32位带透明通道的颜色,获取当前像素颜色,就可以直接变成读取所在数组的颜色。 


//代码来源:色环https://codebus.cn/luoyh/colorcircle
//代码来源:alpha透明贴图: https://codebus.cn/yangw/transparent-putimage//代码来源:cur格式:https://mp.weixin.qq.com/s?__biz=MzkwNzMzMjIyNg==&mid=2247486257&idx=1&sn=1656090e498c22f391c00d0857f4b856&chksm=c0db94dcf7ac1dcacd4618240e05595b984a05b55d5f9f44d277aae41f4353b06bfa5e4294c4&cur_album_id=2474385342163419137&scene=189#wechat_redirect
//代码来源:icon格式生成文件:https://blog.csdn.net/jinzhuojun/article/details/8007586
#include <stdio.h>
#include <graphics.h>
#include<math.h>
#pragma warning(disable : 4996)		// VS2022 对某些函数警告,但是为了方便移植,就无视这些警告 这样 Devc++ VC2010 VS2022 都能跑#define PI acos(-1.0)// 鼠标文件解析
//https://mp.weixin.qq.com/s?__biz=MzkwNzMzMjIyNg==&mid=2247486257&idx=1&sn=1656090e498c22f391c00d0857f4b856&chksm=c0db94dcf7ac1dcacd4618240e05595b984a05b55d5f9f44d277aae41f4353b06bfa5e4294c4&cur_album_id=2474385342163419137&scene=189#wechat_redirect
// 代码来源
//https://blog.csdn.net/jinzhuojun/article/details/8007586
// 中文注释添加自 @ bilibili 民用级脑的研发记录
// 结构注释来自 https://learn.microsoft.com/en-us/previous-versions/ms997538(v=msdn.10)// 注意这个格式和下文中的 WrietByte 的对应关系//typedef struct
//{
//    WORD           idReserved;   // Reserved (must be 0)
//    WORD           idType;       // Resource Type (1 for icons)									// 2 指的是 cur 鼠标静态光标文件
//    WORD           idCount;      // How many images?
//    ICONDIRENTRY   idEntries[1]; // An entry for each image (idCount of 'em)
//} ICONDIR, *LPICONDIR;//typedef struct
//{
//    BYTE        bWidth;          // Width, in pixels, of the image
//    BYTE        bHeight;         // Height, in pixels, of the image
//    BYTE        bColorCount;     // Number of colors in image (0 if >=8bpp)
//    BYTE        bReserved;       // Reserved ( must be 0)
//    WORD        wPlanes;         // Color Planes
//    WORD        wBitCount;       // Bits per pixel
//    DWORD       dwBytesInRes;    // How many bytes in this resource?
//    DWORD       dwImageOffset;   // Where in the file is this image?
//} ICONDIRENTRY, *LPICONDIRENTRY;
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>// 色环
void DrawColorCircle(int x, int y, int r, int h)
{int H = h;float S = 1.f;float V = 1.f;for (int i = 0; i < 360; i++){H = int(H + 1) % 360;setfillcolor(HSVtoRGB((float)H, S, V));solidpie(x - r, y - r, x + r, y + r, i * (PI / 180), (i + 1) * (PI / 180));}
}// 数据写入
void Fwrite(FILE* f, char* data, int byte)				// 一次写入 byte 个字节,且只写一次
{if(1!=fwrite(data,byte,1,f)){perror("fwrite error");exit(1);}
}
// 数据写入
void WriteByte(FILE* f, unsigned int val,int byte)		// 指定写入几个字节
{char data[4];assert(byte<=4);									// 如果它的条件返回错误,则终止程序执行——菜鸟教程可查memcpy((void*)data,(void*)&val,byte);Fwrite(f,data,byte);
}
// 生成cur 格式文件 ,改写自 icon格式文件的生成,仅仅是 wPlane wBitCount 分别作为X,Y热点
void generate_ico_file(const char* filename,char * body,int width, int height, int has_alpha,int HotX,int HotY)
{int x,y;int index=0;int Size=0;int offset = 6+ 1*16;								// 6 = 2 +2 +2,这6个byte 是ico,cur通用的文件头。 16= 1+1+1+1 +2 +2,是一个图片的索引占 16 个字节, n个图片的索引占6*16个字节,,n个图片的因为在不同设备上使用不同型号分辨率的图片,这一堆图片都在一个 icon 或cur里int bpp=32;											// 32位的位图= 8位 alpha + 8 位 R, 8 位 G, 8 位 BFILE* outfile=fopen(filename,"wb");if(outfile==NULL){perror("fopen error");exit(1);}// icon文件头,类型与图片个数WriteByte(outfile,0,2);								// idReserved 保留位,一种格式,可用区分其他文件。WriteByte(outfile,1,2);								// idType 文件类型,如果是1 ,就是icon文件,如果是2 则是cur鼠标光标文件,这类文件格式一样。WriteByte(outfile,1,2);								// idCount 拥有的图片个数,icon为在不同屏幕上正常显示,会存储多个格式的图片以备选择// 具体一个图片的索引信息WriteByte(outfile,width,1);							// bWidthWriteByte(outfile,height,1);						// bHeightWriteByte(outfile,0,1);								// bColorCountWriteByte(outfile,0,1);								// bReserveredWriteByte(outfile,HotX,2);								// wPlanes					// 这里是.cur热点位置 XWriteByte(outfile,HotY,2);							// wBitCount					// 这里是.cur热点位置 YSize = 40 + height * ((width + 31) / 32 * 32 / 8 + width * 3);	//Note 4 bytes alignment		// 这里计算文件索引头与图像数据的总数 ,40=4+4+4+2+2+4*6 个字节。 (width+31)/32是计算int 型AND 位图个数,width / 32,但是不能确定%32 的部分,所以+31 然后再除以 32 。1个int 有4个字节,共32bit,每个bit表示一个像素是否被光栅操作 AND 覆盖,行数 * 32计算一共需要多少bit ,/8是确定有多少字节。if (bpp == 32)Size += height * width;WriteByte(outfile,Size, 4);			//dwBytesInResWriteByte(outfile,offset, 4);			//dwImageOffsetWriteByte(outfile,40, 4);				//biSizeWriteByte(outfile,width, 4);			//biWidthWriteByte(outfile,2 * height, 4);		//biHeightWriteByte(outfile,1, 2);				//biPlanesWriteByte(outfile,bpp, 2);				//biBitCountWriteByte(outfile,0, 4);				//biCompressionWriteByte(outfile,0, 4);				//biSizeImageWriteByte(outfile,0, 4);				//biXPelsPerMeterWriteByte(outfile,0, 4);				//biYPelsPerMeterWriteByte(outfile,0, 4);				//biClrUsedWriteByte(outfile,0, 4);				//biClrImportant// XOR maskfor (y=height - 1 ; y >= 0; --y)   					// 调换打印高度就不会读取了 ,确定为倒置打印,windows倒着读取数据.从左往右,从下往上,所以为了图片倒着读取之后是正的,需要把原图第一行像素数据打印到倒数最后一行{for (x = 0; x < width; ++x){index = (y * width + x) * 4;WriteByte(outfile, body[index], 1);        //BlueWriteByte(outfile, body[index + 1], 1);    //GreenWriteByte(outfile, body[index + 2], 1);    //RedWriteByte(outfile, has_alpha ? body[index + 3] : 255, 1); //Alpha}}// AND maskfor (y = 0; y < (height * ((width + 31) / 32 * 32 / 8)); ++y){WriteByte(outfile, 1, 1);						// 1 在屏幕上显示图片,0则不显示图片,表示为整个图片没有。 三元光栅操作参考}fclose(outfile);
}int main()
{initgraph(1640, 980, 1);setbkcolor(GREEN);cleardevice();int** mesh;int drawdesklx;					// 绘图板左上角坐标int drawdeskly;int pixnum;						// 一个正方形瓦片边长像素int mapi;						// 一列有多少个小方格int mapj;						// 一行有多少个小方格int drawmapi;					// 网格坐标int drawmapj;int drawoldmapi;				// 同一次绘制的前一个涂色的位置int drawoldmapj;int isdraw;						// 绘制状态int drawdeskrx;					// 绘图板右下角坐标int drawdeskry;int drawsmallflag;isdraw=0;drawsmallflag=0;drawdesklx=200;drawdeskly=200;mapi=32;						// 默认 64*64 大小的  .cur文件	// 这里改参数只会改写分辨率,一个像素对应屏幕一个或多个像素,但不会改变图标大小。数值过大会生成失败,原因是int数值上限比较小,不够存储数据了mapj=32;														// 这里改参数只会改写分辨率,一个像素对应屏幕一个或多个像素,但不会改变图标大小。 数值过大会生成失败,原因是int数值上限比较小,不够存储数据了drawmapi=-1;drawmapj=-1;pixnum = 16 ;drawoldmapi=-1;drawoldmapj=-1;drawdeskrx=drawdesklx+pixnum*mapj;				// 瓦片个数 * 一个瓦片的像素 = 画板总长度drawdeskry=drawdeskly+pixnum*mapi;int left=0;								// 刷新绘图板的当前瓦片位置坐标int top=0;int pentake=0x8FFF0000;					// 选中的 ARGB 透明度与颜色int image[mapi * mapj];					// 分配像素内存int i, j;int background = 0x0000CCFF;			// 背景色:天依蓝,颜色按十六进制数int HotX=0;								// 鼠标热点位置int HotY=0;mesh = new int* [mapi];for(int i=0; i<mapi; i++)mesh[i]=new int[mapj];for(int i=0; i<mapi; i++){for(int j=0; j<mapj; j++){mesh[i][j]=0;						// 加入默认的背景色}}int h = 0;DrawColorCircle(800+640 / 4, 480 / 2, 140, h);		// 绘制色环setfillcolor(RGB(128, 126, 129));for (int i = 0; i < mapi ; i++){left = 0;for (int j = 0; j < mapj ; j++){int pennumber = mesh[i][j];					// 读取游戏大地图数组序号//int red =255;
//int blue =255;
//int green =255;
//green = 0x000000FF;
//
//int pixel=0x0000CCFF;
//F=1111 1111 =255;
//https://codebus.cn/yangw/transparent-putimage
//透明色混合原理与透明色计算代码来源int sa = ((pennumber & 0xff000000) >> 24);int sr = ((pennumber & 0x00ff0000) >> 16);int sg = ((pennumber & 0xff00) >> 8);int sb =   pennumber & 0xff;int dr = ((background& 0xff0000) >> 16);int dg = ((background & 0xff00) >> 8);int db =   background & 0xff;int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16)		// sr = 0 dr =255, sa=0, dst->red = 255,即sa = 0 时,dr 占优。sr = 255, dr=0, sa=255, dst->red = 255, sa=255时,sr 占优| ((sg*sa/255 + dg * (255 - sa) / 255) << 8)|  (sb*sa/255 + db * (255 - sa) / 255);setfillcolor(BGR(dst));								// COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印fillrectangle(drawdesklx+left, drawdeskly+top, drawdesklx+left + pixnum, drawdeskly+top + pixnum);left += pixnum;										// 往右移动,准备下一次绘制位置,}top += pixnum;											// 往下移动,准备下一次绘制位置}char icon[200]="图标预览";
//	setbkmode(TRANSPARENT);													// 设置背景为透明settextcolor(BLACK);													// 设置字颜色为黑outtextxy(40,160,icon);													// 打印提示setfillcolor(GREEN);fillrectangle(10,100,300,140) ;											// 覆盖之前的文字提示char tips[200];sprintf(tips,"热点位置 HotX HotY = %d,%d",HotX,HotY);					// 格式化数字
//	setbkmode(TRANSPARENT);													// 设置背景为透明settextcolor(BLACK);													// 设置字颜色为黑outtextxy(10,100,tips);													// 打印提示int lx;										// 按钮位置,大小int ly;int rx;int ry;int width;int height;width=20;height=50;lx=1250;ly=200;rx=lx+width;ry=ly+height;int limitlx;								// 边界矩形int limitly;int limitrx;int limitry;limitlx=lx;limitly=200;limitrx=limitlx+width;limitry=600+height;							// 因为计算透明度 255除以可移动长度然后得出平均每个像素对应几个颜色 时不能方便计算可移动大小,于是直接设定可移动长度再增加一块按钮停泊区int ispressing;								// 滑块是否按下int drawsmallflagv2;						// 绘制控制int oldmx;									// 鼠标在本次拖拽时最先按下的位置int oldmy;int drawx;									// 当前绘制的位置int drawy;int drawoldx;								// 比较上一次绘制的位置,如果相同就不绘制int drawoldy;drawx=0;drawy=0;oldmx=0;oldmy=0;ispressing=0;								// 滑块未被按下drawsmallflag=0;							// 不进行绘制char tipsv2[200];							// 滑块信息,用于透明度测试int trans;									// 透明数据,0是最透明,255是完全不透明trans=255;setfillcolor(BLUE);fillrectangle(lx,ly,rx,ry);					// 绘制滑块settextcolor(BLUE);							// 字体蓝色settextstyle(19, 0, _T("黑体"));			// 设置当前字体为高 16 像素的“Consolas”。(VC6 / VC2008 / VC2010 / VC2012)sprintf(tipsv2,"当前透明度 trans 是:%d",trans);outtextxy(limitlx-50,limitly-50,tipsv2);ExMessage m;while(1){while(peekmessage(&m,EX_KEY|EX_MOUSE,1)){switch (m.message){case WM_LBUTTONDOWN:if(m.x>drawdesklx&&m.y>drawdeskly&&m.x<drawdeskrx&&m.y<drawdeskry)										// 绘制{isdraw=1;drawmapi=-1;drawmapj=-1;}else if(ispressing==0&&m.x>lx&&m.y>ly&&m.x<rx&&m.y<ry){ispressing=1;drawx=0;drawy=0;oldmx=m.x;oldmy=m.y;}break;case WM_LBUTTONUP:isdraw=0;drawoldmapi=-1;drawoldmapj=-1;drawsmallflag=0;// 滑块透明选则部分代码复制粘贴过来了if(ispressing==1){ly=drawy;ry=ly+height;ispressing=0;drawoldx=0;drawoldy=0;drawsmallflagv2=0;			// 清除数据,禁止重复绘制}break;case WM_RBUTTONDOWN:if(m.x>drawdesklx&&m.y>drawdeskly&&m.x<drawdeskrx&&m.y<drawdeskry&&m.ctrl)										// 绘制{HotY=(m.y-drawdeskly)/pixnum;HotX=(m.x-drawdesklx)/pixnum;setfillcolor(GREEN);fillrectangle(10,100,300,140) ;											// 覆盖之前的文字提示char tips[200];sprintf(tips,"热点位置 HotX HotY = %d,%d",HotX,HotY);					// 格式化数字
//						setbkmode(TRANSPARENT);													// 设置背景为透明settextcolor(BLACK);													// 设置字颜色为黑outtextxy(10,100,tips);													// 打印提示}else{pentake = getpixel(m.x,m.y);setfillcolor(pentake);fillrectangle(800,500,900,600);pentake=pentake|0xFF000000;											// 要颜色转换完毕前再补充alpha 通道,否则半透明pentake=BGR(pentake);												// 因为 getpixel 已经是 BGR了,但是在后面的上色还个BGR转换,所以还需要再转换一次BGR来抵消后面的BGR转换。// BGR转换是因为保存数据时是 RGB 保存,但是当绘制图像时,却是蓝色红色相反,所以绘制的时候要调整蓝色红色,保存的是按RGB来
//						setfillcolor(GREEN);
//						fillrectangle(800,400,1240,440);char colortips[200];sprintf(colortips,"new alpha:%d,red:%d,green:%d,blue:%d",(pentake&0xFF000000)>>24,(pentake&0x00FF0000)>>16,(pentake&0x0000FF00)>>8,(pentake&0x000000FF));outtextxy(800,400,colortips);										// 打印颜色提示int pennumber=pentake&0x00FFFFFF;	// 清除占一个字节透明度数据pentake=pennumber|(trans<<24);pennumber=pentake;setfillcolor(BGR(background));// 0000FF红色变蓝色,这样符合RGB 数据位置fillrectangle(lx+60,limitly,lx+160,limitly+100);int sa = ((pennumber & 0xff000000) >> 24);int sr = ((pennumber & 0xff0000) >> 16);int sg = ((pennumber & 0xff00) >> 8);int sb =   pennumber & 0xff;int dr = ((background& 0xff0000) >> 16);int dg = ((background & 0xff00) >> 8);int db =   background & 0xff;int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16)			// sr = 0 dr =255, sa=0, dst->red = 255,即sa = 0 时,dr 占优。sr = 255, dr=0, sa=255, dst->red = 255, sa=255时,sr 占优| ((sg*sa/255 + dg * (255 - sa) / 255) << 8)			// y=kx+b; sa = sb + (sa-sb)/1.0*x  (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);|  (sb*sa/255 + db * (255 - sa) / 255);setfillcolor(BGR(dst));								// COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印fillrectangle(lx+60,limitly+180,lx+160,limitly+280);// 文字组件覆盖int transv2=sa;sprintf(tipsv2,"当前透明度 sa 是:%d",transv2);outtextxy(limitlx+50,limitly+120,tipsv2);}break;case WM_KEYDOWN:switch (m.vkcode){case VK_F1:int width=mapj;int height=mapi;for (i = 0; i < height; ++i){for (j = 0; j < width; ++j){image[i * width + j]  = mesh[i][j];  										// 透明色 叠加 网格数据}																				// Alpha 透明 0x00, red: 00, green: 00, blue: 00  各 bit 位对应 ARGB}																					// 0x00000000是完全透明 0x5F000000 可以看出来不完全透明,可知透明度可调节generate_ico_file("testv8_透明度测试.cur", (char *)image, width, height, 1,HotX,HotY);printf("Save cur,文件名:testv8_透明度测试.cur\n");break;}}}if(isdraw){if(m.x>drawdesklx&&m.y>drawdeskly&&m.x<drawdeskrx&&m.y<drawdeskry){drawmapi=(m.y-drawdeskly)/pixnum;drawmapj=(m.x-drawdesklx)/pixnum;if(drawmapi!=drawoldmapi||drawmapj!=drawoldmapj)		// 检测是否是旧位置{mesh[drawmapi][drawmapj]=pentake;drawoldmapi=drawmapi;drawoldmapj=drawmapj;drawsmallflag=1;}}}else if(ispressing==1){drawy=ly+m.y-oldmy;if(drawy<limitly)drawy=limitly;else if(drawy+height>limitry)drawy=limitry-height;if(drawy!=drawoldy){drawoldy=drawy;drawsmallflagv2=2;}trans=255 - 255/1.0/(limitry-height-limitly)*(drawy-limitly);			// 计算多少个像素,一个像素顶0.81个透明度// 255减去计算的像素, 得到从底向上的数据}if(drawsmallflag==1){top=0;left=0;for (int i = 0; i < mapi ; i++){left = 0;for (int j = 0; j < mapj ; j++){int pennumber = mesh[i][j];							// 读取游戏大地图数组序号
//https://codebus.cn/yangw/transparent-putimage
//透明色混合原理与透明色计算代码来源int sa = ((pennumber & 0xff000000) >> 24);int sr = ((pennumber & 0xff0000) >> 16);	// 源值已经乘过了透明系数int sg = ((pennumber & 0xff00) >> 8);		// 源值已经乘过了透明系数int sb =   pennumber & 0xff;				// 源值已经乘过了透明系数int dr = ((background& 0xff0000) >> 16);int dg = ((background & 0xff00) >> 8);int db =   background & 0xff;int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16)			// y=kx+b; sa = sb + (sa-sb)/1.0*x  (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);| ((sg*sa/255 + dg * (255 - sa) / 255) << 8)			// y=kx+b; sa = sb + (sa-sb)/1.0*x  (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);|  (sb*sa/255 + db * (255 - sa) / 255);				// y=kx+b; sa = sb + (sa-sb)/1.0*x  (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);setfillcolor(BGR(dst));								// COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印fillrectangle(drawdesklx+left, drawdeskly+top, drawdesklx+left + pixnum, drawdeskly+top + pixnum);left += pixnum;										// 往右移动,准备下一次绘制位置,}top += pixnum;											// 往下移动,准备下一次绘制位置}top=0;for (int i = 0; i < mapi ; i++){left = 0;for (int j = 0; j < mapj ; j++){int pennumber = mesh[i][j];							// 读取游戏大地图数组序号
//https://codebus.cn/yangw/transparent-putimage
//透明色混合原理与透明色计算代码来源int sa = ((pennumber & 0xff000000) >> 24);int sr = ((pennumber & 0xff0000) >> 16);int sg = ((pennumber & 0xff00) >> 8);int sb =   pennumber & 0xff;int dr = ((background& 0xff0000) >> 16);int dg = ((background & 0xff00) >> 8);int db =   background & 0xff;int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16)		// y=kx+b; sa = sb + (sa-sb)/1.0*x  (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);| ((sg*sa/255 + dg * (255 - sa) / 255) << 8)		// y=kx+b; sa = sb + (sa-sb)/1.0*x  (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);|  (sb*sa/255 + db * (255 - sa) / 255);			// y=kx+b; sa = sb + (sa-sb)/1.0*x  (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);// 绘制预览图putpixel(drawdesklx-64+left,drawdeskly-32+top,BGR(dst));						// COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印left += 1;											// 往右移动,准备下一次绘制位置,}top += 1;												// 往下移动,准备下一次绘制位置}}else if(drawsmallflagv2==2){setfillcolor(RGB(150,150,150));fillrectangle(limitlx,limitly,limitrx,limitry);setfillcolor(BLUE);fillrectangle(lx,drawy,rx,drawy+height);setbkcolor(GREEN);							// 字体背景默认采用图像的背景色setfillcolor(GREEN);fillrectangle(limitlx-50,limitly-50,limitlx+300,limitly);
//			setbkmode(TRANSPARENT);						// 字体背景透明settextcolor(BLUE);							// 字体蓝色settextstyle(19, 0, _T("黑体"));		// 设置当前字体为高 16 像素的“Consolas”。(VC6 / VC2008 / VC2010 / VC2012)sprintf(tipsv2,"当前透明度 trans 是:%d",trans);outtextxy(limitlx-50,limitly-50,tipsv2);int pennumber=pentake&0x00FFFFFF;	// 清除占一个字节透明度数据pentake=pennumber|(trans<<24);pennumber=pentake;
//			int background=0x00000000;setfillcolor(BGR(background));// 0000FF红色变蓝色,这样符合RGB 数据位置fillrectangle(lx+60,limitly,lx+160,limitly+100);int sa = ((pennumber & 0xff000000) >> 24);int sr = ((pennumber & 0xff0000) >> 16);	// 源值已经乘过了透明系数int sg = ((pennumber & 0xff00) >> 8);		// 源值已经乘过了透明系数int sb =   pennumber & 0xff;				// 源值已经乘过了透明系数int dr = ((background& 0xff0000) >> 16);int dg = ((background & 0xff00) >> 8);int db =   background & 0xff;int dst = ((sr*sa/255 + dr * (255 - sa) / 255) << 16)			// sr = 0 dr =255, sa=0, dst->red = 255,即sa = 0 时,dr 占优。sr = 255, dr=0, sa=255, dst->red = 255, sa=255时,sr 占优| ((sg*sa/255 + dg * (255 - sa) / 255) << 8)			// y=kx+b; sa = sb + (sa-sb)/1.0*x  (sa,1),(sb,0); /1.0*x=/255*sa, x(0,1),sa(0,255);|  (sb*sa/255 + db * (255 - sa) / 255);setfillcolor(BGR(dst));								// COLORREF 的颜色格式是 ABGR ,需要把 RGB 转换成 BGR 格式,然后打印出画板的颜色和保存的图片颜色一样,图片按ARGB 保存,但是画板按ABGR打印fillrectangle(lx+60,limitly+180,lx+160,limitly+280);// 文字组件覆盖setfillcolor(GREEN);fillrectangle(limitlx+50,limitly+120,limitlx+300,limitly+160);int transv2=sa;sprintf(tipsv2,"当前透明度 sa 是:%d",transv2);outtextxy(limitlx+50,limitly+120,tipsv2);}Sleep(2);}return 0;
}

这篇关于C语言 实现带透明度的鼠标光标 .cur 编辑器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/919473

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

ONLYOFFICE 8.1 版本桌面编辑器测评

在现代办公环境中,办公软件的重要性不言而喻。从文档处理到电子表格分析,再到演示文稿制作,强大且高效的办公软件工具能够极大提升工作效率。ONLYOFFICE 作为一个功能全面且开源的办公软件套件,一直以来都受到广大用户的关注与喜爱。而其最新发布的 ONLYOFFICE 8.1 版本桌面编辑器,更是带来了诸多改进和新特性。本文将详细评测 ONLYOFFICE 8.1 版本桌面编辑器,探讨其在功能、用户

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议