1.不再使用setscrollrange,setscrollpos,getscrollrange,getscrollpos这些函数,这只是有助于理解其中运行原理

2.改用setscrollinfo,getscrollinfo函数和结构体scrollinfo去改变和获取滚动条信息,相对于上面会更加灵活,方便扩展

3.scrollwindow:滚动窗口客户区的内容,只滚动当前显示的内容,要显示其他内容,需要重绘失效的窗口,但是相对于重绘整个窗口是一个很节省内存的方法

#include <windows.h>
#include "Sysmet.h"
#include <strsafe.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
//声明全局数据:类名
static TCHAR szClassName[] = TEXT("MyWindows");
HWND hwnd;
MSG msg; //注册窗口类
WNDCLASS wndclass; wndclass.hInstance = hInstance;
wndclass.lpszClassName = szClassName;
wndclass.cbClsExtra = ;
wndclass.cbWndExtra = ;
wndclass.lpfnWndProc = WndProc;
wndclass.lpszMenuName = NULL;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.style = CS_HREDRAW; if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("this program must run in Windows NT!"), szClassName, MB_ICONERROR);
return ;
} hwnd = CreateWindow(
szClassName,
TEXT("MyFirstPractice"),
WS_OVERLAPPEDWINDOW|WS_VSCROLL,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
); ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd); while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} return msg.wParam;
} LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
//获取字体大小,初始化数据
static int cxChar, cyChar, cxCaps;
//获取每次重绘窗口后的大小尺寸
static int cxClient, cyClient;
//获取总行数和当前行数
static numCount, curCount; static int y;
int FirstLine, LastLine; TEXTMETRIC tm;
TCHAR szBuffer[];
size_t st;
SCROLLINFO si; switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);
//获取字体大小,初始化数据
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight + tm.tmExternalLeading;
cxCaps = (tm.tmPitchAndFamily & ? : )*cxChar / ; //初始化总行数和当前行数
numCount = NUMLINES;
curCount = ; //初始化滚动条位置
SetScrollRange(hwnd, SB_VERT, , numCount, FALSE);
SetScrollPos(hwnd, SB_VERT, , TRUE); ReleaseDC(hwnd, &hdc); break;
case WM_SIZE:
//获取每次重绘后的屏幕大小
cxClient = LOWORD(lParam); //这是获取当前窗口的大小
cyClient = HIWORD(lParam); //设置垂直滚动条的范围和页面大小
si.cbSize = sizeof(si); //为了更好的兼容版本
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = ;
si.nMax = numCount - ;
si.nPage = cyClient / cyChar; //页面的大小设置 SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
break;
case WM_VSCROLL:
//获得垂直滚动条的信息
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, SB_VERT, &si); //保存当前滑块的位置
curCount = si.nPos; switch (LOWORD(wParam))
{
case SB_LINEUP:
si.nPos -= ;
break;
case SB_LINEDOWN:
si.nPos += ;
break;
case SB_PAGEUP:
//先获取当前页面有几行
si.nPos -= si.nPage;
break;
case SB_PAGEDOWN:
//先获取当前页面的行数
si.nPos += si.nPage;
break; case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
//在si.nTrackPos中存放着SB_THUMBTRACK和SB_THUMBPOSITION的位置信息
case SB_THUMBPOSITION:
si.nPos = si.nTrackPos;
break;
default:
break;
} //设置滚动滑块的新位置
si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE); //再次获得滚动滑块的位置,由于窗口调整,他可能不是同一个值
GetScrollInfo(hwnd, SB_VERT, &si);
//curCount是前面未滚动的数据,si.nPos是刚刚滚动后的数据(除非是在顶部或者底部,不然由于窗口调整,两种一定不是同一个值)
if (si.nPos != curCount)
{
ScrollWindow(hwnd, , cyChar*(curCount-si.nPos), NULL, NULL);
/*
hwnd :窗口句柄
0 :水平滚动的数量
cyChar*(curCount-si.nPos):垂直滚动的距离
NULL(lpRect) :为NULL时,当前整个客户区将被滚动
NULL(lpClipRect) :与上一个参数有关,当上一个设置区域后,该参数在其区域中裁剪区域进行滚动
*/
UpdateWindow(hwnd);
//不进入消息队列,直接发送WM_PAINT消息进行处理
}
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); //获取垂直滚动条的位置
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo(hwnd,SB_VERT, &si);
curCount = si.nPos; //计算需要重绘的区域
FirstLine = max(, curCount + ps.rcPaint.top / cyChar);
LastLine = min(numCount - , curCount + ps.rcPaint.bottom / cyChar);
/*
ps是结构体,ps.rcPaint是指需要重绘的部分窗口矩形,ps.rcPaint.top是该矩形的上部
*/ for (int i = FirstLine; i < LastLine;i++)
{
y = cyChar*(i - curCount); //相当于将这个重绘区域看着新窗口,重这个区域的顶部开始重新绘制 StringCchLength(sysmetrics[i].szLabel, , &st);
TextOut(hdc, , y, sysmetrics[i].szLabel, st); StringCchLength(sysmetrics[i].szDesc, , &st);
TextOut(hdc, * cxChar, y, sysmetrics[i].szDesc, st); SetTextAlign(hdc, TA_RIGHT | TA_TOP); StringCchPrintf(szBuffer, , L"%5d", GetSystemMetrics(sysmetrics[i].iIndex));
StringCchLength(szBuffer, , &st);
TextOut(hdc, * cxChar + * cxCaps, y, szBuffer, st); SetTextAlign(hdc, TA_LEFT);
} EndPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage();
return ;
} return DefWindowProc(hwnd, message, wParam, lParam);
}

学习windows编程 day3 之滚动条完善的更多相关文章

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

    相关函数: setscrollrange,setscrollpos,getscrollrange,getscrollpos 使用滚动条时我们需要进行的操作: 1.初始化滚动条范围和位置 在窗口创建时W ...

  2. 学习windows编程 day3 之窗口绘画二:边框绘制函数

    #include <windows.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l ...

  3. 学习windows编程 day3 之窗口绘画一:点线绘制

    #include <windows.h> #include <math.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT message, ...

  4. 学习windows编程 day3 之 设置当前的背景颜色

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRU ...

  5. 学习windows编程 day3 之 自定义画笔的两种方法

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRU ...

  6. 有一定基础的 C++ 学习者该怎样学习 Windows 编程?

    人的心理有个奇异的特性:一项知识一旦学会之后,学习过程中面临的困惑和不解非常快就会忘得干干净净,似乎一切都是自然而然,本来就该这种.因此,关于「怎样入门」这类问题,找顶尖高手来回答,未必能比一个刚入门 ...

  7. 我为什么学习Windows编程

    前一段时间在看TCP/IP,在图书馆里面找了不少的书,其中有几本书还是不错的.比如: <Windows网络与通信程序设计(第二版)> 王艳平著 <WinSock网络编程经络> ...

  8. 学习windows编程 day1

    #include <windows.h> #include <strsafe.h> /* 任务:去掉标题栏和边框 */ //#define LineHeight 15 这是自己 ...

  9. 学习windows编程 day6 之处理鼠标移动

    #define POINT_MAX 1000 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPara ...

随机推荐

  1. Hibernate的初次使用

    使用hibernate的四个步骤:第一:创建一个hibernate.cfg.xml.<!DOCTYPE hibernate-configuration PUBLIC "-//Hiber ...

  2. java可变参数长度

    一: 在python中 有可变参数*args和万能参数**args参数分别为列表和字典.在java中也有类似的可变参数列表.不过传递进去的是可变参数数组. package com.company; p ...

  3. MySQL 单表优化

    一.表字段优化 1.整数类型尽量使用 TINYINT.SMALLINT.MEDIUM_INT 而不是INT,非负数要加上UNSIGNED 2.VARCHAR的长度分配要合理,不要过大 3.时间字段不超 ...

  4. #Leetcode# 977. Squares of a Sorted Array

    https://leetcode.com/problems/squares-of-a-sorted-array/ Given an array of integers A sorted in non- ...

  5. PAT 1002 写出这个数

    https://pintia.cn/problem-sets/994805260223102976/problems/994805324509200384 读入一个自然数n,计算其各位数字之和,用汉语 ...

  6. back to top 回到顶部按钮 css+js

    效果 html <p id="back-to-top"><a href="#top"><span></span> ...

  7. python中常用的九种数据预处理方法分享

    Spyder   Ctrl + 4/5: 块注释/块反注释 本文总结的是我们大家在python中常见的数据预处理方法,以下通过sklearn的preprocessing模块来介绍; 1. 标准化(St ...

  8. Java中一些jar包的作用

    axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期管理的常用方法. jaxrpc.jar Ax ...

  9. 使用Java HttpComponent/HttpClinet 调用 WebAPI问题的解决

    几个关键字: WebAPI, Android, Apache HttpComponent/HttpClient 问题:无论怎么测试, WebAPI的FormBody value总是空. 最简单的代码 ...

  10. python---random模块详解

    在python中用于生成随机数的模块是random,在使用前需要import, 下面看下它的用法. random.random random.random()用于生成一个0到1的随机符点数: 0 &l ...