第一次寫隨筆,我本來想將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 };
這種方法看起來挺笨的,所以最後留兩個問題。
問題一:如何設置系統菜單欄為漸變色?
問題二:按鈕背景如何透明?
參考:雜七雜八找了很多資料