Win32 滚动条的创建实例(一)

滚动描述:
我们所看到的滚动其实是文本打印位置的改变,例如:向下滚动,本来我们的文本是从y坐标为0的位置开始排列向下打印,如果我们从y坐标为-1开始打印,这不就实现了滚动的效果(因为坐标为负是文本不显示)。
所需四个重要函数:

  1. 设置滚动条的范围:SetScrollRange
  2. 设置滚动滑块的位置:SetScrollPos
  3. 获取滚动条的范围:GetScrollRange
  4. 获取滚动滑块的位置:GetScrollPos

实例效果如下:在这里插入图片描述


一、实现(需完成以下操作)

最开始是创建一个典型的Win32应用程序,然后对生成的代码进行添加修改

1. 添加滚动条

添加滚动条操作是在CreateWindowW函数中第三个参数中添加
WS_VSCROLL(垂直滚动条)WS_HSCROLL(水平滚动条)

2. 打印文本

这里使用了一个for循环打印文本

3. 设置滚动条的范围(SetScrollRange)

SetScrollRange(hWnd, SB_VERT, 0, 100, FALSE);
函数原型:

BOOL SetScrollRange(
HWND hWnd,       // 窗口句柄
int nBar,        // 滚动条类型
int nMinPos,     // 滚动条的最小位置
int nMaxPos,     // 滚动条的最大位置
BOOL bRedraw     // 重绘标志
);

参数解释:

参数一: hWnd
[输入] 滚动条控件或带有标准滚动条窗体的句柄,由nBar参数值确定。

参数二 :nBar
[输入] 指定滚动条将被设置。这个参数可以是下表值中的一个,含义如下:

说明
SB_CTL 设置滚动条控件的范围。而参数hwnd必须是滚动条控件的句柄。
SB_HORZ 设置窗体的标准水平滚动条的范围。
SB_VERT 设置窗体的标准垂直滚动条的范围

参数三:nMinPos
[输入] 指定滚动位置的最小值。

参数四:nMaxPos
[输入] 指定滚动位置的最大值.。

参数五:bRedraw
[输入] 指定滚动条是否被重画以反映变化。如果这个参数为TRUE,滚动条将被重画;如果为FALSE则不被重画。

4. 处理滚动条消息

	case WM_VSCROLL:
	{
		switch (LOWORD(wParam))  // 低16位
		{
		case SB_LINEDOWN:
		case SB_LINEUP:
		case SB_PAGEDOWN:
		case SB_PAGEUP:
		case SB_THUMBTRACK:
		}
	}
消息 作用
SB_LINELEFT 键盘左 或上 或鼠标点击左或上按钮 (三角形)
SB_LINERIGHT 键盘右或下 或鼠标点击右或下按钮
SB_PAGELEFT 键盘 pgup 键(上翻页) 或鼠标点击滑块左或上面的空白
SB_PAGERIGHT 键盘 pgdn键(下翻页)或鼠标点击滑块右或下面的空白
SB_THUMBTRACK 鼠标拖动滑块
SB_TOP 键盘home键
SB_BOTTOM 键盘end键

5. 更新画面、设置滚动条位置

	SetScrollPos(hWnd, SB_VERT, iVscrollPos, TRUE);   // 设置滚动条位置
	InvalidateRect(hWnd, NULL, TRUE);     // 发送WM_PAINT消息,更新窗口

二、关键代码(有改动添加的部分)

1. 在窗口创建函数CreateWindowW中

添加第三个参数即可(用 | 进行连接)

HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VSCROLL,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

2.消息处理函数WndProc

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int i;
	size_t j;
	TCHAR str[100];
	TEXTMETRIC tm;    //  结构体,用于计算字符的高度、宽度、间距等很多数据
	static int cxChar, cyChar, iVscrollPos, cxClient, cyClient, y;

	switch (message)
	{
	case WM_CREATE:  // 窗口创建时,所产生的消息
	{
		HDC hdc;
		hdc = GetDC(hWnd);
		GetTextMetrics(hdc, &tm);
		cxChar = tm.tmAveCharWidth;   //字符平均宽度
		cyChar = tm.tmHeight + tm.tmExternalLeading;  //字符所需的高度
		iVscrollPos = 0;  // 滑块的初始位置
		ReleaseDC(hWnd, hdc);
	}
	case WM_SIZE:  // 窗口大小改变
	{
		cxClient = LOWORD(lParam);   //客户区的宽度
		cyClient = HIWORD(lParam);   // 客户区的高度
		y = cyClient / cyChar;       // 计算一页中有多少行文本
		SetScrollRange(hWnd, SB_VERT, 0, 50 -  y, FALSE);  //创建滚动条的范围
	}
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);
		
		// for循环打印文本
		for (i = 0; i < 50; i++)
		{
			SetTextAlign(hdc, TA_LEFT | TA_TOP);  //文本左对齐
			// 安全字符串操作
			StringCchPrintf(str, 100, TEXT("%d:I love you!"), i + 1);
			StringCchLength(str, 100, &j);
			TextOut(hdc, 0, (i - iVscrollPos)* cyChar, str, j);
			TextOut(hdc, 20 * cxChar, (i - iVscrollPos)*cyChar, str, j);
			SetTextAlign(hdc, TA_RIGHT | TA_TOP);  // 文本右对齐
			TextOut(hdc, 50 * cxChar, (i - iVscrollPos)*cyChar, str, j);
		}
		EndPaint(hWnd, &ps);
	}
	break;
	case WM_VSCROLL:
	{
		switch (LOWORD(wParam))
		{
		case SB_LINEDOWN:
			iVscrollPos += 1;
			break;
		case SB_LINEUP:
			iVscrollPos -= 1;
			break;
		case SB_PAGEDOWN:
			iVscrollPos += y;
			break;
		case SB_PAGEUP:
			iVscrollPos -= y;
			break;
		case SB_THUMBTRACK:
			iVscrollPos = HIWORD(wParam);
			break;
		}
		iVscrollPos = min(50 - y, max(0, iVscrollPos));  //确保滑块不超出滚动条的范围
		if (iVscrollPos != GetScrollPos(hWnd, SB_VERT))
		{
			SetScrollPos(hWnd, SB_VERT, iVscrollPos, TRUE); // 设置滚动条的位置
			InvalidateRect(hWnd, NULL, TRUE);   //发送WM_PAINT消息,更新窗口
		}
	}
	break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

今日一言:
你现在的努力,是为了以后有更多的选择。

发布了30 篇原创文章 · 获赞 37 · 访问量 5509

猜你喜欢

转载自blog.csdn.net/qq_45021180/article/details/98633656