本节介绍了基于 Windows 的应用程序中对使用滚动条进行平移的支持。
在 Windows 7 中,平移笔势会生成 WM_*SCROLL 消息以启用对平移的旧版支持。由于您的应用程序可能不支持所有 WM_*SCROLL 消息,因此平移可能无法正常工作。本主题介绍了为确保应用程序中的旧版平移体验如用户预期那样正常工作所必须执行的步骤。
概述
以下各部分说明如何启用旧版平移体验:
- 创建带滚动条的应用程序。
- 禁用划动。
- 自定义平移体验。
创建带滚动条的应用程序
使用 Microsoft Visual Studio 向导启动新的 Win32 项目。确保将应用程序类型设置为 Windows 应用程序。您无需启用对活动模板库 (ATL) 的支持。在启动项目后,它将如下图所示。
接下来,在图像上启用滚动条。更改 InitInstance 中的窗口创建代码,以便 CreateWindow 函数调用创建一个带滚动条的窗口。以下代码演示如何执行此操作。
hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VSCROLL, // style 200, // x 200, // y 550, // width 300, // height NULL, NULL, hInstance, NULL );
在更改窗口创建代码之后,应用程序将具有一个滚动条。下图显示了应用程序此时可能具有的外观。
在更改窗口创建代码之后,将滚动条对象添加到应用程序,并添加一些文本以便进行滚动。将以下代码置于 WndProc方法的顶部。
TEXTMETRIC tm; SCROLLINFO si; // These variables are required to display text. static int xClient; // width of client area static int yClient; // height of client area static int xClientMax; // maximum width of client area static int xChar; // horizontal scrolling unit static int yChar; // vertical scrolling unit static int xUpper; // average width of uppercase letters static int xPos; // current horizontal scrolling position static int yPos; // current vertical scrolling position int i; // loop counter int x, y; // horizontal and vertical coordinates int FirstLine; // first line in the invalidated area int LastLine; // last line in the invalidated area HRESULT hr; int abcLength = 0; // length of an abc[] item int lines = 0; // Create an array of lines to display. static const int LINES=28; static LPCWSTR abc[] = { L"anteater", L"bear", L"cougar", L"dingo", L"elephant", L"falcon", L"gazelle", L"hyena", L"iguana", L"jackal", L"kangaroo", L"llama", L"moose", L"newt", L"octopus", L"penguin", L"quail", L"rat", L"squid", L"tortoise", L"urus", L"vole", L"walrus", L"xylophone", L"yak", L"zebra", L"This line contains words, but no character. Go figure.", L"" };
紧接着,实现应用程序逻辑以便为文本度量配置文本计算。以下代码应替换 WndProc 函数中的现有 WM_CREATE 用例。
case WM_CREATE : // Get the handle to the client area's device context. hdc = GetDC (hWnd); // Extract font dimensions from the text metrics. GetTextMetrics (hdc, &tm); xChar = tm.tmAveCharWidth; xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2; yChar = tm.tmHeight + tm.tmExternalLeading; // Free the device context. ReleaseDC (hWnd, hdc); // Set an arbitrary maximum width for client area. // (xClientMax is the sum of the widths of 48 average // lowercase letters and 12 uppercase letters.) xClientMax = 48 * xChar + 12 * xUpper; return 0;
然后,在调整窗口大小时,为文本块的重新计算实现应用程序逻辑。应将以下代码置于 WndProc 中的消息开关中。
case WM_SIZE: // Retrieve the dimensions of the client area. yClient = HIWORD (lParam); xClient = LOWORD (lParam); // Set the vertical scrolling range and page size si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE; si.nMin = 0; si.nMax = LINES - 1; si.nPage = yClient / yChar; SetScrollInfo(hWnd, SB_VERT, &si, TRUE); // Set the horizontal scrolling range and page size. si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE; si.nMin = 0; si.nMax = 2 + xClientMax / xChar; si.nPage = xClient / xChar; SetScrollInfo(hWnd, SB_HORZ, &si, TRUE); return 0;
接下来,为垂直滚动消息实现应用程序逻辑。应将以下代码置于 WndProc 中的消息开关中。
case WM_VSCROLL: // Get all the vertical scroll bar information si.cbSize = sizeof (si); si.fMask = SIF_ALL; GetScrollInfo (hWnd, SB_VERT, &si); // Save the position for comparison later on yPos = si.nPos; switch (LOWORD (wParam)) { // user clicked the HOME keyboard key case SB_TOP: si.nPos = si.nMin; break; // user clicked the END keyboard key case SB_BOTTOM: si.nPos = si.nMax; break; // user clicked the top arrow case SB_LINEUP: si.nPos -= 1; break; // user clicked the bottom arrow case SB_LINEDOWN: si.nPos += 1; break; // user clicked the scroll bar shaft above the scroll box case SB_PAGEUP: si.nPos -= si.nPage; break; // user clicked the scroll bar shaft below the scroll box case SB_PAGEDOWN: si.nPos += si.nPage; break; // user dragged the scroll box case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; // user positioned the scroll box // This message is the one used by Windows Touch case SB_THUMBPOSITION: si.nPos = HIWORD(wParam); break; default: break; } // Set the position and then retrieve it. Due to adjustments // by Windows it may not be the same as the value set. si.fMask = SIF_POS; SetScrollInfo (hWnd, SB_VERT, &si, TRUE); GetScrollInfo (hWnd, SB_VERT, &si); // If the position has changed, scroll window and update it if (si.nPos != yPos) { ScrollWindow(hWnd, 0, yChar * (yPos - si.nPos), NULL, NULL); UpdateWindow (hWnd); } break;
然后,更新代码以重新绘制窗口。以下代码应替换 WndProc 中的默认 WM_PAINT 用例。
case WM_PAINT: // Prepare the window for painting hdc = BeginPaint (hWnd, &ps); // Get vertical scroll bar position si.cbSize = sizeof (si); si.fMask = SIF_POS; GetScrollInfo (hWnd, SB_VERT, &si); yPos = si.nPos; // Get horizontal scroll bar position GetScrollInfo (hWnd, SB_HORZ, &si); xPos = si.nPos; // Find painting limits FirstLine = max (0, yPos + ps.rcPaint.top / yChar); LastLine = min (LINES - 1, yPos + ps.rcPaint.bottom / yChar); for (i = FirstLine; i <= LastLine; i++) { x = xChar * (1 - xPos); y = yChar * (i - yPos); // Note that "55" in the following depends on the // maximum size of an abc[] item. // abcLength = wcslen(abc[i]); hr = S_OK; if ((FAILED(hr))) { MessageBox(hWnd, L"err", L"err", NULL); }else{ TextOut(hdc, x, y, abc[i], abcLength); } } // Indicate that painting is finished EndPaint (hWnd, &ps); return 0;
现在,当生成并运行应用程序时,它应具有样板文本和垂直滚动条。下图显示了应用程序的可能外观。
禁用划动
若要改进应用程序中的平移体验,您应关闭划动。为此,请在初始化 hWnd 值时设置其窗口属性。用于划动的值将存储在 tpcshrd.h 标头中,因此还必须包含该标头。在创建 hWnd 之后,应将以下代码置于包含指令和 InitInstance 函数中。
#include <tpcshrd.h>
[...] BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){ [...]
const DWORD_PTR dwHwndTabletProperty = TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves) TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down (circle) TABLET_DISABLE_FLICKS; // disables pen flicks (back, forward, drag down, drag up) SetProp(hWnd, MICROSOFT_TABLETPENSERVICE_PROPERTY, reinterpret_cast<HANDLE>(dwHwndTabletProperty));
自定义平移体验
默认情况下,您可能需要与 Windows 7 提供的平移体验不同的平移体验。若要改进平移体验,您必须为WM_GESTURE 消息添加处理程序。有关更多信息,请参见改进单指平移体验。
转自:http://msdn.microsoft.com/zh-cn/library/windows/desktop/dd562171(v=vs.85).aspx