1. 程式人生 > >跟我一起玩Win32開發(23):漸變顏色填充

跟我一起玩Win32開發(23):漸變顏色填充

GradientFill函式可以對特定的矩形區域或者三角形區域進行漸變顏色的填充。我們先來看看GradientFill函式到底長得什麼樣子,帥不帥。

BOOL GradientFill(
  _In_  HDC hdc,
  _In_  PTRIVERTEX pVertex,
  _In_  ULONG nVertex,
  _In_  PVOID pMesh,
  _In_  ULONG nMesh,
  _In_  ULONG ulMode
);

引數涉及結構體,於是有些人就開始感到痛苦了,呼叫函式一遇到結構體就會痛苦,而這個函式更痛苦,還要結構體的陣列。

人家達摩祖師說了,痛苦是你的事,和API無關,它又不會因為你痛苦就變得簡單易用,該簡單的就簡單,該複雜的還是那麼複雜。我們來分析一個吧。首先第一個hdc就不用我說了,就是某個上下文,這個上下文你就理解為和誰有關,就是誰的控制代碼,控制代碼是一種資源標識,以前說過了,就好比身份證號碼可以唯一標識你的身份一般(假身份證除外)。所以,這個hdc就是決定你要把漸變顏色畫到哪裡,畫到視窗上就是視窗的HDC,畫到桌面上就是桌面的HDC。

第二個引數,注意,是TRIVERTEX結構體的陣列,陣列中每一個TRIVERTEX結構體的變數指定一個漸變點的座標和顏色,顏色是ARGB四通道的,也就是說你可以玩透明效果,A,R,G,B每個值的範圍,MSDN上有說明是The color information of each channel is specified as a value from 0x0000 to 0xff00,這個範圍用十進位制表示到底是多少,自己開啟“計算器”算一下就知道了,Win7以後的計算器程式嚴重強大,用來算命都可以,更別說進位制換算了。

如果你寫C++程式多了,你就會猜到第三個引數是什麼了,凡是涉及到傳陣列作為引數的,後面肯定要帶一個引數指明陣列中有多少個元素。因為C語言的陣列與託管語言不同,其實它是善變的,你定義了int a[3] ....,然後你賦值的時候,賦到a[5]都可以,雖然會報錯,但是你不妨試試,即使報錯,但是仍然可以取到值,因為記憶體分佈是連續的。

不用說,nVertex 就是指明前面pVertex的個數;後面一個pMesh又是一個結構體的陣列,但它是“雄雌同體”的,可以是GRADIENT_TRIANGLE結構體的陣列,也可以是GRADIENT_RECT結構體的陣列,具體得看你想怎麼填充,從名字就知道,GRADIENT_TRIANGLE是三角形填充,就是填充出來的區域是三角形的,這個應該好理解,就是你的內褲的形狀;而GRADIENT_RECT更好理解了,矩形,就是小學老師教你的長方形,正方形。

接著這個nMesh 引數你肯定知道了,不解釋了,你懂的。

最後一個引數就是指定怎麼填充,無非就是水平填過去,還是垂直填下來之類的。

那麼,TRIVERTEX陣列與GRADIENT_RECT或GRADIENT_TRIANGLE陣列是如何對應的呢?

GRADIENT_TRIANGLE是定義三角形的,要確定一個三角形就得要三個點,所以這些點就從TRIVERTEX陣列來,每個TRIVERTEX變數定義一個點。

比如,TRIVERTEX陣列有六個元素,就有六個點,剛好可以定義兩個三角形,GRADIENT_TRIANGLE中的三個成員就是三角形三個點的索引,這些索引就是TRIVERTEX陣列中的元素的索引,六個點,索引是0,1,2,3,4,5,接著,如果第一個GRADIENT_TRIANGLE中的三個成員分別設為0,1,2,則六個點中前三個點就定義了第一個三角形,如果第二個GRADIENT_TRIANGLE的三個成員設定為3,4,5,那麼,六個點中的後三個點組成一個三角形。如果是1,4,5,就說明六個點中的第二個,第五個和第六個點將組成一個三角形。

GRADIENT_RECT就更好理解了,兩個點就可以確定一個矩形,即左上角的點,右下角的點,如果漸變點有四個,正好可以組成兩個矩形。0和1,2和3.

下面的程式碼將畫出兩個矩形的填充區域。

	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此新增任意繪圖程式碼...
		TRIVERTEX trives[4];
		trives[0].x=10;
		trives[0].y=12;
		trives[0].Alpha=0xff00;
		trives[0].Red=0xe100;
		trives[0].Green=0x00cc;
		trives[0].Blue=0xa3c3;
		trives[1].x=188;
		trives[1].y=80;
		trives[1].Alpha=0xff00;
		trives[1].Red=0x00fa;
		trives[1].Green=0x0068;
		trives[1].Blue=46;
		trives[2].x=280;
		trives[2].y=190;
		trives[2].Alpha=0xff00;
		trives[2].Red=0x0004;
		trives[2].Green=0x0017;
		trives[2].Blue=0xff00;
		trives[3].x=500;
		trives[3].y=320;
		trives[3].Alpha=0xff00;
		trives[3].Red=0xfac0;
		trives[3].Green=0xcccc;
		trives[3].Blue=0xcef0;

		// 定義漸變區為矩形,並確定其點
		GRADIENT_RECT rects[2];
		rects[0].UpperLeft=0;
		rects[0].LowerRight=1;
		rects[1].UpperLeft =2;
		rects[1].LowerRight=3;

		GradientFill(hdc,trives,4,rects,2,GRADIENT_FILL_RECT_H);

		EndPaint(hWnd, &ps);
		break;

最後就得到如下圖所示的效果。


好,下面我們看看三角形的。

		// 三角形
		GRADIENT_TRIANGLE triangles[2];
		triangles[0].Vertex1=2;
		triangles[0].Vertex2=0;
		triangles[0].Vertex3=3;
		triangles[1].Vertex1=3;
		triangles[1].Vertex2=1;
		triangles[1].Vertex3=0;

		// 矩形填充
		GradientFill(hdc,trives,4,rects,2,GRADIENT_FILL_RECT_V);
		// 三角形填充
		GradientFill(hdc,trives,4,triangles,2,GRADIENT_FILL_TRIANGLE);

我們用的還是前面填充矩形的四個點,那有人會問了,不對啊,四個怎麼能弄出兩個三角形呢,不是應該要六個點嗎?是啊,是六個點,但是這個四個點是可以重複利用,現在都說要環保,所以迴圈利用,2-0-3組成一個三角形,3-1-0又組成一個三角形。反正就是一個排列組合,你只要每個三角形弄足三個點就行了。前面的矩形同樣道理,你只要每個矩形弄夠兩個點就行了。這就很像WPF中使用的三角形建模的三維圖形同理,點的集合我就定義這麼多個,但是我在其中任取三個就可以組成一個“模型單元”。

與前面的程式碼合併執行,最後得到這種效果。