学习windows编程 day2 之滚动条使用

相关函数:

setscrollrange,setscrollpos,getscrollrange,getscrollpos

使用滚动条时我们需要进行的操作:

1.初始化滚动条范围和位置

在窗口创建时WM_CREATE响应时可以完成

SetScrollRange(hwnd, SB_VERT, 0, NUMLINES,FALSE);
SetScrollPos(hwnd, SB_VERT, 0, TRUE);

2.处理窗口过程的滚动条消息

在响应WM_VSCROLL时处理

switch(LOWORD(wParam))
{
   case SB_LINEUP:
         ....
         break;
   case SB_LINEDOWN:
         ....
         break;
   case SB_PAGEUP:
         ....
         break;
   case SB_PAGEDOWN:
         ....
         break;
   case SB_THUMBTRACK:
         ....
         break;
   case SB_THUMBPOSITION:
         ....
         break;
}    

注意在wParam参数中的低十六位中可以获取鼠标在滚动条上的动作使用LOWORD(wParam)

当滚动条动作为SB_THUMBPOSITION或SB_THUMBTRACK时,可以在wParam参数中的高十六位中获取位置HIWORD(wParam)

3.更新滑块位置

SetScrollPos(hwnd, SB_VERT, XXX, TRUE);

4.根据滚动条变化更新客户端内容

可以在处理滚动条消息是设置全局参数,在WM_PAINT响应时做出响应更新

为了及时更新客户端内容

可以使用

InvalidateRect(hwnd, NULL, TRUE);

向消息队列中发送消息WM_PAINT,此消息会放在消息队列后面,知道其他消息处理完毕才会响应

或者使用

UpdateWindow(hwnd);

非队列化消息,跳过消息循环机制直接处理更新窗口

 全部代码:

#include <windows.h>
#include <strsafe.h>
#include "SysMet.h"


LRESULT CALLBACK WndProc(HWND hwnd, UINT message,WPARAM wParam,LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iShowCmd)
{
    static TCHAR szClassName[] = TEXT("MyWindow5");
    MSG msg;
    HWND hwnd;

    WNDCLASS wndclass;
    wndclass.cbClsExtra=0;
    wndclass.cbWndExtra=0;
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.hCursor = LoadCursor(NULL, IDI_APPLICATION);
    wndclass.hIcon = LoadIcon(NULL, IDC_ARROW);
    wndclass.hInstance = hInstance;
    wndclass.lpfnWndProc = WndProc;
    wndclass.lpszClassName = szClassName;
    wndclass.lpszMenuName = NULL;
    wndclass.style = CS_HREDRAW;

    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("this program must run in win nt!"), TEXT("ERROR"), MB_OK);
        return 0;
    }

    hwnd = CreateWindow(szClassName,
        TEXT("MyWindowProgram"),
        WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL
        );

    ShowWindow(hwnd,iShowCmd);
    UpdateWindow(hwnd);
    
    while (GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    TCHAR szBuffer[100];
    TEXTMETRIC tm;
    static int cxChar, cyChar, cxCaps,iVscrollPos;//大写占1.5倍
    size_t st;
    int y;
    static int cxClient, cyClient;
    switch (message)
    {
    case WM_CREATE:
        iVscrollPos = 0;
        SetScrollRange(hwnd, SB_VERT, 0, NUMLINES,FALSE);//后面代表是否现在重画窗口
        SetScrollPos(hwnd, SB_VERT, 0, TRUE);

        hdc = GetDC(hwnd);
        GetTextMetrics(hdc, &tm);
        cxChar = tm.tmAveCharWidth;
        cyChar = tm.tmExternalLeading + tm.tmHeight;
        cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2)*cxChar / 2;
        ReleaseDC(hwnd,hdc);
        break;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        for (int i = 0; i < NUMLINES;i++)
        {
            y = cyChar*(i - iVscrollPos);
            //获取的大量数据
            StringCchLength(sysmetrics[i].szLabel, 1024, &st);
            TextOut(hdc, 0, y, sysmetrics[i].szLabel, st);

            StringCchLength(sysmetrics[i].szDesc, 1024, &st);
            TextOut(hdc, 40 * cxCaps, y, sysmetrics[i].szDesc, st);

            SetTextAlign(hdc,TA_RIGHT|TA_TOP);
            StringCchPrintf(szBuffer, 100, L"%d    %d  %5d", i + 1,iVscrollPos, GetSystemMetrics(sysmetrics[i].iIndex));
            StringCchLength(szBuffer, 100, &st);
            TextOut(hdc, 40 * cxCaps + 40 * cxChar, y, szBuffer, st);
            SetTextAlign(hdc, TA_LEFT|TA_TOP);
        }

        //获取屏幕分辨率
//         cxClient=GetSystemMetrics(SM_CXSCREEN);    //水平
//         cyClient=GetSystemMetrics(SM_CYSCREEN);    //垂直
//         StringCchPrintf(szBuffer, 100, L"screen : %d * %d px", cxClient, cyClient);
//         //在屏幕中心写字
//         GetClientRect(hwnd, &rect);
//         DrawText(hdc, szBuffer, -1, &rect, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
        
        
        EndPaint(hwnd, &ps);
        break;
    case WM_VSCROLL:
        hdc = GetDC(hwnd);
        GetClientRect(hwnd, &rect);
        if (LOWORD(wParam) == SB_LINEUP)
        {
            iVscrollPos -= 1;
        }
        else if (LOWORD(wParam) == SB_LINEDOWN)
        {
            iVscrollPos += 1;
        }
        else if (LOWORD(wParam) == SB_PAGEUP)
        {
            iVscrollPos -= cyClient / cyChar;
        }
        else if (LOWORD(wParam) == SB_PAGEDOWN)
        {
            iVscrollPos += cyClient / cyChar;
        }
        else if (LOWORD(wParam) == SB_THUMBTRACK)
        {
            DrawText(hdc, L"Slider.....", -1, &rect, DT_RIGHT | DT_VCENTER);
        }
        else if (LOWORD(wParam) == SB_THUMBPOSITION)
        {
            iVscrollPos = HIWORD(wParam);
        }
        ReleaseDC(hwnd, hdc);

        iVscrollPos = max(0, min(iVscrollPos, NUMLINES));
        if (iVscrollPos != GetScrollPos(hwnd, SB_VERT))
         {
            InvalidateRect(hwnd, NULL, TRUE);
            SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_QUIT:
        break;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}
View Code

 

posted @ 2018-03-03 22:39  山上有风景  阅读(357)  评论(0编辑  收藏  举报