当前位置:C++技术网 > 精选软件 > 窗口滚动条和滚动条控件的区别与联系的对比分析

窗口滚动条和滚动条控件的区别与联系的对比分析

更新时间:2016-02-22 15:08:02浏览次数:1+次

    如果一个窗口的内容很多,就会用到窗口滚动条,这样就可以拖动滚动条来浏览超出窗口显示区域的内容。如果在窗口内要调节一些参数,就可能需要用到能够拖动的滚动条来修改参数的值,这就需要用到滚动条控件。
    那么问题来了,滚动条大家都有印象。然而窗口滚动条和滚动条控件两者又是如何区分的呢?窗口滚动条和滚动条控件之间又有什么关系呢?

    我们就在此来分析一下。先看看下面的窗口滚动条和滚动条控件的截图:

窗口滚动条和滚动条控件的区别

【窗口滚动条和滚动条控件的区别】
    左边的是一个垂直滚动条控件,窗口最右边有一个垂直的窗口滚动条。从图中可以看出一点区别。下面来细说。
    窗口滚动条,是与窗口整合在一起的窗口组成部分,为了完成操作超出窗口可视部分的内容而存在的。窗口滚动条分为垂直方向和水平方向两种,默认情况下,垂直的窗口滚动条在窗口右侧,水平的窗口滚动条在窗口的底部。
    滚动条控件,是一种公共控件。在滑动取值、设置参数等场景中使用,如调节音量、调节颜色等。滚动条控件也分为两种,即垂直滚动条控件和水平滚动条控件。
    窗口滚动条和滚动条控件的区别就在各自的定义中可以看出来。窗口滚动条和滚动条控件的应用场景不同。窗口滚动条通常处理窗口内容的移动,让窗口滚动条的滑块的移动与窗口内容移动同步。滚动条控件更多是局部的滚动,你可以有更多的控制,便于操作。比如在一个窗口中有很多参数要设置,需要同时有多个滚动条,那么最好就是用滚动条控件了。不同的控件修改不同的参数,而窗口滚动条一个窗口只能拥有一个垂直滚动条和一个水平滚动条,无法满足多个滚动条使用场景。
    那么这是从应用方面做的一点分析。那么我们在从编程的角度来分析两者的不同和相同。
    我们要知道,窗口滚动条和滚动条控件是怎么创建出来的。窗口滚动条是窗口的组成部分之一,是通过窗口风格指定而产生的。所以在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_COMMAND消息,用参数中的通知码来告知父窗口发生了什么事情。而滚动条控件则不一样。滚动条控件和窗口滚动条一样,都是发送标准的WM_HSCROLL或者WM_VSCROLL消息。这一点,是滚动条控件和窗口滚动条的相同点。也就是说,对于消息的通知机制,滚动条控件和窗口滚动条是一样的。
    那么同样的消息,如何区分是滚动条控件还是窗口滚动条产生的呢?因为窗口滚动条是窗口的组成部分,不是独立的窗口,因此没有独立的句柄来操作窗口滚动条。而滚动条控件则是一个独立的窗口,有对应的窗口句柄,一般叫做滚动条控件句柄。那么这个区别就在滚动条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;
}