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对象必须设置回原有的不被选中的状态,此外不能在按钮的区域以外绘制任何图形。