那么问题来了,滚动条大家都有印象。然而窗口滚动条和滚动条控件两者又是如何区分的呢?窗口滚动条和滚动条控件之间又有什么关系呢?
我们就在此来分析一下。先看看下面的窗口滚动条和滚动条控件的截图:
【窗口滚动条和滚动条控件的区别】
左边的是一个垂直滚动条控件,窗口最右边有一个垂直的窗口滚动条。从图中可以看出一点区别。下面来细说。窗口滚动条,是与窗口整合在一起的窗口组成部分,为了完成操作超出窗口可视部分的内容而存在的。窗口滚动条分为垂直方向和水平方向两种,默认情况下,垂直的窗口滚动条在窗口右侧,水平的窗口滚动条在窗口的底部。
滚动条控件,是一种公共控件。在滑动取值、设置参数等场景中使用,如调节音量、调节颜色等。滚动条控件也分为两种,即垂直滚动条控件和水平滚动条控件。
窗口滚动条和滚动条控件的区别就在各自的定义中可以看出来。窗口滚动条和滚动条控件的应用场景不同。窗口滚动条通常处理窗口内容的移动,让窗口滚动条的滑块的移动与窗口内容移动同步。滚动条控件更多是局部的滚动,你可以有更多的控制,便于操作。比如在一个窗口中有很多参数要设置,需要同时有多个滚动条,那么最好就是用滚动条控件了。不同的控件修改不同的参数,而窗口滚动条一个窗口只能拥有一个垂直滚动条和一个水平滚动条,无法满足多个滚动条使用场景。
那么这是从应用方面做的一点分析。那么我们在从编程的角度来分析两者的不同和相同。
我们要知道,窗口滚动条和滚动条控件是怎么创建出来的。窗口滚动条是窗口的组成部分之一,是通过窗口风格指定而产生的。所以在CreateWindow创建窗口的时候,就可以指定窗口风格,让窗口拥有窗口滚动条。代码如下:
HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW|WS_VSCROLL,10,100,400,400,NULL,NULL,hInstance,NULL);
这句代码让窗口拥有了垂直的窗口滚动条,如果你在加入WS_HSCROLL,则窗口还会拥有水平滚动条。可以看到,窗口增加滚动条,是顺带的事情,并不需要太多的工作。而滚动条控件则完全不一样。滚动条控件是一种公共控件,控件也是一种窗口。所以创建控件也就是创建一个窗口,只是窗口类指定为系统预定义的滚动条控件窗口类"scrollbar"。滚动条不会显示文字,所以滚动条窗口文字被忽略。默认情况下,滚动条控件为水平滚动条控件,也就是横着放的滚动条。可以给滚动条控件指定窗口风格SBS_VERT创建垂直滚动条控件,水平滚动条控件的窗口风格位SBS_HORZ。
滚动条控件风格是以SBS_开头的,因为SS_是static控件的缩写,所以滚动条就用了三个字母缩写,也是滚动条的英文单词缩写。创建滚动条控件代码如下:
CreateWindow(_T("scrollbar"),_T("C++技术网\r\nhttp://www.cjjjs.com"),WS_CHILD|WS_VISIBLE|SBS_VERT,50,50,20,200,hwnd,(HMENU)1,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),0);
所以,窗口滚动条和滚动条控件在创建时区别很大哦,因为性质不同,一个是窗口的组成部分,如标题栏也是窗口的组成部分,一个是窗口,控件是预定义的特别窗口。
那么同样的消息,如何区分是滚动条控件还是窗口滚动条产生的呢?因为窗口滚动条是窗口的组成部分,不是独立的窗口,因此没有独立的句柄来操作窗口滚动条。而滚动条控件则是一个独立的窗口,有对应的窗口句柄,一般叫做滚动条控件句柄。那么这个区别就在滚动条WM_HSCROLL或者WM_VSCROLL消息的LPARAM参数中。LPARAM参数携带的是控件的句柄,如果是滚动条控件发送的消息 ,自然就携带了滚动条控件的句柄,否则就是NULL。那么我们就可以通过这个来区分窗口滚动条和滚动条控件了。这个参数是相同的消息通知机制中的不同之处。
当然,一个窗口中可以有多个滚动条控件,然而WM_HSCROLL或者WM_VSCROLL消息中并没有携带滚动条控件的ID信息,所以要区分多个滚动条控件,就只有通过滚动条控件的句柄来区分多个滚动条控件了。
区分窗口滚动条和滚动条控件的代码如下:
case WM_VSCROLL:
{
if (lParam!=NULL)
{
//滚动条控件,lParam携带了滚动条控件的窗口句柄
if (hScrollBar==(HWND)lParam)
{
//滚动条控件被操作
}
}
else
{
//窗口滚动条
//窗口滚动条被操作
}
}
return 0;
WM_HSCROLL或者WM_VSCROLL消息中的WPARAM参数携带的参数,对于窗口滚动条和滚动条控件来说,使用都是一样的。了解到这些区别和联系后,对于滚动条的使用再也不畏惧了。下面是完整的代码:
#include "windows.h"
#include <tchar.h>
TCHAR tip[]=_T("C++技术网http://www.cjjjs.com");
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static HBRUSH hBrush;
static HWND hScrollBar;
switch (message)
{
case WM_CREATE:
{
hScrollBar = CreateWindow(_T("scrollbar"),_T("C++技术网\r\nhttp://www.cjjjs.com"),WS_CHILD|WS_VISIBLE|SBS_VERT,50,50,20,200,hwnd,(HMENU)1,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),0);
CreateWindow(_T("static"),_T("声音:100%"),WS_CHILD|WS_VISIBLE,50,250,100,20,hwnd,(HMENU)1,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),0);
return 0;
}
case WM_VSCROLL:
{
if (lParam!=NULL)
{
//滚动条控件,lParam携带了滚动条控件的窗口句柄
if (hScrollBar==(HWND)lParam)
{
//滚动条控件被操作
}
}
else
{
//窗口滚动条
//窗口滚动条被操作
}
}
return 0;
case WM_CTLCOLORSCROLLBAR:
{
hBrush = CreateSolidBrush(RGB(255,0,0));
return (LRESULT)hBrush;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break;//跳出到默认处理
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
TCHAR ClassName[] = _T("MyClass");
TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
WNDCLASS wndClass;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = WinProc;
wndClass.lpszClassName = ClassName;
wndClass.lpszMenuName=NULL;
wndClass.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
if(!RegisterClass(&wndClass))return 0;
HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW|WS_VSCROLL,10,100,400,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}