Visual C++ 7.1Visual Studio 6Visual C++ 7.0Windows 2003Windows 2000Visual C++ 6.0Windows XPMFC中级开发Visual StudioWindowsC++
如何快速轻松地制作渐变色图像






3.20/5 (10投票s)
想知道 Photoshop 和其他软件是如何生成渐变色的吗?
引言
本文档解释了如何在您的 Windows 应用程序中绘制渐变色。本文档需要一些 MFC 类和 GUI 的基本知识。下面的代码非常简单且注释良好 - 我注释掉了我认为可能需要注释的每一句话。 核心思想是获取两种颜色的 RGB 值,然后使用这些颜色以及介于它们之间的所有 256 种颜色来绘制和填充矩形,从而创建像我们在设置和安装程序中看到的渐变图像。
我仍然是一个初学者程序员,如果您对本文档有任何评论或建议,我将非常乐意收到您的反馈。 另外,如果您有任何问题,可以通过 mohgdeisat@hotmail.com 与我联系。
Gradient.h
#if !defined(AFX_GRADIENT1_H__39634012_8104_4550_A02B_65C0C7553A60__INCLUDED_) #define AFX_GRADIENT1_H__39634012_8104_4550_A02B_65C0C7553A60__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 class CGradient { public: CGradient(CSize=CSize(800,600)); virtual ~CGradient(); //members void PrepareVertical(CDC *pDC,UINT RTop, UINT GTop,UINT BTOP,UINT RBot,UINT GBot,UINT BBot); void PrepareHorizontal(CDC *pDC,UINT RRight, UINT GRight,UINT BRight,UINT RLeft,UINT GLeft,UINT BLeft); CSize GetDimensions(); void SetDimensions(CSize Size); void Draw(CDC *pDC, int xDest,int yDest,int xSrc, int ySrc, int Width, int Height,DWORD Rop); protected: CDC *m_dcMem; CSize m_Size; }; #endif // !defined(AFX_GRADIENT1_H__39634012_8104_4550_A02B_65C0C7553A60__INCLUDED_)
类的实现代码如下
// Gradient1.cpp: implementation of the CGradient class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Gradient.h" #include "Gradient1.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CGradient::CGradient(CSize Size) { m_Size=Size; m_dcMem=NULL; } CGradient::~CGradient() { if(m_dcMem!=NULL) delete m_dcMem; } CSize CGradient::GetDimensions() { return m_Size; } void CGradient::SetDimensions(CSize Size) { m_Size=Size; } void CGradient::PrepareVertical(CDC *pDC,UINT RTop, UINT GTop,UINT BTop,UINT RBot,UINT GBot,UINT BBot) { //Here we will create a memory bitmap and draw the colored bitmap on it //using my pretty Algorithm for generating colors. //if we have already a drawn DC then delete it so we will not have a //memory leak if(m_dcMem!=NULL) { delete m_dcMem; } //create the Memory Bitmap CBitmap Bitmap; m_dcMem=new CDC; //new Device Context m_dcMem->CreateCompatibleDC(pDC); //Make it Compatible with pDC m_dcMem->SetMapMode(MM_TEXT); //Pixels Mapping Mode //Make the Bitmap compatible with the memory DC Bitmap.CreateCompatibleBitmap(pDC,m_Size.cx,m_Size.cy); //Select the bitmap into the memory DC m_dcMem->SelectObject(&Bitmap); //////////////////////////////////////////////////////////////// ////Drawing The Gradient in a MemDC //////////////////////////////////////////////////////////////// //ALGORITHM: //We will have the RGB values of the color at which we will start //and the RGB values of the color at which we will end //we will fill 256 rectangles using all colors that lie between //these two colors. this is done by moving the R,G, and B values slowly //from the Starting color to the Ending Color. //For example: if we have RTop=100 and RBot=150 then we will draw 256 //rectangles colored with the R-values of 100,100+(150-100)/256, //100+2*(150-100)/256,100+3*(150-100)/256,... //and the same will happen to G and B values. //rStep,gStep, and bStep are variables that will be used //to hold the values at which R,G,B will be changed respectivily //For example: if we have RTop=100 and RBot=150 then //rStep=(150-100)/256 so when we start at R=100 and draw 256 rectangles //we will end at R=150 when we finish drawing these rectangles double rStep,gStep,bStep; double rCount,gCount,bCount; double RectHeight=m_Size.cy/256.0; const int NUM_COLORS=256; //We will start counting from TopColor to BottomColor //So we give an initial value of the TopColor rCount=RTop; gCount=GTop; bCount=BTop; //Calcualte the step of R,G,B values rStep=-((double)RTop-RBot)/NUM_COLORS; gStep=-((double)GTop-GBot)/NUM_COLORS; bStep=-((double)BTop-BBot)/NUM_COLORS; for(int ColorCount=0;ColorCount<NUM_COLORS;ColorCount++) { //Draw using current RGB values and Change RGB values //to represent the next color in the chain m_dcMem->FillRect(CRect(0,ColorCount*RectHeight, m_Size.cx,(ColorCount+1)*RectHeight), &CBrush(RGB(rCount,gCount,bCount))); rCount+=rStep; gCount+=gStep; bCount+=bStep; } } void CGradient::PrepareHorizontal(CDC *pDC,UINT RLeft, UINT GLeft,UINT BLeft,UINT RRight,UINT GRight,UINT BRight) { if(m_dcMem!=NULL) { delete m_dcMem; } CBitmap Bitmap; m_dcMem=new CDC; m_dcMem->CreateCompatibleDC(pDC); m_dcMem->SetMapMode(MM_TEXT); Bitmap.CreateCompatibleBitmap(pDC,m_Size.cx,m_Size.cy); m_dcMem->SelectObject(&Bitmap); //////////////////////////////////////////////////////////////// ////Drawing The Gradient in a MemDC double rStep,gStep,bStep; double rCount,gCount,bCount; double RectWidth=m_Size.cx/256.0; const int NUM_COLORS=256; rCount=RRight; gCount=GRight; bCount=BRight; rStep=-((double)RRight-RLeft)/NUM_COLORS; gStep=-((double)GRight-GLeft)/NUM_COLORS; bStep=-((double)BRight-BLeft)/NUM_COLORS; for(int ColorCount=0;ColorCount<NUM_COLORS;ColorCount++) { m_dcMem->FillRect(CRect(ColorCount*RectWidth, 0,(ColorCount+1)*RectWidth,m_Size.cy), &CBrush(RGB(rCount,gCount,bCount))); rCount+=rStep; gCount+=gStep; bCount+=bStep; } } void CGradient::Draw(CDC *pDC, int xDest,int yDest, int xSrc, int ySrc, int Width, int Height,DWORD Rop) { //Use BitBlt to Draw on a DC pDC->BitBlt(xDest,yDest,Width,Height,m_dcMem,xSrc,ySrc,Rop); }