win32自绘按钮,使用GDI+(一)

第一次写随笔,我本来想将win32窗口的标题栏设置成渐变色,像这样的效果

但发现找不到设置标题栏属性的api,SetWindowLong也只是增减窗口的固定的样式而已。所以想到一个思路,把标题栏去掉,自己绘制一个标题栏,包括标题栏上的按钮都自己来绘制创建。这里用到了gdi+,对于这个库也是刚接触到的。

最后程序实现的效果如下。

代码:

  1 #ifndef ULONG_PTR
  2 #define ULONG_PTR unsigned long*
  3 #endif
  4 #include <windows.h>  
  5 //#include <objidl.h>  
  6 #include <gdiplus.h>  
  7 using namespace Gdiplus; 
  8 #pragma comment (lib,"Gdiplus.lib") 
  9 #define ID_BUTTON1 1 
 10 #define ID_BUTTON2 2
 11 HINSTANCE hInst;
 12 
 13 void LoadBkImge(HDC hdc)
 14 {
 15     Graphics graphics(hdc); 
 16    Image image(L"pic1.png");
 17    graphics.DrawImage(&image,0,25);
 18 }
 19  
 20 
 21 void FillRec(HDC hdc,Rect myRect,Color* colors,float *positions,int i) 
 22 { 
 23     Graphics graphics(hdc); 
 24    //多彩渐变色
 25     LinearGradientBrush myLinearGradientBrush(
 26        myRect,
 27        Color(255,255,255,0),
 28        Color(255,255,0,0),
 29        LinearGradientModeVertical
 30        );//LinearGradientModeHorizontal*/
 31   
 32       myLinearGradientBrush.SetInterpolationColors(colors, positions, i);
 33       graphics.FillRectangle(&myLinearGradientBrush,myRect);
 34 } 
 35 
 36 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
 37  
 38 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) 
 39 { 
 40    HWND                hWnd; 
 41    MSG                 msg; 
 42    WNDCLASS            wndClass; 
 43    GdiplusStartupInput gdiplusStartupInput; 
 44    ULONG_PTR           gdiplusToken; 
 45    hInst=hInstance;
 46     
 47    // Initialize GDI+.  
 48    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 
 49     
 50    wndClass.style          = CS_HREDRAW | CS_VREDRAW|DS_CENTER; 
 51    wndClass.lpfnWndProc    = WndProc; 
 52    wndClass.cbClsExtra     = 0; 
 53    wndClass.cbWndExtra     = 0; 
 54    wndClass.hInstance      = hInstance; 
 55    wndClass.hIcon          = LoadIcon(NULL, IDI_APPLICATION); 
 56    wndClass.hCursor        = LoadCursor(NULL, IDC_ARROW); 
 57    wndClass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH); 
 58    wndClass.lpszMenuName   = NULL; 
 59    wndClass.lpszClassName  = TEXT("Gdiplustest"); 
 60     
 61    RegisterClass(&wndClass); 
 62     
 63    hWnd = CreateWindow( 
 64       TEXT("Gdiplustest"), 
 65       TEXT("Gdiplustest"),
 66       WS_OVERLAPPED|WS_POPUP,   
 67       CW_USEDEFAULT,          
 68       CW_USEDEFAULT,        
 69       400,           
 70       250,         
 71       NULL,                  
 72       NULL,                   
 73       hInstance,             
 74       NULL);                 
 75     
 76    ShowWindow(hWnd, iCmdShow); 
 77    UpdateWindow(hWnd); 
 78     
 79    while(GetMessage(&msg, NULL, 0, 0)) 
 80    { 
 81       TranslateMessage(&msg); 
 82       DispatchMessage(&msg); 
 83    } 
 84     
 85    GdiplusShutdown(gdiplusToken); 
 86    return msg.wParam; 
 87 }  
 88  
 89 LRESULT CALLBACK WndProc(HWND hWnd, UINT message,  
 90    WPARAM wParam, LPARAM lParam) 
 91 { 
 92    static HDC   hdc; 
 93    static HWND hButton1,hButton2;
 94    PAINTSTRUCT  ps; 
 95    LPDRAWITEMSTRUCT pdis;
 96     
 97    switch(message) 
 98    { 
 99    case WM_CREATE:
100        {
101            //窗口居中显示
102            int scrWidth,scrHeight;
103            RECT rect;
104            scrWidth=GetSystemMetrics(SM_CXSCREEN);
105            scrHeight=GetSystemMetrics(SM_CYSCREEN);
106            GetWindowRect(hWnd,&rect);
107            rect.left=(scrWidth-rect.right)/2;
108            rect.top=(scrHeight-rect.bottom)/2;
109            SetWindowPos(hWnd,HWND_TOP,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW);
110            hButton1=CreateWindow("button","",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,355,5,15,15,hWnd,(HMENU)ID_BUTTON1,hInst,NULL);
111            hButton2=CreateWindow("button","",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,380,5,15,15,hWnd,(HMENU)ID_BUTTON2,hInst,NULL);
112 
113            //
114            hdc=GetDC(hWnd);
115            return 0;
116        }
117    case WM_SIZE:
118        return 0;
119    case WM_PAINT:
120        {
121         hdc = BeginPaint(hWnd, &ps); 
122         LoadBkImge(hdc);
123         Rect myRect(0,0,400,25);
124 
125         //
126        Color colors[]={
127        Color(255,255,255),
128        Color(247,251,255),
129        Color(239,239,247),
130        Color(222,227,231),
131        Color(231,235,239),
132        Color(214,219,222)
133        };
134       float positions[]={
135        0.0f,
136        0.2f,
137        0.4f,
138        0.6f,
139        0.8f,
140        1.0f
141       };
142         FillRec(hdc,myRect,colors,positions,6);
143         Graphics graphics(hdc);
144         Pen pen1(Color(255,255,255,255));
145         Pen pen2(Color(255,160,160,160));
146         Pen pen3(Color(255,181,178,181));
147         graphics.DrawLine(&pen1,0,0,400,0);
148         graphics.DrawLine(&pen2,0,1,400,1);
149         graphics.DrawLine(&pen3,0,25,400,25);
150 
151       EndPaint(hWnd, &ps); 
152       return 0; 
153        }
154    case WM_COMMAND:
155        {
156            switch(wParam)
157             {
158            case ID_BUTTON1:
159                {
160                    ShowWindow(hWnd,SW_SHOWMINIMIZED);
161                    break;
162                }
163            case ID_BUTTON2:
164                 {
165                     PostQuitMessage(0); 
166                     break;
167                 }
168                 //
169            }
170 
171        return 0;
172 
173        }
174 
175    case WM_DRAWITEM:
176        {
177 
178             pdis=(LPDRAWITEMSTRUCT)lParam;
179             //SetBkMode(pdis->hDC, TRANSPARENT );
180             FillRect(pdis->hDC,&pdis->rcItem,NULL);
181             FrameRect(pdis->hDC,&pdis->rcItem,(HBRUSH)GetStockObject(BLACK_BRUSH));
182 
183             int cx=pdis->rcItem.right-pdis->rcItem.bottom;
184             int cy=pdis->rcItem.bottom-pdis->rcItem.top;
185 
186             switch(pdis->CtlID)
187             {
188 
189                 case ID_BUTTON1:
190                 {
191                         Graphics graphics(pdis->hDC); 
192                         Rect rectt(0,0,40,30);
193                         Color colors[]={
194                         Color(247,251,255),
195                         Color(239,239,247),
196                         Color(222,227,231),
197                         Color(231,235,239),
198                         };
199                         float positions[]={
200                         0.0f,
201                         0.333333f,
202                         0.666666f,
203                         1.0f
204                         };
205                         FillRec(pdis->hDC,rectt,colors,positions,4);
206                         {
207                         SolidBrush  m_pBrush(Color(255,0,0,0));
208                         PointF point1(3.0f, 6.5f);
209                         PointF point2(12.0f, 6.5f);
210                         PointF point3(12.0f, 8.50f);
211                         PointF point4(3.0f, 8.50f);
212                         PointF points[4] = {point1, point2, point3,point4};
213                         graphics.FillPolygon(&m_pBrush, points, 4, FillModeAlternate); 
214                         }
215                         
216                         break;
217                 }
218 
219                 case ID_BUTTON2:
220                 {
221                     Graphics graphics(pdis->hDC); 
222                     Rect rectt(0,0,40,30);
223                     Color colors[]={
224                     Color(247,251,255),
225                     Color(239,239,247),
226                     Color(222,227,231),
227                     Color(231,235,239),
228                     };
229                     float positions[]={
230                         0.0f,
231                         0.33333f,
232                         0.66633f,
233                         1.0f
234                     };
235                     FillRec(pdis->hDC,rectt,colors,positions,4);
236         
237                     SolidBrush  m_pBrush(Color(255,0,0,0));
238                     //
239                     PointF point1(2.0f, 4.0f);
240                     PointF point2(4.0f, 2.0f);
241                     PointF point3(13.0f, 11.0f);
242                     PointF point4(11.0f, 13.0f);
243                     PointF points[4] = {point1, point2, point3,point4};
244                     graphics.FillPolygon(&m_pBrush, points, 4, FillModeAlternate);
245                     //
246                     PointF point5(13.0f, 4.0f);
247                     PointF point6(11.0f, 2.0f);
248                     PointF point7(2.0f, 11.0f);
249                     PointF point8(4.0f, 13.0f);
250 
251                     PointF points2[4] = {point5, point6, point7,point8    };
252                     graphics.FillPolygon(&m_pBrush, points2, 4, FillModeAlternate); 
253                     }
254                 break;
255             }
256           //if (pdis->itemState & ODS_SELECTED)
257               // InvertRect (pdis->hDC, &pdis->rcItem) ;
258           
259               //  Draw a focus rectangle if the button has the focus
260           
261           if (pdis->itemState & ODS_FOCUS)
262           {
263                pdis->rcItem.left   += cx / 16 ;
264                pdis->rcItem.top    += cy / 16 ;
265                pdis->rcItem.right  -= cx / 16 ;
266                pdis->rcItem.bottom -= cy / 16 ;
267                
268                DrawFocusRect (pdis->hDC, &pdis->rcItem) ;
269           }
270           return 0 ;
271        }
272 
273    case WM_DESTROY: 
274       PostQuitMessage(0); 
275       return 0; 
276    case WM_LBUTTONDOWN:
277       SendMessage(hWnd,WM_NCLBUTTONDOWN,HTCAPTION,0);
278       return 0;
279    default: 
280       return DefWindowProc(hWnd, message, wParam, lParam); 
281    } 
282 }

说明:

这里有一个严重的问题,如何设置按钮的背景透明?临时的解决办法是将按钮填充相同的渐变色。如画的标题栏的五种渐变色的position数组值为

1       float positions[]={
2        0.0f,
3        0.2f,
4        0.4f,
5        0.6f,
6        0.8f,
7        1.0f
8       };

颜色为

1         Color colors[]={
2         Color(255,255,255),
3         Color(247,251,255),
4         Color(239,239,247),
5         Color(222,227,231),
6         Color(231,235,239),
7         Color(214,219,222)
8        };

根据坐标计算出按钮的渐变色颜色和位置分别为

 1              Color colors[]={
 2                 Color(247,251,255),
 3                 Color(239,239,247),
 4                 Color(222,227,231),
 5                 Color(231,235,239),
 6             };
 7             float positions[]={
 8                 0.0f,
 9                 0.333333f,
10                 0.666666f,
11                 1.0f
12             };

这种方法看起来挺笨的,所以最后留两个问题。

问题一:如何设置系统菜单栏为渐变色?

问题二:按钮背景如何透明?

参考:杂七杂八找了很多资料

posted @ 2015-12-11 22:04  廖凡  阅读(4673)  评论(0编辑  收藏  举报