了解即可,不细细研究了
# include
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ScrollProc(HWND, UINT, WPARAM, LPARAM);
//拥有输入焦点的滚动条的ID
int idFocus;
/*
可以查看一下定义:
ypedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
*/
WNDPROC OldScroll[3];//WNDPROC是函数指针
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR lpCmdLine,
int iCmdShow
)
{
static TCHAR szAppName[] = TEXT("那又怎样");
WNDCLASS wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = CreateSolidBrush(0);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//这里用NULL表示使用微软提供的图标
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //同上
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WndProc;
wndclass.lpszClassName = szAppName;
wndclass.lpszMenuName = NULL;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wndclass))//注册窗口类
{
MessageBox(NULL, "Program requires windows NT!", szAppName, MB_ICONERROR);
return 0;
}
HWND hwnd;
hwnd = CreateWindow(szAppName, TEXT("Color Scroll"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL,NULL, hInstance, NULL);//在窗口风格用或语句就可以加上滚动条了
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static COLORREF crPrim[3] = { RGB(255, 0, 0), RGB(0, 255, 0), RGB(0, 0, 255) };//三种颜色,红,绿,蓝
static HBRUSH hBrush[3], hBrushStatic;
static HWND hwndScroll[3], hwndLabel[3], hwndValue[3], hwndRect;
static int color[3], cyChar;
static RECT rcColor;
static TCHAR *szColorLabel[] = { TEXT("Red"), TEXT("Green"), TEXT("Blue") };
HINSTANCE hInstance;
int i, cxClient, cyClient;
TCHAR szBuffer[10];
switch (uMsg)
{
case WM_CREATE:
//获取WinMain里的hInstance
hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
//Create the white-rectangle window against which the scroll bars will be positioned
//The child window ID is 9
//左半部分背景
hwndRect = CreateWindow(TEXT("static"), NULL, WS_CHILD | WS_VISIBLE| SS_GRAYRECT,
0, 0, 0,0,
hwnd, (HMENU)9, hInstance,NULL);
for (i = 0; i < 3; i++)
{
//The three scroll bar have IDs 0,1 and 2,with scroll bar ranges from 0 through 255
hwndScroll[i] = CreateWindow(TEXT("scrollbar"), NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP
| SBS_VERT,
0, 0, 0, 0, hwnd, (HMENU)i, hInstance, NULL);
/* WS_TABSTOP
Specifies a control that can receive the keyboard focus when the user presses the TAB key. Pressing the TAB key changes the keyboard focus to the next control with the WS_TABSTOP style.
You can turn this style on and off to change dialog box navigation. To change this style after a window has been created, use SetWindowLong.
*/
SetScrollRange(hwndScroll[i], SB_CTL, 0, 255, FALSE);
SetScrollPos(hwndScroll[i], SB_CTL, 0, FALSE);
//The three color-name tables have IDs 3,4,and 5,and
//text string "Red","Green",and "Blue".
hwndLabel[i] = CreateWindow(TEXT("static"), szColorLabel[i], WS_CHILD | WS_VISIBLE | SS_CENTER,
0, 0, 0, 0,
hwnd,(HMENU)(i + 3), hInstance, NULL);
//The three color-value text fields have IDs 6,7,and 8,
//and initial text strints of "0".
hwndValue[i] = CreateWindow(TEXT("static"),TEXT("0"), WS_CHILD | WS_VISIBLE | SS_CENTER,
0, 0, 0, 0,
hwnd, (HMENU)(i + 6), hInstance, NULL);
//将三个滚动条的窗口过程设置为ScrollProc
//试试三个滚动条的窗口过程都设置为同一窗口过程
OldScroll[i] = (WNDPROC)SetWindowLong(hwndScroll[i], GWL_WNDPROC, (LONG)ScrollProc);
hBrush[i] = CreateSolidBrush(crPrim[i]);
}
//用来画静态控件的画刷
hBrushStatic = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
cyChar = HIWORD(GetDialogBaseUnits());
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
//右半部分
SetRect(&rcColor, cxClient / 2, 0, cxClient, cyClient);
//左半部分
MoveWindow(hwndRect, 0, 0, cxClient / 2, cyClient,TRUE);
for (i = 0; i < 3; i++)
{
MoveWindow(hwndScroll[i], (2 * i + 1)*cxClient / 14,2*cyChar, cxClient / 14, cyClient - 4 * cyChar, TRUE);
MoveWindow(hwndLabel[i], (4 * i + 1)*cxClient / 28, cyChar / 2, cxClient / 7, cyChar, TRUE);
MoveWindow(hwndValue[i], (4 * i + 1)*cxClient / 28, cyClient - 3 * cyChar / 2, cxClient / 7, cyChar, TRUE);
}
SetFocus(hwnd);
return 0;
//主窗口具有输入焦点时,使得id为idFocus的滚动条具有输入焦点
case WM_SETFOCUS:
SetFocus(hwndScroll[idFocus]);
return 0;
case WM_VSCROLL:
//对于滚动条,lParam不会用到(为0),而对于滚动条控制其值为滚动条控制的窗口句柄
i = GetWindowLong((HWND)lParam, GWL_ID);
switch (LOWORD(wParam))
{
case SB_PAGEDOWN:
color[i] += 15;
//fall through
case SB_LINEDOWN:
color[i] = min(255, color[i] + 1);
break;
case SB_PAGEUP:
color[i] -= 15;
case SB_LINEUP:
color[i] = max(0, color[i] - 1);
break;
case SB_TOP:
color[i] = 0;
break;
case SB_BOTTOM:
color[i] = 255;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
color[i] = HIWORD(wParam);
break;
default:
break;
}
SetScrollPos(hwndScroll[i], SB_CTL, color[i], TRUE);
wsprintf(szBuffer, TEXT("%d"), color[i]);
SetWindowText(hwndValue[i], szBuffer);
//删除未命名的背景画刷,即设计窗口类时用的:
//wndclass.hbrBackground = CreateSolidBrush(0);
//并用后面新创建的画刷代替
DeleteObject((HBRUSH)SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(color[0], color[1], color[2]))));
InvalidateRect(hwnd, &rcColor, TRUE);
return 0;
//查看msdn,一目了然
case WM_CTLCOLORSCROLLBAR:
i = GetWindowLong((HWND)lParam, GWL_ID);
return (LRESULT)hBrush[i];
case WM_CTLCOLORSTATIC:
i = GetWindowLong((HWND)lParam, GWL_ID);
if (i >= 3 && i <= 8) //static text controls
{
SetTextColor((HDC)wParam, crPrim[i % 3]);
SetBkColor((HDC)wParam,GetSysColor(COLOR_BTNHIGHLIGHT));
return (LRESULT)hBrushStatic;//必须返回一个画刷用来画静态控件的背景
}
break;
/*
其实,i一定是在[3,8]范围,因为只有这6个控件是静态控件(创建窗口时包含SS_CENTER,为静态类型),所以
父窗口只会收到这些控件的WM_CTLCOLORSTATIC消息,作者可能以为系统会收到别的控件的该消息,所以就break
跳出这一循环,如果是return 0则不行
*/
case WM_SYSCOLORCHANGE:
DeleteObject(hBrushStatic);
hBrushStatic = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
return 0;
case WM_CLOSE:
auto iI = GCL_HBRBACKGROUND;
//替换与类有关的背景刷子的句柄,这里就是删除注册窗口类时那个未命名的CreateSolidBrush(0)画刷句柄,并且
//之后背景画刷为WHITE_BRUSH
DeleteObject((HBRUSH)SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)GetStockObject(WHITE_BRUSH)));
for (i = 0; i < 3; i++)
DeleteObject(hBrush[i]);
PostQuitMessage(0);
//DestroyWindow(hwnd);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK ScrollProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int id = GetWindowLong(hwnd, GWL_ID);
switch (message)
{
//当前滚动条具有输入焦点,按下TAB键(同时按SHIFT键),GetKeyState(VK_SHIFT)<0,然后设置相应的滚动条
//具有输入焦点
case WM_KEYDOWN:
if (wParam == VK_TAB)
SetFocus(GetDlgItem(GetParent(hwnd), (id + (GetKeyState(VK_SHIFT) < 0 ? 2 : 1)) % 3));
break;//不要return 0;外层还有主窗口的循环
case WM_SETFOCUS:
idFocus = id;//具有输入焦点时更新idFocus的值
break;
default:
break;
}
/*可以使用带GWL_WNDPROC索引值的SetWindowLong函数创建一个窗口类的子类,该窗口类是用于创建该窗口的类。
一个应用程序可以以一个系统类为子类,但是不能以一个其他进程产生的窗口类为子类,SetwindowLong函数通过
改变与一个特殊的窗口类相联系的窗口过程来创建窗口子类,从而使系统调用新的窗口过程而不是以前定义的窗口过程。
应用程序必须通过调用CallWindowProc函数向前窗口传递未被新窗口处理的消息,这样作允许应用程序创建一个窗口
过程链。
*/
return CallWindowProc(OldScroll[id], hwnd,message, wParam,lParam);
}