滚动条的实现(1)

  • 滚动条(以滚动列,即纵向为例)
  • 滚动条的绘制:系统绘制CreateWindow(..., WS_OVERLAPPEDWINDOW | WS_VSCROLL /*| WS_HSCROLL*/, ...)
  • 系统与用户分别需要对滚动条做些什么
  • 滚动条处理函式解析
  • 滚动条响应视窗处理程式解析
  • 为了实现滚动列的实例,参考了《windows程式设计 第五版》,这里使用TextOut(...)函数在显示区域绘制系统字体,这里需要知道每一行字体的高度,才能获取字体的总行数,下面为字体高度解析
  • 程序设计(参考《windows程式设计 第五版》)
  • Metrics.h
  • #ifndef _METRICS_H__
    #define _METRICS_H__
    
    #include <windows.h>
    
    #define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0])) 
    
    typedef struct
    {
    	int Index;
    	TCHAR * szLabel;
    	TCHAR * szDesc;
    }ST_METRICS, *PST_METRICS;
    
    ST_METRICS sysmetrics[] =
    {
    	SM_CXSCREEN, TEXT("SM_CXSCREEN"), TEXT("Screen width in pixels"),
    	SM_CYSCREEN, TEXT("SM_CYSCREEN"), TEXT("Screen height in pixels"),
    	SM_CXVSCROLL, TEXT("SM_CXVSCROLL"), TEXT("Vertical scroll width"),
    	SM_CYHSCROLL, TEXT("SM_CYHSCROLL"), TEXT("Horizontal scroll height"),
    	SM_CYCAPTION, TEXT("SM_CYCAPTION"), TEXT("Caption bar height"),
    	SM_CXBORDER, TEXT("SM_CXBORDER"), TEXT("Window border width"),
    	SM_CYBORDER, TEXT("SM_CYBORDER"), TEXT("Window border height"),
    	SM_CXFIXEDFRAME, TEXT("SM_CXFIXEDFRAME"), TEXT("Dialog window frame width"),
    	SM_CYFIXEDFRAME, TEXT("SM_CYFIXEDFRAME"), TEXT("Dialog window frame height"),
    	SM_CYVTHUMB, TEXT("SM_CYVTHUMB"), TEXT("Vertical scroll thumb height"),
    	SM_CXHTHUMB, TEXT("SM_CXHTHUMB"), TEXT("Horizontal scroll thumb width"),
    	SM_CXICON, TEXT("SM_CXICON"), TEXT("Icon width"),
    	SM_CYICON, TEXT("SM_CYICON"), TEXT("Icon height"),
    	SM_CXCURSOR, TEXT("SM_CXCURSOR"), TEXT("Cursor width"),
    	SM_CYCURSOR, TEXT("SM_CYCURSOR"), TEXT("Cursor height"),
    	SM_CYMENU, TEXT("SM_CYMENU"), TEXT("Menu bar height"),
    	SM_CXFULLSCREEN, TEXT("SM_CXFULLSCREEN"), TEXT("Full screen client area width"),
    	SM_CYFULLSCREEN, TEXT("SM_CYFULLSCREEN"), TEXT("Full screen client area height"),
    	SM_CYKANJIWINDOW, TEXT("SM_CYKANJIWINDOW"), TEXT("Kanji window height"),
    	SM_MOUSEPRESENT, TEXT("SM_MOUSEPRESENT"), TEXT("Mouse present flag"),
    	SM_CYVSCROLL, TEXT("SM_CYVSCROLL"), TEXT("Vertical scroll arrow height"),
    	SM_CXHSCROLL, TEXT("SM_CXHSCROLL"), TEXT("Horizontal scroll arrow width"), 
    	SM_DEBUG, TEXT("SM_DEBUG"), TEXT("Debug version flag"),
    	SM_SWAPBUTTON, TEXT("SM_SWAPBUTTON"), TEXT("Mouse buttons swapped flag"),
    	SM_CXMIN, TEXT("SM_CXMIN"), TEXT("Minimum window width"),
    	SM_CYMIN, TEXT("SM_CYMIN"), TEXT("Minimum window height"),
    	SM_CXSIZE, TEXT("SM_CXSIZE"), TEXT("Min/Max/Close button width"),
    	SM_CYSIZE, TEXT("SM_CYSIZE"), TEXT("Min/Max/Close button height"),
    	SM_CXSIZEFRAME, TEXT("SM_CXSIZEFRAME"), TEXT("Window sizing frame width"),
    	SM_CYSIZEFRAME, TEXT("SM_CYSIZEFRAME"), TEXT("Window sizing frame height"),
    	SM_CXMINTRACK, TEXT("SM_CXMINTRACK"), TEXT("Minimum window tracking width"),
    	SM_CYMINTRACK, TEXT("SM_CYMINTRACK"), TEXT("Minimum window tracking height"),
    	SM_CXDOUBLECLK, TEXT("SM_CXDOUBLECLK"), TEXT("Double click x tolerance"),
    	SM_CYDOUBLECLK, TEXT("SM_CYDOUBLECLK"), TEXT("Double click y tolerance"),
    	SM_CXICONSPACING, TEXT("SM_CXICONSPACING"), TEXT("Horizontal icon spacing"),
    	SM_CYICONSPACING, TEXT("SM_CYICONSPACING"), TEXT("Vertical icon spacing"),
    	SM_MENUDROPALIGNMENT, TEXT("SM_MENUDROPALIGNMENT"), TEXT("Left or right menu drop"),
    	SM_PENWINDOWS, TEXT("SM_PENWINDOWS"), TEXT("Pen extensions installed"),
    	SM_DBCSENABLED, TEXT("SM_DBCSENABLED"), TEXT("Double-Byte Char Set enabled"),
    	SM_CMOUSEBUTTONS, TEXT("SM_CMOUSEBUTTONS"), TEXT("Number of mouse buttons"), 
    	SM_SECURE, TEXT("SM_SECURE"), TEXT("Security present flag"),
    	SM_CXEDGE, TEXT("SM_CXEDGE"), TEXT("3-D border width"),
    	SM_CYEDGE, TEXT("SM_CYEDGE"), TEXT("3-D border height"),
    	SM_CXMINSPACING, TEXT("SM_CXMINSPACING"), TEXT("Minimized window spacing width"),
    	SM_CYMINSPACING, TEXT("SM_CYMINSPACING"), TEXT("Minimized window spacing height"),
    	SM_CXSMICON, TEXT("SM_CXSMICON"), TEXT("Small icon width"),
    	SM_CYSMICON, TEXT("SM_CYSMICON"), TEXT("Small icon height"),
    	SM_CYSMCAPTION, TEXT("SM_CYSMCAPTION"), TEXT("Small caption height"),
    	SM_CXSMSIZE, TEXT("SM_CXSMSIZE"), TEXT("Small caption button width"),
    	SM_CYSMSIZE, TEXT("SM_CYSMSIZE"), TEXT("Small caption button height"),
    	SM_CXMENUSIZE, TEXT("SM_CXMENUSIZE"), TEXT("Menu bar button width"),
    	SM_CYMENUSIZE, TEXT("SM_CYMENUSIZE"), TEXT("Menu bar button height"),
    	SM_ARRANGE, TEXT("SM_ARRANGE"), TEXT("How minimized windows arranged"),
    	SM_CXMINIMIZED, TEXT("SM_CXMINIMIZED"), TEXT("Minimized window width"),
    	SM_CYMINIMIZED, TEXT("SM_CYMINIMIZED"), TEXT("Minimized window height"),
    	SM_CXMAXTRACK, TEXT("SM_CXMAXTRACK"), TEXT("Maximum draggable width"),
    	SM_CYMAXTRACK, TEXT("SM_CYMAXTRACK"), TEXT("Maximum draggable height"),
    	SM_CXMAXIMIZED, TEXT("SM_CXMAXIMIZED"), TEXT("Width of maximized window"),
    	SM_CYMAXIMIZED, TEXT("SM_CYMAXIMIZED"), TEXT("Height of maximized window"),
    	SM_NETWORK, TEXT("SM_NETWORK"), TEXT("Network present flag"),
    	SM_CLEANBOOT, TEXT("SM_CLEANBOOT"), TEXT("How system was booted"),
    	SM_CXDRAG, TEXT("SM_CXDRAG"), TEXT("Avoid drag x tolerance"),
    	SM_CYDRAG, TEXT("SM_CYDRAG"), TEXT("Avoid drag y tolerance"),
    	SM_SHOWSOUNDS, TEXT("SM_SHOWSOUNDS"), TEXT("Present sounds visually"),
    	SM_CXMENUCHECK, TEXT("SM_CXMENUCHECK"), TEXT("Menu check-mark width"),
    	SM_CYMENUCHECK, TEXT("SM_CYMENUCHECK"), TEXT("Menu check-mark height"),
    	SM_SLOWMACHINE, TEXT("SM_SLOWMACHINE"), TEXT("Slow processor flag"),
    	SM_MIDEASTENABLED, TEXT("SM_MIDEASTENABLED"), TEXT("Hebrew and Arabic enabled flag"),
    	SM_MOUSEWHEELPRESENT, TEXT("SM_MOUSEWHEELPRESENT"), TEXT("Mouse wheel present flag"),
    	SM_XVIRTUALSCREEN, TEXT("SM_XVIRTUALSCREEN"), TEXT("Virtual screen x origin"),
    	SM_YVIRTUALSCREEN, TEXT("SM_YVIRTUALSCREEN"), TEXT("Virtual screen y origin"),
    	SM_CXVIRTUALSCREEN, TEXT("SM_CXVIRTUALSCREEN"), TEXT("Virtual screen width"),
    	SM_CYVIRTUALSCREEN, TEXT("SM_CYVIRTUALSCREEN"), TEXT("Virtual screen height"),
    	SM_CMONITORS, TEXT("SM_CMONITORS"), TEXT("Number of monitors"),
    	SM_SAMEDISPLAYFORMAT, TEXT("SM_SAMEDISPLAYFORMAT"), TEXT("Same color format flag")
    };
    
    #endif /*_METICS_H__*/

    ScrollTest.cpp

  • #include "Metrics.h"
    
    LRESULT CALLBACK pfnWndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance,		
    	HINSTANCE hPrevInstance,	
    	PSTR szCmdLine,			
    	int iCmdShow)		
    {
    	MSG stMsg;
    	memset(&stMsg, 0, sizeof (stMsg));
    	HWND stHwnd;
    	memset(&stHwnd, 0, sizeof (stHwnd));
    	WNDCLASS stWndClass;
    	memset(&stWndClass, 0, sizeof (stWndClass));
    	const TCHAR szAppName[] = TEXT("SCROLL TEST");
    
    	stWndClass.style = CS_HREDRAW | CS_VREDRAW;	
    	stWndClass.lpfnWndProc = pfnWndProc;
    	stWndClass.cbClsExtra = 0;
    	stWndClass.cbWndExtra = 0;
    
    	stWndClass.hInstance = hInstance;
    	stWndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	stWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    	stWndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	stWndClass.lpszMenuName = NULL;
    	stWndClass.lpszClassName = szAppName;
    
    	if (!RegisterClass(&stWndClass))
    	{
    		MessageBox(NULL, TEXT("Regiester failure"), szAppName, MB_ICONERROR);
    		return 0;
    	}
    
    	stHwnd = CreateWindow(szAppName,			
    						  TEXT("SCROLL TEST"),		
    						  WS_OVERLAPPEDWINDOW | WS_VSCROLL /*| WS_HSCROLL*/,  
    						  CW_USEDEFAULT,		
    						  CW_USEDEFAULT,		
    						  CW_USEDEFAULT,		
    						  CW_USEDEFAULT,		
    						  NULL,					
    						  NULL,					
    						  hInstance,			
    						  NULL);			
    
    	ShowWindow(stHwnd, iCmdShow);				
    	UpdateWindow(stHwnd);						
    
    	while (GetMessage(&stMsg, NULL, 0, 0))
    	{
    		TranslateMessage(&stMsg);
    		DispatchMessage(&stMsg);
    	}
    
    	return stMsg.wParam;
    }
    
    LRESULT CALLBACK pfnWndProc(HWND stHwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
    {
    	HDC stHdc;
    	memset(&stHdc, 0, sizeof (stHdc));
    	PAINTSTRUCT stPs;
    	memset(&stPs, 0, sizeof (stPs));
    	RECT stRect;
    	memset(&stRect, 0, sizeof (stRect));
    	TEXTMETRIC stTextMetric;
    	memset(&stTextMetric, 0, sizeof (stTextMetric));
    
    	int iYpos = 0;
    
    	static int s_iCharWidth = 0;
    	static int s_iCharHeight = 0;
    	static int s_iClientHeight = 0;
    	static int s_iVScrollPos = 0;
    	static int s_iCapitalCharWidth = 0;
    
    	switch (uiMsg)
    	{
    	case WM_CREATE:
    		stHdc = GetDC(stHwnd);//GDI函式入口
    
    		GetTextMetrics(stHdc, &stTextMetric);//获取系统文字字元结构
    		s_iCharWidth = stTextMetric.tmAveCharWidth;//字元宽度
    		s_iCapitalCharWidth = (stTextMetric.tmPitchAndFamily & 1 ? 3 : 2) * s_iCharWidth / 2;//大字字元宽度
    		s_iCharHeight = stTextMetric.tmHeight + stTextMetric.tmExternalLeading;//字元高度
    
    		ReleaseDC(stHwnd, stHdc);
    
    		SetScrollRange(stHwnd, SB_VERT, 0, NUMLINES - 1, FALSE);
    		SetScrollPos(stHwnd, SB_VERT, s_iVScrollPos, TRUE);
    		return 0;
    
    	case WM_SIZE:
    		s_iClientHeight = HIWORD(lParam);
    		return 0;
    
    	case WM_VSCROLL:
    		switch (LOWORD(wParam))
    		{
    		case SB_LINEUP:
    			s_iVScrollPos -= 1;
    			break;
    		case SB_LINEDOWN:
    			s_iVScrollPos += 1;
    			break;
    		case SB_PAGEUP:
    			s_iVScrollPos -= s_iClientHeight / s_iCharHeight;
    			break;
    		case SB_PAGEDOWN:
    			s_iVScrollPos += s_iClientHeight / s_iCharHeight;
    			break;
    		case SB_THUMBPOSITION:
    			s_iVScrollPos = HIWORD(wParam);
    			break;
    		default:
    			break;
    		}
    
    		s_iVScrollPos = max(0, min(s_iVScrollPos, NUMLINES - 1));
    		if (s_iVScrollPos != GetScrollPos(stHwnd, SB_VERT))
    		{
    			SetScrollPos(stHwnd, SB_VERT, s_iVScrollPos, TRUE);
    			InvalidateRect(stHwnd, NULL, TRUE);
    			/*设置滑块新的位置,但是这里没有产生WM_PAINT的触发条件,
    			  使用InvalidateRect强制使用显示区域无效*/
    			UpdateWindow(stHwnd);
    			//如果系统任务多时,WM_PAINT消息优先级低,需要等待WM_PAINT消息响应
    			//UpdateWindow可以通知系统立即处理WM_PAINT消息
    		}
    		
    
    		return 0;
    
    	case WM_PAINT:
    		stHdc = BeginPaint(stHwnd, &stPs);
    
    		for (int iNum = 0; iNum < NUMLINES; iNum++)
    		{
    			iYpos = s_iCharHeight * (iNum - s_iVScrollPos);
    			TextOut(stHdc, 0, iYpos, sysmetrics[iNum].szLabel, lstrlen(sysmetrics[iNum].szLabel));
    			TextOut(stHdc, 40 * s_iCapitalCharWidth, iYpos, sysmetrics[iNum].szDesc, lstrlen(sysmetrics[iNum].szDesc));
    		}
    
    		EndPaint(stHwnd, &stPs);
    		return 0;
    
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    
    	default:
    		return DefWindowProc(stHwnd, uiMsg, wParam, lParam);
    	}
    }

     

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值