版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://shujiantang.blogbus.com/logs/29666445.html
接下来是添加按钮图片。在MSDN中查看了位图按钮类CBitmapButton,知道按钮一共有四种状态:
1. Up(normal):弹起状态,按钮正常情况下呈现的状态。
2. Down(selected):下压状态,鼠标点击按钮或用键盘确定处于焦点状态的按钮时,按钮呈现的状态。
3. Focused:焦点状态,一般通过TAB按键将焦点调整到按钮时,按钮呈现的状态。形态上类似Up状态,一般可能带有着重边框或颜色比Up状态深。
4. Disabled:无效状态,按钮失去功效时呈现的状态,形态上类似Up状态,不过颜色一般为死灰色或比Up状态浅。
对于位图按钮来说,每个按钮需要有四种状态位图支持,其中Up位图是必须具备的,而其它三种状态的位图是可选的。
之前美工给我的按钮图片只是Up状态图片,为了表现出按钮的动态特性,我向美工请求了全状态支持位图。
MSDN中有“在对话框中包含位图按钮控件”的详细步骤:
To include a bitmap-button control in a dialog box
在对话框中包含位图按钮控件
1. Create one to four bitmap images for the button.
为按钮创建1~4个位图图片
2. Create a dialog template with an owner-draw button positioned where you want the bitmap button. The size of the button in the template does not matter.
在希望创建位图按钮的地方创建一个自绘按钮的对话框模板。模板中按钮的尺寸无关紧要。
3. Set the button's caption to a value such as "MYIMAGE" and define a symbol for the button such as IDC_MYIMAGE.
设置按钮的标题,比如“MYIMAGE”;定义按钮ID,比如IDC_MYIMAGE。
4. In your application's resource script, give each of the images created for the button an ID constructed by appending one of the letters "U," "D," "F," or "X" (for up, down, focused, and disabled) to the string used for the button caption in step 3. For the button caption "MYIMAGE," for example, the IDs would be "MYIMAGEU," "MYIMAGED," "MYIMAGEF," and "MYIMAGEX." You must specify the ID of your bitmaps within double quotes. Otherwise the resource editor will assign an integer to the resource and MFC will fail when loading the image.
在应用资源脚本中,为每个用于按钮的图片构造ID:将字母“U”、“D”、“F”或“X”(分别对应按钮的Up状态、Down状态、Focused状态和Disabled状态)附加到在第3步中设定的按钮标题字符串之后。假如按钮标题为“MYIMAGE”,则图片的ID分别为“MYIMAGEU”、“MYIMAGED”、“MYIMAGEF”和“MYIMAGEX”。在指定位图ID时,一定要为构造好的ID加上双引号。否则资源编辑器会为其分配一个整数,导致MFC加载图片时失败。
5. In your application's dialog class (derived from CDialog), add a CBitmapButton member object.
在应用的对话类(继承于CDialog)中添加CBitmapButton成员对象。
6. In the CDialog object's OnInitDialog routine, call the CBitmapButton object's AutoLoad function, using as parameters the button's control ID and the CDialog object's this pointer.
在CDialog对象的OnInitDialog函数中,调用CBitmapButton对象的AutoLoad函数,它的参数分别为按钮控件ID和CDialog对象的指针。
由于以上步骤要求按钮图片的格式为“bmp位图”格式,而美工给我的图片是“png”格式。而且美工设计的按钮是椭圆形,但边缘颜色却和我设定的透明色不一致。于是决定写一个程序进行转换(这个实现比较容易,就不麻烦美工了)。
这个转换程序的主要函数就是ConvertImage,它完成了图片边沿颜色的转换和图片类型的转换:
//转换图片
//iImageFileAddr:要转换图片文件地址
//iSaveFolderAddr:保存转换后文件的文件夹地址
//iImageType:图片的转换类型
//iSouColor:图片中需要替换的颜色
//iDesColor:图片要替换为的颜色
//iOnlyEdge:指示是否仅替换图片边沿部分(true,仅替换边沿部分;false,替换全部)
//返回值:转换成功返回true,转换失败返回false
bool CImageConverterDlg::ConvertImage(const CString& iImageFileAddr,const CString& iSaveFolderAddr,TImageType iImageType,COLORREF iSouColor,COLORREF iDesColor,bool iOnlyEdge)
{
//加载图片
CImage image;
if(image.Load(iImageFileAddr)!=0)
return false;
//转换颜色
if(iSouColor!=iDesColor)
{
if(iOnlyEdge)
{
for(int x=0;x<image.GetWidth();x++)
{
for(int y=0;y<image.GetHeight();y++)
{
if(image.GetPixel(x,y)==iSouColor)
{
image.SetPixel(x,y,iDesColor);
}
else
{
break;
}
}
for(int y=image.GetHeight()-1;y>=0;y--)
{
if(image.GetPixel(x,y)==iSouColor)
{
image.SetPixel(x,y,iDesColor);
}
else
{
break;
}
}
}
}
else
{
for(int x=0;x<image.GetWidth();x++)
{
for(int y=0;y<image.GetHeight();y++)
{
if(image.GetPixel(x,y)==iSouColor)
{
image.SetPixel(x,y,iDesColor);
}
}
}
}
}
//构造图片保存路径
CString savePath(iSaveFolderAddr);
TCHAR drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME],ext[_MAX_EXT];
::_tsplitpath_s(iImageFileAddr,drive,dir,fname,ext);
savePath+=fname;
//保存图片
switch(iImageType)
{
case EBmp:
savePath+=_T(".bmp");
if(image.Save(savePath,Gdiplus::ImageFormatBMP)!=0)
return false;
break;
case EJPEG:
savePath+=_T(".jpg");
if(image.Save(savePath,Gdiplus::ImageFormatJPEG)!=0)
return false;
break;
case EGIF:
savePath+=_T(".gif");
if(image.Save(savePath,Gdiplus::ImageFormatGIF)!=0)
return false;
break;
case EPNG:
savePath+=_T(".png");
if(image.Save(savePath,Gdiplus::ImageFormatPNG)!=0)
return false;
break;
default:
return false;
break;
}
return true;
}
ConvertImage使用CImage类实现转换功能。它是一个共享Visula C++类,我认为它是对GDI+中Image类的封装。不过对于普通的处理来说,CImage要比Image简单易用得多。
其中图片类型的转换完全是调用CImage提供的方法,比较简单。下面仅解释一下边沿颜色替换的实现。
美工给我的图片,边沿部分全为白色,我希望将其转换为程序中设置的透明色(灰色)。该函数提供了iOnlyEdge参数,如果设置为true,它会先从左到右,再从右向左,对图片每一行像素点进行检查,如果为iSouColor指定的颜色就转换为iDesColor指定的颜色,否则停止该次转换。这样就可以转换全部的边沿颜色了。而如果iOnlyEdge为false,则检查图片的每个像素点,进行以上的转换。
这样转换之后,通过VC的加载资源向导将图片加载进来,根据上述的步骤很轻松地就将所有按钮替换为位图按钮了。
至此,终于将整个程序的美化工作完成了,尽管不是太精致,但比起MFC的标准窗口,还是要养眼许多呢!