Trackbar

Trackbar bao gồm 1 slider + 1 tick mark. Chúng ta có thể sử dụng chuột hoặc bàn phím để di chuyển thanh slider. Trackbar được dùng để lựa chọn 1 giá trị xác định trong 1 dải giá trị liên tục.
Chúng ta tạo trackbar bằng 3 static text control. 2 đối tượng static được đặt ở bên trái và bên phải của slider. Khi ta kéo slider trượt thì text của đối tượng static còn lại sẽ thay đổi.

#include "windows.h"
#include "commctrl.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void CreateControls(HWND hwnd);
void UpdateLabel(void);

HWND hTrack;
HWND hlbl;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nCmdShow)
{
    HWND hwnd;
    MSG  msg ;
    WNDCLASSW wc = {0};
    wc.lpszClassName = L"Trackbar";
    wc.hInstance     = hInstance ;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc   = WndProc ;
    wc.hCursor       = LoadCursor(0,IDC_ARROW);

    RegisterClassW(&wc);
    hwnd = CreateWindowW(wc.lpszClassName, L"Trackbar", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 350, 180, 0, 0, hInstance, 0);

    while( GetMessage(&msg, NULL, 0, 0)) 
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch(msg)
    {
        case WM_CREATE:
            CreateControls(hwnd);
            break;
        case WM_HSCROLL:
            UpdateLabel();
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void CreateControls(HWND hwnd)
{
    HWND hLeftLabel = CreateWindowW(L"STATIC", L"0", WS_CHILD | WS_VISIBLE, 0, 0, 10, 30, hwnd, (HMENU)1, NULL, NULL);
    HWND hRightLabel = CreateWindowW(L"STATIC", L"100", WS_CHILD | WS_VISIBLE, 0, 0, 30, 30, hwnd, (HMENU)2,NULL, NULL);
    hlbl = CreateWindowW(L"STATIC", L"0", WS_CHILD | WS_VISIBLE, 270, 20, 30, 30, hwnd, (HMENU)3, NULL, NULL);
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC  = ICC_LISTVIEW_CLASSES;
    InitCommonControlsEx(&icex);

    hTrack = CreateWindowW(L"msctls_trackbar32", L"Trackbar Control", WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS,
20, 20, 170, 30, hwnd, (HMENU) 3, NULL, NULL);
    SendMessageW(hTrack, TBM_SETRANGE,  TRUE, MAKELONG(0, 100));
    SendMessageW(hTrack, TBM_SETPAGESIZE, 0,  10);
    SendMessageW(hTrack, TBM_SETTICFREQ, 10, 0);
    SendMessageW(hTrack, TBM_SETPOS, FALSE, 0);
    SendMessageW(hTrack, TBM_SETBUDDY, TRUE, (LPARAM) hLeftLabel);
    SendMessageW(hTrack, TBM_SETBUDDY, FALSE, (LPARAM) hRightLabel);
}

void UpdateLabel(void)
{
    LRESULT pos = SendMessageW(hTrack, TBM_GETPOS, 0, 0);
    wchar_t buf[4];
    wsprintfW(buf, L"%ld", pos);
    SetWindowTextW(hlbl, buf);
}

Giải thích:

HWND hLeftLabel = CreateWindowW(L"STATIC", L"0", WS_CHILD | WS_VISIBLE, 0, 0, 10, 30, hwnd, (HMENU)1, NULL, NULL);
HWND hRightLabel = CreateWindowW(L"STATIC", L"100", WS_CHILD | WS_VISIBLE, 0, 0, 30, 30, hwnd, (HMENU)2, NULL, NULL);
hlbl = CreateWindowW(L"STATIC", L"0", WS_CHILD | WS_VISIBLE, 270, 20, 30, 30, hwnd, (HMENU)3, NULL, NULL);

3 static control sẽ được tạo. 2 static đầu tiên hiển thị giá trị min,max của trackbar. Static còn lại sẽ hiển thị giá trị được chọn.

INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC  = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);

Nếu chúng ta muốn sử dụng 1 trong những common control, thì cần phải load common control DLL (Comctl32.dll) và đăng kí common control class lấy từ DLL.
Hàm InitCommonControlsEx() phải được khai báo trước khi tạo common control.

hTrack = CreateWindowW(L"msctls_trackbar32", L"Trackbar Control", WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS, 20, 20, 170, 30, hwnd, (HMENU) 3, NULL, NULL);

Trackbar đã được tạo, TBS_AUTOTICKS tạo ra thang chia độ trên trackbar.

SendMessageW(hTrack, TBM_SETRANGE,  TRUE, MAKELONG(0, 100));
SendMessageW(hTrack, TBM_SETPAGESIZE, 0,  10);
SendMessageW(hTrack, TBM_SETTICFREQ, 10, 0);
SendMessageW(hTrack, TBM_SETPOS, FALSE, 0);

Ta cần gửi message đến trackbar để tạo thành 1 trackbar hoàn chỉnh.
TBM_SETRANGE dùng để đặt dải giá trị cho trackbar (ở đây là 100).
TBM_SETPAGESIZE dùng để đặt bước nhảy khi ta click chuột, thanh slider sẽ trượt đi 1 khoảng là 10.
TBM_SETTICFREQ dùng để đặt độ dài mỗi vạch trên trackbar.
TBM_SETPOS dùng để thiết lập vị trí ban đầu cho trackbar.

SendMessageW(hTrack, TBM_SETBUDDY, TRUE, (LPARAM) hLeftLabel);
SendMessageW(hTrack, TBM_SETBUDDY, FALSE, (LPARAM) hRightLabel);

TBM_SETBUDDY dùng để đặt control static “0” và “100” vào bên trái và bên phải của trackbar. Nếu TRUE : bên trái, FALSE : bên phải.

case WM_HSCROLL:
    UpdateLabel();
    break;

Khi ta di chuyển thanh slider thì hàm WndProc() sẽ nhận được message WM_HSCROLL (trong trường hợp trackbar nằm ngang).

void UpdateLabel(void)
{
    LRESULT pos = SendMessageW(hTrack, TBM_GETPOS, 0, 0);
    wchar_t buf[4];
    wsprintfW(buf, L"%ld", pos);
    SetWindowTextW(hlbl, buf);
}

Trong hàm UpdateLabel(), ta lấy vị trí hiện tại của slider bằng cách gửi message TMB_GETPOS tới trackbar. Giá trị trả về của hàm SendMessageW() sẽ được convert sang dạng text và được set lên trackbar bằng hàm SetWindowTextW(hlbl, buf).

Kết quả:

Trackbar

Be the first to comment

Leave a Reply