Guide pratique pour faire défiler le texte
Cette section décrit les modifications que vous pouvez apporter à la procédure de fenêtre main d’une application pour permettre à un utilisateur de faire défiler le texte. L’exemple de cette section crée et affiche un tableau de chaînes de texte et traite WM_HSCROLL et WM_VSCROLL messages de barre de défilement afin que l’utilisateur puisse faire défiler le texte à la fois verticalement et horizontalement.
Bon à savoir
Technologies
Prérequis
- C/C++
- Programmation de l’interface utilisateur Windows
Instructions
Traitement du message WM_CREATE
Les unités de défilement sont généralement définies lors du traitement du message WM_CREATE . Il est pratique de baser les unités de défilement sur les dimensions de la police associée au contexte d’appareil (DC) de la fenêtre. Pour récupérer les dimensions de police d’un contrôleur de domaine spécifique, utilisez la fonction GetTextMetrics .
Dans l’exemple de cette section, une unité de défilement vertical équivaut à la hauteur d’une cellule de caractère, plus le début externe. Une unité de défilement horizontal équivaut à la largeur moyenne d’une cellule de caractère. Les positions de défilement horizontales ne correspondent donc pas aux caractères réels, sauf si la police d’écran est à largeur fixe.
Traitement du message WM_SIZE
Lors du traitement du WM_SIZE message, il est pratique d’ajuster la plage de défilement et la position de défilement pour refléter les dimensions de la zone cliente ainsi que le nombre de lignes de texte qui seront affichées.
La fonction SetScrollInfo définit les valeurs de position minimale et maximale, la taille de page et la position de défilement d’une barre de défilement.
Traitement des messages WM_HSCROLL et WM_VSCROLL
La barre de défilement envoie WM_HSCROLL et WM_VSCROLL messages à la procédure de fenêtre chaque fois que l’utilisateur clique sur la barre de défilement ou fait glisser la zone de défilement. Les mots de bas ordre de WM_VSCROLL et WM_HSCROLL contiennent chacun un code de requête qui indique la direction et l’ampleur de l’action de défilement.
Lorsque les messages WM_HSCROLL et WM_VSCROLL sont traités, le code de demande de barre de défilement est examiné et l’incrément de défilement est calculé. Une fois l’incrément appliqué à la position de défilement actuelle, la fenêtre fait défiler vers la nouvelle position à l’aide de la fonction ScrollWindowEx , et la position de la zone de défilement est ajustée à l’aide de la fonction SetScrollInfo .
Une fois qu’une fenêtre fait défiler, une partie de sa zone cliente est rendue non valide. Pour vous assurer que la région non valide est mise à jour, la fonction UpdateWindow est utilisée pour générer un message WM_PAINT .
Traitement du message WM_PAINT
Lors du traitement du message WM_PAINT , il est pratique de dessiner les lignes de texte que vous souhaitez afficher dans la partie non valide de la fenêtre. L’exemple suivant utilise la position de défilement actuelle et les dimensions de la région non valide pour déterminer la plage de lignes dans la région non valide afin de les afficher.
Exemple de défilement de texte
L’exemple suivant est une procédure de fenêtre pour une fenêtre qui affiche du texte dans sa zone cliente. L’exemple montre comment faire défiler le texte en réponse à une entrée à partir des barres de défilement horizontales et verticales.
#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);
}
Rubriques connexes