Freigeben über


Gewusst wie: Scrollen von Text

In diesem Abschnitt werden die Änderungen beschrieben, die Sie an der Standard-Fensterprozedur einer Anwendung vornehmen können, um einem Benutzer das Scrollen von Text zu ermöglichen. Das Beispiel in diesem Abschnitt erstellt und zeigt ein Array von Textzeichenfolgen an und verarbeitet WM_HSCROLL und WM_VSCROLL Bildlaufleistennachrichten, sodass der Benutzer text vertikal und horizontal scrollen kann.

Wichtige Informationen

Technologien

Voraussetzungen

  • C/C++
  • Programmierung der Windows-Benutzeroberfläche

Anweisungen

Verarbeiten der WM_CREATE-Nachricht

Bildlaufeinheiten werden in der Regel während der Verarbeitung der WM_CREATE-Nachricht festgelegt. Es ist praktisch, die Bildlaufeinheiten auf den Abmessungen der Schriftart zu basieren, die dem Gerätekontext (Device Context, DC) des Fensters zugeordnet ist. Verwenden Sie die GetTextMetrics-Funktion , um die Schriftdimensionen für einen bestimmten DC abzurufen.

Im Beispiel in diesem Abschnitt entspricht eine vertikale Bildlaufeinheit der Höhe einer Zeichenzelle zuzüglich einer externen Voranführung. Eine horizontale Bildlaufeinheit entspricht der durchschnittlichen Breite einer Zeichenzelle. Die horizontalen Bildlaufpositionen entsprechen daher nicht den tatsächlichen Zeichen, es sei denn, die Bildschirmschriftart hat eine feste Breite.

Verarbeiten der WM_SIZE Nachricht

Bei der Verarbeitung der WM_SIZE Nachricht ist es praktisch, den Bildlaufbereich und die Scrollposition so anzupassen, dass die Abmessungen des Clientbereichs sowie die Anzahl der angezeigten Textzeilen berücksichtigt werden.

Die SetScrollInfo-Funktion legt die minimalen und maximalen Positionswerte, die Seitengröße und die Bildlaufposition für eine Bildlaufleiste fest.

Verarbeiten der WM_HSCROLL- und WM_VSCROLL-Nachrichten

Die Bildlaufleiste sendet WM_HSCROLL und WM_VSCROLL Nachrichten an die Fensterprozedur, wenn der Benutzer auf die Bildlaufleiste klickt oder das Bildlauffeld zieht. Die Wörter mit niedriger Reihenfolge WM_VSCROLL und WM_HSCROLL enthalten jeweils einen Anforderungscode, der die Richtung und Größe der Scrollaktion angibt.

Wenn die WM_HSCROLL und WM_VSCROLL Meldungen verarbeitet werden, wird der Anforderungscode der Bildlaufleiste untersucht und das Bildlaufinkrement berechnet. Nachdem das Inkrement auf die aktuelle Bildlaufposition angewendet wurde, wird das Fenster mithilfe der ScrollWindowEx-Funktion zur neuen Position gescrollt, und die Position des Bildlauffelds wird mithilfe der SetScrollInfo-Funktion angepasst.

Nachdem ein Fenster gescrollt wurde, wird ein Teil des Clientbereichs ungültig gemacht. Um sicherzustellen, dass die ungültige Region aktualisiert wird, wird die Funktion UpdateWindow verwendet, um eine WM_PAINT Meldung zu generieren.

Verarbeiten der WM_PAINT-Nachricht

Bei der Verarbeitung der WM_PAINT Nachricht ist es praktisch, die Textzeilen zu zeichnen, die im ungültigen Teil des Fensters angezeigt werden sollen. Im folgenden Beispiel werden die aktuelle Bildlaufposition und die Dimensionen des ungültigen Bereichs verwendet, um den Zeilenbereich innerhalb des ungültigen Bereichs zu bestimmen, um sie anzuzeigen.

Beispiel für textscrollenden Text

Das folgende Beispiel ist eine Fensterprozedur für ein Fenster, in dem Text im Clientbereich angezeigt wird. Im Beispiel wird veranschaulicht, wie der Text als Reaktion auf Eingaben aus den horizontalen und vertikalen Bildlaufleisten gescrollt wird.

#include "strsafe.h"

LRESULT CALLBACK MyTextWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc; 
PAINTSTRUCT ps; 
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;
size_t abcLength;        // length of an abc[] item 

// Create an array of lines to display. 
#define LINES 28 
static TCHAR *abc[] = { 
       TEXT("anteater"),  TEXT("bear"),      TEXT("cougar"), 
       TEXT("dingo"),     TEXT("elephant"),  TEXT("falcon"), 
       TEXT("gazelle"),   TEXT("hyena"),     TEXT("iguana"), 
       TEXT("jackal"),    TEXT("kangaroo"),  TEXT("llama"), 
       TEXT("moose"),     TEXT("newt"),      TEXT("octopus"), 
       TEXT("penguin"),   TEXT("quail"),     TEXT("rat"), 
       TEXT("squid"),     TEXT("tortoise"),  TEXT("urus"), 
       TEXT("vole"),      TEXT("walrus"),    TEXT("xylophone"), 
       TEXT("yak"),       TEXT("zebra"),
       TEXT("This line contains words, but no character. Go figure."),
       TEXT("")
     }; 
 
switch (uMsg) 
{ 
    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; 
 
    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; 
    case WM_HSCROLL:
        // Get all the vertial scroll bar information.
        si.cbSize = sizeof (si);
        si.fMask  = SIF_ALL;

        // Save the position for comparison later on.
        GetScrollInfo (hwnd, SB_HORZ, &si);
        xPos = si.nPos;
        switch (LOWORD (wParam))
        {
        // User clicked the left arrow.
        case SB_LINELEFT: 
            si.nPos -= 1;
            break;
              
        // User clicked the right arrow.
        case SB_LINERIGHT: 
            si.nPos += 1;
            break;
              
        // User clicked the scroll bar shaft left of the scroll box.
        case SB_PAGELEFT:
            si.nPos -= si.nPage;
            break;
              
        // User clicked the scroll bar shaft right of the scroll box.
        case SB_PAGERIGHT:
            si.nPos += si.nPage;
            break;
              
        // User dragged the scroll box.
        case SB_THUMBTRACK: 
            si.nPos = si.nTrackPos;
            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_HORZ, &si, TRUE);
        GetScrollInfo (hwnd, SB_HORZ, &si);
         
        // If the position has changed, scroll the window.
        if (si.nPos != xPos)
        {
            ScrollWindow(hwnd, xChar * (xPos - si.nPos), 0, NULL, NULL);
        }

        return 0;
         
    case WM_VSCROLL:
        // Get all the vertial 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;
              
        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);
        }

        return 0;
         
    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. Also, you must include
            // strsafe.h to use the StringCchLength function.
            hr = StringCchLength(abc[i], 55, &abcLength);
            if ((FAILED(hr))|(abcLength == NULL))
            {
                //
                // TODO: write error handler
                //
            }

            // Write a line of text to the client area.
            TextOut(hdc, x, y, abc[i], abcLength); 
        }

        // Indicate that painting is finished.
        EndPaint (hwnd, &ps);
        return 0;
         
    case WM_DESTROY :
        PostQuitMessage (0);
        return 0;
    }

    return DefWindowProc (hwnd, uMsg, wParam, lParam);
}

Verwenden von Bildlaufleisten

Demo zu allgemeinen Windows-Steuerelementen (CppWindowsCommonControls)