第一次寫隨筆,我本來想將win32窗口的標題欄設置成漸變色,像這樣的效果

但發現找不到設置標題欄屬性的api,SetWindowLong也只是增減窗口的固定的樣式而已。所以想到一個思路,把標題欄去掉,自己繪制一個標題欄,包括標題欄上的按鈕都自己來繪制創建。這裡用到了gdi+,對於這個庫也是剛接觸到的。
最後程序實現的效果如下。

對顏色值對應的顏色還不太了解,所以看起來有點丑。
代碼:
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
#include <windows.h>
//#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
#define ID_BUTTON1 1
#define ID_BUTTON2 2
HINSTANCE hInst;
void LoadBkImge(HDC hdc)
{
Graphics graphics(hdc);
Image image(L"pic1.png");
graphics.DrawImage(&image,0,0);
}
void FillRec(HDC hdc,Rect myRect,Color* colors,float *positions,int i)
{
Graphics graphics(hdc);
//多彩漸變色
LinearGradientBrush myLinearGradientBrush(
myRect,
Color(255,255,255,0),
Color(255,255,0,0),
LinearGradientModeVertical
);//LinearGradientModeHorizontal*/
myLinearGradientBrush.SetInterpolationColors(colors, positions, i);
graphics.FillRectangle(&myLinearGradientBrush,myRect);
}
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
hInst=hInstance;
// Initialize GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
wndClass.style = CS_HREDRAW | CS_VREDRAW|DS_CENTER;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = TEXT("Gdiplustest");
RegisterClass(&wndClass);
hWnd = CreateWindow(
TEXT("Gdiplustest"),
TEXT("Gdiplustest"),
WS_OVERLAPPED|WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
400,
250,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gdiplusToken);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
static HDC hdc;
static HWND hButton1,hButton2;
PAINTSTRUCT ps;
LPDRAWITEMSTRUCT pdis;
switch(message)
{
case WM_CREATE:
{
//窗口居中顯示
int scrWidth,scrHeight;
RECT rect;
scrWidth=GetSystemMetrics(SM_CXSCREEN);
scrHeight=GetSystemMetrics(SM_CYSCREEN);
GetWindowRect(hWnd,&rect);
rect.left=(scrWidth-rect.right)/2;
rect.top=(scrHeight-rect.bottom)/2;
SetWindowPos(hWnd,HWND_TOP,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW);
hButton1=CreateWindow("button","",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,310,5,40,30,hWnd,(HMENU)ID_BUTTON1,hInst,NULL);
hButton2=CreateWindow("button","",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,355,5,40,30,hWnd,(HMENU)ID_BUTTON2,hInst,NULL);
//
hdc=GetDC(hWnd);
LoadBkImge(hdc);
return 0;
}
case WM_SIZE:
return 0;
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
//Draw1(hdc);
Rect myRect(0,0,400,40);
//
Color colors[]={
Color(255,255,255),
Color(247,247,247),
Color(231,235,139),
Color(214,223,231),
Color(181,178,181)
};
float positions[]={
0.0f,
0.125f,
0.5f,
0.875f,
1.0f
};
FillRec(hdc,myRect,colors,positions,5);
EndPaint(hWnd, &ps);
return 0;
}
case WM_COMMAND:
{
switch(wParam)
{
case ID_BUTTON1:
{
MessageBox(NULL," Undefined","",MB_OK);
break;
}
case ID_BUTTON2:
{
PostQuitMessage(0);
break;
}
//
}
return 0;
}
case WM_DRAWITEM:
{
pdis=(LPDRAWITEMSTRUCT)lParam;
//SetBkMode(pdis->hDC, TRANSPARENT );
FillRect(pdis->hDC,&pdis->rcItem,NULL);
FrameRect(pdis->hDC,&pdis->rcItem,(HBRUSH)GetStockObject(BLACK_BRUSH));
int cx=pdis->rcItem.right-pdis->rcItem.bottom;
int cy=pdis->rcItem.bottom-pdis->rcItem.top;
switch(pdis->CtlID)
{
case ID_BUTTON1:
{
Graphics graphics(pdis->hDC);
Rect rectt(0,0,40,30);
Color colors[]={
Color(247,247,247),
Color(231,235,139),
Color(214,223,231),
};
float positions[]={
0.0f,
0.5f,
1.0f
};
FillRec(pdis->hDC,rectt,colors,positions,3);
{
SolidBrush m_pBrush(Color(255,130,130,130));
PointF point1(0.0f, 00.0f);
PointF point2(30.0f, 20.0f);
PointF point3(10.0f, 30.0f);
PointF points[3] = {point1, point2, point3};
graphics.FillPolygon(&m_pBrush, points, 3, FillModeAlternate);
}
break;
}
case ID_BUTTON2:
{
Graphics graphics(pdis->hDC);
Rect rectt(0,0,40,30);
Color colors[]={
Color(247,247,247),
Color(231,235,139),
Color(214,223,231),
};
float positions[]={
0.0f,
0.5f,
1.0f
};
FillRec(pdis->hDC,rectt,colors,positions,3);
SolidBrush m_pBrush(Color(255,130,130,130));
PointF point1(0.0f, 7.0);
PointF point2(6.0f, 0.0f);
PointF point3(40.0f, 23.0f);
PointF point4(34.0f, 30.0f);
PointF points[4] = {point1, point2, point3,point4};
graphics.FillPolygon(&m_pBrush, points, 4, FillModeAlternate);
//
PointF point5(0.0f, 23.0f);
PointF point6(34.0f, 0.0f);
PointF point7(40.0f, 7.0f);
PointF point8(6.0f, 30.0f);
PointF points2[4] = {point5, point6, point7,point8 };
graphics.FillPolygon(&m_pBrush, points2, 4, FillModeAlternate);
}
break;
}
//if (pdis->itemState & ODS_SELECTED)
// InvertRect (pdis->hDC, &pdis->rcItem) ;
// Draw a focus rectangle if the button has the focus
if (pdis->itemState & ODS_FOCUS)
{
pdis->rcItem.left += cx / 16 ;
pdis->rcItem.top += cy / 16 ;
pdis->rcItem.right -= cx / 16 ;
pdis->rcItem.bottom -= cy / 16 ;
DrawFocusRect (pdis->hDC, &pdis->rcItem) ;
}
return 0 ;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_LBUTTONDOWN:
SendMessage(hWnd,WM_NCLBUTTONDOWN,HTCAPTION,0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
說明:
這裡有一個嚴重的問題,如何設置按鈕的背景透明?臨時的解決辦法是將按鈕填充相同的漸變色。如畫的標題欄的五種漸變色的position數組值為
float positions[]={
0.0f,
0.125f,
0.5f,
0.875f,
1.0f
};
顏色為
Color colors[]={
Color(255,255,255),
Color(247,247,247),
Color(231,235,139),
Color(214,223,231),
Color(181,178,181)
};
根據坐標計算出按鈕的漸變色顏色和位置分別為
Color colors[]={
Color(247,247,247),
Color(231,235,139),
Color(214,223,231),
};
float positions[]={
0.0f,0.5f,1.0f
};

這種方法看起來挺笨的,所以最後留兩個問題。
問題一:如何設置系統菜單欄為漸變色?
問題二:按鈕背景如何透明?
參考:雜七雜八找了很多資料