COLORS1这个应用程序的功能是利用3个滚动条控件来调控颜色。
我把这个程序分成3大部分:(1)基础功能的实现(2)滚动条控件与静态窗口的美化(3)实现Tab键转移焦点功能
先来看基础功能的实现,首先从创建控件开始吧:
static HWND ScrollBarHwnd[3],LabelHwnd[3],ValueHwnd[3],RectHwnd;//10个子窗口控件
static int color[3];//记录3个滚动条的thumb的pos
static TCHAR *szLabel[3]={TEXT("RED"),TEXT("GREEN"),TEXT("BLUE")};//3个Label窗口的文本
if(uimsg==WM_CREATE)
{
HINSTANCE hInstance=((LPCREATESTRUCT)lparam)->hInstance;
RectHwnd=CreateWindow(TEXT("static"),NULL,WS_CHILD | WS_VISIBLE | SS_WHITERECT,0,0,0,0,hwnd,(HMENU)9,hInstance,NULL);
for(int i=0;i<3;i++)
{
ScrollBarHwnd[i]=CreateWindow(TEXT("scrollbar"),NULL,WS_CHILD | WS_VISIBLE | SBS_VERT,0,0,0,0,hwnd,(HMENU)i,hInstance,NULL);
SetScrollRange(ScrollBarHwnd[i],SB_CTL,0,255,false);
color[i]=0;
SetScrollPos(ScrollBarHwnd[i],SB_CTL,color[i],false);
LabelHwnd[i]=CreateWindow(TEXT("static"),szLabel[i],WS_CHILD | WS_VISIBLE | SS_CENTER,0,0,0,0,hwnd,(HMENU)(i+3),hInstance,NULL);
ValueHwnd[i]=CreateWindow(TEXT("static"),TEXT("0"),WS_CHILD | WS_VISIBLE | SS_CENTER,0,0,0,0,hwnd,(HMENU)(i+6),hInstance,NULL);
}
return 0;
}
else if(uimsg==WM_SIZE)
{
int cxClient=LOWORD(lparam);
int cyClient=HIWORD(lparam);
int cyChar=HIWORD(GetDialogBaseUnits());
MoveWindow(RectHwnd,0,0,cxClient/2,cyClient,true);
for(int i=0;i<3;i++)
{
MoveWindow(ScrollBarHwnd[i],(2*i+1)*cxClient/14,2*cyChar,cxClient/14,cyClient-4*cyChar,true);
MoveWindow(LabelHwnd[i],(4*i+1)*cxClient/28,cyChar/2,cxClient/7,cyChar,true);
MoveWindow(ValueHwnd[i],(4*i+1)*cxClient/28,cyClient-3*cyChar/2,cxClient/7,cyChar,true);
}
return 0;
}
接着实现右边显示3种RGB融合之后的颜色:
else if(uimsg==WM_VSCROLL)
{
int id=GetWindowLong((HWND)lparam,GWL_ID);//确定是哪一个滚动条发送的消息
if(LOWORD(wparam)==SB_LINEDOWN)
color[id]++;
else if(LOWORD(wparam)==SB_LINEUP)
color[id]--;
else if(LOWORD(wparam)==SB_PAGEDOWN)
color[id]+=16;
else if(LOWORD(wparam)==SB_PAGEUP)
color[id]-=16;
else if(LOWORD(wparam)==SB_THUMBPOSITION || LOWORD(wparam)==SB_THUMBTRACK)
color[id]=HIWORD(wparam);
color[id]=min(255,max(0,color[id]));
SetScrollPos(ScrollBarHwnd[id],SB_CTL,color[id],true);//处理滚动条的位置,使它正常运行
TCHAR szbuf[100];
wsprintf(szbuf,TEXT("%d"),color[id]);
SetWindowText(ValueHwnd[id],szbuf);//修改ValueHwnd的内容
DeleteObject((HBRUSH)SetClassLong(hwnd,GCL_HBRBACKGROUND,(LONG)CreateSolidBrush(RGB(color[0],color[1],color[2]))));//更换主窗口的背景画刷
InvalidateRect(hwnd,&rcColor,true);//无效化显示区域,使颜色变化显示出来
return 0;
}
上面的代码就能实现了我们程序的基本功能,接下来就要美化静态子窗口的文字:
static RECT rcColor;//记录右边显示区域的大小
static HBRUSH hbrush[3],hbrushstatic;//对应美化静态窗口的3种颜色
static COLORREF colorPrim[3]={RGB(255,0,0),RGB(0,255,0),RGB(0,0,255)};
else if(uimsg==WM_CTLCOLORSCROLLBAR)//lparam参数是控件窗口的句柄,wparam参数是控件窗口的hdc(所有WM_CTLCOLOR???这样的消息基本都是这样子)
{
int id=GetWindowLong((HWND)lparam,GWL_ID);
return (LRESULT)hbrush[id];
}
else if(uimsg==WM_CTLCOLORSTATIC)
{
int id=GetWindowLong((HWND)lparam,GWL_ID);
if(id>=3 && id<=8)
{
SetTextColor((HDC)wparam,colorPrim[id%3]);
SetBkColor((HDC)wparam,GetSysColor(COLOR_BTNHIGHLIGHT));
return (LRESULT)hbrushstatic;
}
}
最后我们就要处理Tab的功能转移焦点:
首先在父窗口加如下代码:
else if (uimsg==WM_KEYDOWN)
{
return 0;
}
并在这个消息里面设置断点,调试,我们可以发现当我们用鼠标拖动thumb的时候,滚动条也做出了相应的变化,但是我们再按键盘的时候程序依然会停在断点处,可以得出滚动条控件与button控件不一样,不会因为点击而得到焦点,我们按tab的时候应该把焦点传到滚动条控件去的,顺便可以增加按VK_UP这些键功能,不但如此,如果我们只是简单的在父窗口转移焦点,第一次转移还可以,但是第二次转移的时候tab这个keydown消息就传去子窗口控件中去了,我们有必要处理到控件的过程函数才行。
在创建完每个滚动条之后,把它的过程函数改变为我们自己弄的,并且保存之前的过程函数用于DefWindowProc同样的功能
OldScrollBarProc[i]=(WNDPROC)SetWindowLong(ScrollBarHwnd[i],GWL_WNDPROC,(LONG)ScrollBarProc);
在自己的滚动条过程函数里面处理自己感兴趣的消息:
LRESULT CALLBACK ScrollBarProc(HWND hwnd,UINT uimsg,WPARAM wparam,LPARAM lparam)
{
int id=GetWindowLong(hwnd,GWL_ID);
if(uimsg==WM_KEYDOWN)//处理Tab键的转移焦点
{
if(wparam==VK_TAB)
{
id=(id+1)%3;
SetFocus(GetDlgItem(GetParent(hwnd),id));
}
else if(wparam==VK_UP)
SendMessage(GetParent(hwnd),WM_VSCROLL,SB_LINEUP,(LPARAM)hwnd);
else if(wparam==VK_DOWN)
SendMessage(GetParent(hwnd),WM_VSCROLL,SB_LINEDOWN,(LPARAM)hwnd);
return 0;
}
else if(uimsg==WM_SETFOCUS)
{
idFocus=id;
return 0;
}
return CallWindowProc(OldScrollBarProc[id],hwnd,uimsg,wparam,lparam);
}