Windows有29种系统颜色,每种颜色都在0-255之间,它使用GetSysColor和SetSysColors来调用颜色参数:
也就是Windows下的画板的颜色:
罗列一下具体的29种颜色的参数:
如下调用:
SetBkColor(hdc,GetSysColor(COLOR_BTNFACE)); SetTextColor(hdc,GetSysColor(Color_WINDOWTEXT)); //更改了系统颜色,要用下面的语句传递消息 case WM_SYSCOLORCHANGE: InvalidateRect(hwnd,NULL,TRUE); break;
一般使用获取WM_CTLCOLORSTATIC:消息去改变颜色:
下面看一段自绘按钮的代码:
#include<windows.h> #include<windowsx.h> #define ID_SMALLER 1 #define ID_LARGER 2 #define BTN_WIDTH (8*cxChar) #define BTN_HEIGHT (4*cyChar) LRESULT CALLBACK WindowProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); HINSTANCE hInst; int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state ) { static TCHAR szAppName[]=TEXT("leidemingzi"); HWND hwnd; MSG msg; WNDCLASS wndclass; hInst=hInstance; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); wndclass.hIcon=LoadIcon(NULL,IDI_ERROR); wndclass.hInstance=hInstance; wndclass.lpfnWndProc=WindowProc; wndclass.lpszClassName=szAppName; wndclass.lpszMenuName=NULL; wndclass.style=CS_HREDRAW|CS_VREDRAW; if(!RegisterClass(&wndclass)) { MessageBox(NULL,TEXT("the program requrie the window nt"),TEXT("tips"),MB_ICONERROR); return 0; } hwnd=CreateWindow( szAppName, // registered class name TEXT("this is title"), // window name WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // horizontal position of window CW_USEDEFAULT, // vertical position of window CW_USEDEFAULT, // window width CW_USEDEFAULT, // window height NULL, // handle to parent or owner window NULL, // menu handle or child identifier hInstance, // handle to application instance NULL // window-creation data ); ShowWindow(hwnd,nCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } void Triangle(HDC hdc,POINT pt[]) { SelectObject(hdc,GetStockObject(BLACK_BRUSH)); Polygon(hdc,pt,3); SelectObject(hdc,GetStockObject(WHITE_BRUSH)); } LRESULT CALLBACK WindowProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { static HWND hwndSmaller,hwndLarger; static int cxClient,cyClient,cxChar,cyChar; LPDRAWITEMSTRUCT pdis; POINT pt[3]; int cx,cy; RECT rect; switch(uMsg) { case WM_CREATE: cxChar=LOWORD(GetDialogBaseUnits()); cyChar=HIWORD(GetDialogBaseUnits()); hwndSmaller=CreateWindow( TEXT("button"),TEXT(""), WS_CHILD|WS_VISIBLE|BS_OWNERDRAW, 0,0,BTN_WIDTH,BTN_HEIGHT,hwnd, (HMENU)ID_SMALLER,hInst,NULL ); hwndLarger=CreateWindow( TEXT("button"),TEXT(""), WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,0,0, BTN_WIDTH,BTN_HEIGHT, hwnd,(HMENU)ID_LARGER,hInst,NULL ); return 0; case WM_SIZE: cxClient=GET_X_LPARAM(lParam); cyClient=GET_Y_LPARAM(lParam); MoveWindow(hwndSmaller,cxClient/2-3*BTN_WIDTH/2,cyClient/2-BTN_HEIGHT/2,BTN_WIDTH,BTN_HEIGHT,TRUE); MoveWindow(hwndLarger,cxClient/2+BTN_WIDTH/2,cyClient/2-BTN_HEIGHT/2,BTN_WIDTH,BTN_HEIGHT,TRUE); return 0; case WM_COMMAND: GetWindowRect(hwnd,&rect); switch(wParam) { case ID_SMALLER: rect.left+=cxClient/20; rect.right-=cxClient/20; rect.top+=cyClient/20; rect.right-=cyClient/20; break; case ID_LARGER: rect.left-=cxClient/20; rect.right+=cxClient/20; rect.top-=cyClient/20; rect.right+=cyClient/20; break; } MoveWindow(hwnd,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,TRUE); return 0; case WM_DRAWITEM: pdis=(LPDRAWITEMSTRUCT)lParam; FillRect(pdis->hDC,&pdis->rcItem,(HBRUSH)GetStockObject(WHITE_BRUSH)); FrameRect(pdis->hDC,&pdis->rcItem,(HBRUSH)GetStockObject(BLACK_BRUSH)); cx=pdis->rcItem.right-pdis->rcItem.left; cy=pdis->rcItem.bottom-pdis->rcItem.top; switch (pdis->CtlID) { case ID_SMALLER : pt[0].x = 3 * cx / 8 ; pt[0].y = 1 * cy / 8 ; pt[1].x = 5 * cx / 8 ; pt[1].y = 1 * cy / 8 ; pt[2].x = 4 * cx / 8 ; pt[2].y = 3 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 7 * cx / 8 ; pt[0].y = 3 * cy / 8 ; pt[1].x = 7 * cx / 8 ; pt[1].y = 5 * cy / 8 ; pt[2].x = 5 * cx / 8 ; pt[2].y = 4 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 5 * cx / 8 ; pt[0].y = 7 * cy / 8 ; pt[1].x = 3 * cx / 8 ; pt[1].y = 7 * cy / 8 ; pt[2].x = 4 * cx / 8 ; pt[2].y = 5 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 1 * cx / 8 ; pt[0].y = 5 * cy / 8 ; pt[1].x = 1 * cx / 8 ; pt[1].y = 3 * cy / 8 ; pt[2].x = 3 * cx / 8 ; pt[2].y = 4 * cy / 8 ; Triangle (pdis->hDC, pt) ; break ; case ID_LARGER : pt[0].x = 5 * cx / 8 ; pt[0].y = 3 * cy / 8 ; pt[1].x = 3 * cx / 8 ; pt[1].y = 3 * cy / 8 ; pt[2].x = 4 * cx / 8 ; pt[2].y = 1 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 5 * cx / 8 ; pt[0].y = 5 * cy / 8 ; pt[1].x = 5 * cx / 8 ; pt[1].y = 3 * cy / 8 ; pt[2].x = 7 * cx / 8 ; pt[2].y = 4 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 3 * cx / 8 ; pt[0].y = 5 * cy / 8 ; pt[1].x = 5 * cx / 8 ; pt[1].y = 5 * cy / 8 ; pt[2].x = 4 * cx / 8 ; pt[2].y = 7 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 3 * cx / 8 ; pt[0].y = 3 * cy / 8 ; pt[1].x = 3 * cx / 8 ; pt[1].y = 5 * cy / 8 ; pt[2].x = 1 * cx / 8 ; pt[2].y = 4 * cy / 8 ; Triangle (pdis->hDC, pt) ; break ; } if(pdis->itemState*ODS_SELECTED) InvertRect(pdis->hDC,&pdis->rcItem); 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; } return DefWindowProc(hwnd,uMsg,wParam,lParam); }
其中,GetDialogBaseUnits()方法类似于TEXTMETRIC的tmAveCharWidth属性
case WM_DRAWITEM在绘制OWNERDRAW控件生效
再看一下DRAWITEMSTRUCT的定义,详细请看MSDN
typedef struct tagDRAWITEMSTRUCT { UINT CtlType; UINT CtlID; UINT itemID; UINT itemAction; UINT itemState; HWND hwndItem; HDC hDC; RECT rcItem; ULONG_PTR itemData; } DRAWITEMSTRUCT
效果图如下:
选中的时候,按钮颜色取反,左边按钮使窗体变小,右边按钮使窗体变大
忠告:
对于使用自绘按钮的人,Windows会为你获得设备环境,并把它放在DRAWITEMSTRUCT结构的一个字段中,必须原样不动保持这个设备的状态,任何一个被选入该设备环境的GDI对象必须设置回原有的不被选中的状态,此外不能在按钮的区域以外绘制任何图形。