学习windows编程 day3 之滚动条完善
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 之滚动条完善的更多相关文章
- 学习windows编程 day2 之滚动条使用
相关函数: setscrollrange,setscrollpos,getscrollrange,getscrollpos 使用滚动条时我们需要进行的操作: 1.初始化滚动条范围和位置 在窗口创建时W ...
- 学习windows编程 day3 之窗口绘画二:边框绘制函数
#include <windows.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l ...
- 学习windows编程 day3 之窗口绘画一:点线绘制
#include <windows.h> #include <math.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT message, ...
- 学习windows编程 day3 之 设置当前的背景颜色
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRU ...
- 学习windows编程 day3 之 自定义画笔的两种方法
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRU ...
- 有一定基础的 C++ 学习者该怎样学习 Windows 编程?
人的心理有个奇异的特性:一项知识一旦学会之后,学习过程中面临的困惑和不解非常快就会忘得干干净净,似乎一切都是自然而然,本来就该这种.因此,关于「怎样入门」这类问题,找顶尖高手来回答,未必能比一个刚入门 ...
- 我为什么学习Windows编程
前一段时间在看TCP/IP,在图书馆里面找了不少的书,其中有几本书还是不错的.比如: <Windows网络与通信程序设计(第二版)> 王艳平著 <WinSock网络编程经络> ...
- 学习windows编程 day1
#include <windows.h> #include <strsafe.h> /* 任务:去掉标题栏和边框 */ //#define LineHeight 15 这是自己 ...
- 学习windows编程 day6 之处理鼠标移动
#define POINT_MAX 1000 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPara ...
随机推荐
- (html4与html5分别实现)用一个表单向php界面提交不同的命令
先看上面的表单实例,分别有3个submit,只不过需要根据需要进行选择添加.删除或是修改.现在有两个方案. 方案一: 如果实在HTML4中,可以用下面的代码实现, 即将所有的submit提交到acce ...
- PAT L2-001 紧急救援
https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840 作为一个城市的应急救援队伍的负责人,你有一张 ...
- Tomcat7注册为Linux服务
https://www.openprogrammer.info/2015/06/14/how-to-install-java-8-and-tomcat-8-on-centos-6-as-service ...
- 利用ss-redir加速服务器上国外服务的访问
https://blog.microdog.me/2016/06/28/Speed-Up-Network-Accessing-To-Overseas-Services-On-Your-Server/
- Sonatype Nexus 2.11.1-01 使用入门
nexus安装与启动 linux下: 安装路径 /home/maven/nexus-2.11.1-01/ 启动方法 ./bin/nexus start windows下: 管理员模式运行cmd.exe ...
- docker 构建dockerfile
版本为: 使用cenotos 7 docker 版本 [root@zhao ~]# docker --versionDocker version 17.03.1-ce, build c6d412e ...
- centos mpeg acc 解码器安装
# yum -y install http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noar ...
- Test Scenarios for sending emails
(test cases for composing or validating emails are not included)(make sure to use dummy email addres ...
- Java之Date Time API (Java 8 新特性)
Java 8 – Date Time API Java 8 comes with a much improved and much required change in the way date an ...
- matplotlib之scatter自动绘制散点
# 使用matplotlib.pyplot.scatter绘制散点 import matplotlib.pyplot as plt from pylab import mpl # 设置默认字体,解决中 ...