学习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 ...
随机推荐
- Linux系统知识汇总
1 系统相关 1.1 静态IP地址配置 Ubuntu配置和修改IP地址 1.2 Linux内核升级和降级 内核升级 Linux升级内核的正确姿势 内核降级 Ubuntu 16.04 内核降级 1.3 ...
- 纯MarkDown博客阅读体验优化
今天鼓捣了一天纯MarkDown书写的博客样式的美化,事实证明图表较多的MarkDown撰写的博文一样可以展现出非常漂亮的效果.为了让纯MarkDown书写的博客有一个干净舒服的阅读体验,我主要针对博 ...
- Docker for windows 入门三(PowerShell命令使用)
- Jmeter While Controller 使用${__jexl2(,)}
1. String [] str ={"1","2","3"}; vars.putObject("strArray",s ...
- 在做销售录入界面时,如何使用dbgrid?(50分)
给你段源码看一看用stringgird做得: procedure Tfrmingoods.adddata ; var i:integer; begin do begin ,i])=trim(goods ...
- BZOJ1127 POI2008KUP(悬线法)
首先显然地,如果某个格子的权值超过2k,其一定不在答案之中:如果在[k,2k]中,其自身就可以作为答案.那么现在我们只需要考虑所选权值都小于k的情况. 可以发现一个结论:若存在一个权值都小于k的矩阵其 ...
- HDU - 1160 (FatMouse's Speed )最长上升子序列
题意:一个元素有两个属性 w 和 sp 求在w严格递增的情况下 sp严格递减 用结构体 定义三个参数 w sp ix , ix是在输入时的顺序 因为我们要排序 之后把结构体数组 按从小到大排序 ...
- Codeforces Round #337 (Div. 2) B. Vika and Squares
B. Vika and Squares time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- DP的各种优化(动态规划,决策单调性,斜率优化,带权二分,单调栈,单调队列)
前缀和优化 当DP过程中需要反复从一个求和式转移的话,可以先把它预处理一下.运算一般都要满足可减性. 比较naive就不展开了. 题目 [Todo]洛谷P2513 [HAOI2009]逆序对数列 [D ...
- springmvc源码解析MvcNamespaceHandler之<mvc:view-resolvers>
说在前面 本次主要介绍springmvc配置解析. springmvc配置解析 本次介绍MvcNamespaceHandler. 进入到这个方法org.springframework.web.serv ...