Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

   Программирование -> C/C++ -> Уроки программирования на C/C++ под Windows 95


Улучшенная прокрутка


Вы наверное заметили, что вертикальная прокрутка, организованная в предыдущей программе, не очень эффективна. На данном уроке мы улучшим вертикальную прокрутку и добавим горизонтальную.
Вот пример программы:


//файл sm.h остался прежним, поэтому он здесь не приводится



//файл main.cpp

#include <windows.h>

#include "sm.h"



//описание оконной процедуры

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);



//Это главная функция программы.

int WINAPI WinMain(HINSTANCE hInst,

                   HINSTANCE hPrevInst,

                   PSTR szCmdLine,

                   int iCmdShow)

{

  HWND hwnd;

  MSG  msg;

  WNDCLASSEX w;

  static CHAR *szAppName={"TextOutExample"};

  w.cbSize=sizeof(w);

  w.style=CS_HREDRAW|CS_VREDRAW;

  w.lpfnWndProc=WndProc;

  w.cbClsExtra=0;

  w.cbWndExtra=0;

  w.hInstance=hInst;

  w.hIcon=LoadIcon(NULL,IDI_APPLICATION);

  w.hCursor=LoadCursor(NULL,IDC_ARROW);

  w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);

  w.lpszMenuName=NULL;

  w.lpszClassName=szAppName;

  w.hIconSm=w.hIcon;

  RegisterClassEx(&w);



  hwnd=CreateWindow(

       szAppName,

       "System metrics",

       WS_OVERLAPPEDWINDOW|WS_VSCROLL,

       CW_USEDEFAULT, CW_USEDEFAULT,

       CW_USEDEFAULT, CW_USEDEFAULT,

       NULL,

       NULL,

       hInst,

       NULL);

  ShowWindow(hwnd,iCmdShow);

  UpdateWindow(hwnd);



  while(GetMessage(&msg,NULL,0,0))

  {

    TranslateMessage(&msg);

    DispatchMessage(&msg);

  }

  return msg.wParam;

}



//Оконная процедура

LRESULT CALLBACK WndProc(HWND hwnd, UINT imsg,

                         WPARAM wParam, LPARAM lParam)

{

  PAINTSTRUCT ps;

  HDC         hdc;

  TEXTMETRIC  tm;

  static int  cxChar,cyChar,iVscrollPos=0,iVscrollMax,cyClient,cxClient,

              iMaxWidth,iHscrollMax,iHscrollPos;

  int         iPaintBeg,iPaintEnd,iVscrollInc,iHscrollInc,i,x,y;

  CHAR        szBuffer[10];



  switch(imsg)

  {

    case WM_CREATE:

         hdc=GetDC(hwnd);

         GetTextMetrics(hdc,&tm);

         cxChar=tm.tmAveCharWidth;

         cyChar=tm.tmHeight+tm.tmExternalLeading;

         iMaxWidth=120*cxChar;

         ReleaseDC(hwnd,hdc);

         return 0;



    case WM_SIZE:

         cxClient=LOWORD(lParam);

         cyClient=HIWORD(lParam);



         iVscrollMax=max(0, N_LINES+2-cyClient/cyChar);

         iVscrollPos=min(iVscrollPos, iVscrollMax);

         SetScrollRange(hwnd,SB_VERT,0,iVscrollMax,FALSE);

         SetScrollPos(hwnd,SB_VERT,iVscrollPos,TRUE);



         iHscrollMax=max(0, 2+(iMaxWidth-cxClient)/cxChar);

         iHscrollPos=min(iHscrollPos,iHscrollMax);

         SetScrollRange(hwnd,SB_HORZ,0,iHscrollMax,FALSE);

         SetScrollPos(hwnd,SB_HORZ,iHscrollPos,TRUE);

         return 0;



    case WM_PAINT:

         hdc=BeginPaint(hwnd, &ps);

         iPaintBeg=max(0,iVscrollPos+ps.rcPaint.top/cyChar-1);

         iPaintEnd=min(N_LINES,iVscrollPos+ps.rcPaint.bottom/cyChar);



         for(i=iPaintBeg; i<iPaintEnd; i++)

         {

           x=cxChar*(1-iHscrollPos);

           y=cyChar*(1-iVscrollPos+i);

           TextOut(hdc,x,y,sm[i].szLabel,

                   lstrlen(sm[i].szLabel));

           wsprintf(szBuffer,"%5d",

                    GetSystemMetrics(sm[i].i));

           TextOut(hdc,x+22*cxChar,y,szBuffer,

                   lstrlen(szBuffer));

           TextOut(hdc,x+24*cxChar+8*cxChar,y,

                   sm[i].szDesc,lstrlen(sm[i].szDesc));

         }

         EndPaint(hwnd, &ps);

         return 0;



    case WM_VSCROLL:

         switch(LOWORD(wParam))

         {

           case SB_TOP:

                iVscrollInc = -iVscrollPos; break;

           case SB_BOTTOM:

                iVscrollInc = iVscrollMax-iVscrollPos; break;

           case SB_LINEUP:

                iVscrollInc = -1;

                break;

           case SB_LINEDOWN:

                iVscrollInc = 1;

                break;

           case SB_PAGEUP:

                iVscrollInc = min(-1,-cyClient/cyChar);

                break;

           case SB_PAGEDOWN:

                iVscrollInc = max(1,cyClient/cyChar);

                break;

           case SB_THUMBTRACK:

                iVscrollInc=HIWORD(wParam)-iVscrollPos;

                break;

           default: iVscrollInc=0;

         }



         iVscrollInc=max(-iVscrollPos,

                         min(iVscrollInc,iVscrollMax-iVscrollPos));

         if(iVscrollInc!=0)

         {

           iVscrollPos += iVscrollInc;

           ScrollWindow(hwnd,0,-cyChar*iVscrollInc,NULL,NULL);

           SetScrollPos(hwnd,SB_VERT,iVscrollPos,TRUE);

           UpdateWindow(hwnd);

         }

         return 0;



    case WM_HSCROLL:

         switch(LOWORD(wParam))

         {

           case SB_LINEUP:

                iHscrollInc=-1; break;

           case SB_LINEDOWN:

                iHscrollInc=1; break;

           case SB_PAGEUP:

                iHscrollInc=-8; break;

           case SB_PAGEDOWN:

                iHscrollInc=8; break;

           case SB_THUMBPOSITION:

                iHscrollInc=HIWORD(wParam)-iHscrollPos;

                break;

           default: iHscrollInc=0;

         }

         iHscrollInc=max(-iHscrollPos,

                         min(iHscrollInc,iHscrollMax-iHscrollPos));

         if(iHscrollInc!=0)

         {

           iHscrollPos+=iHscrollInc;

           ScrollWindow(hwnd,-cxChar*iHscrollInc,0,NULL,NULL);

           SetScrollPos(hwnd,SB_HORZ,iHscrollPos,TRUE);

         }

         return 0;



    case WM_DESTROY:

         PostQuitMessage(0);

         return 0;

  }



  return DefWindowProc(hwnd,imsg,wParam,lParam);

}

В этой программе есть небольшие улучшения:

  • Вы не сможете прокрутить окно так, чтобы последняя строка оказалась в самом верху. Прокрутка продолжается только до тех пор, пока появится последняя строка. Для того, чтобы сделать это, программа расчитывает диапазон полосы прокрутки и положение бегунка при обработке сообщения WM_SIZE. (Сообщение WM_SIZE посылается окну тогда, когда изменяется его размеры). Диапазон прокрутки вычисляется на основании числа строк текста (N_LINES) и размера рабочей области (cyClient).
    Если рабочая область будет достаточно велика, чтобы в ней поместились все строки, тогда минимальное и максимальное положение диапазона прокрутки будет равно нулю. Это приведет к тому, что Windows удалит полосу прокрутки, т.к. она уже больше не нужна.
    Аналогично, если ширина рабочей области будет достаточна для отображения 120 символов (см. WM_CREATE: ... iMaxWidth=120*cxChar;), то исчезнет и горизонтальная полоса прокрутки.
  • Перед тем, как прокрутить окно, расчитывается приращение текущей позиции прокрутки - iVscrollInc (для вертикальной прокрутки), iHscrollInc (для горизонтальной прокрутки). Затем выполняется прокрутка окна с помощью функции

ScrollWindow(hwnd, xInc, yInc, pRect, pClipRect);


Параметры xInc и yInc задают величину прокрутки. Параметры pRect и pClipRect устанавливаются в NULL для того, чтобы прокрутить всю рабочую область.
В результате вызова функции ScrollWindow рабочая область, открываемая после прокрутки, делается недействительной, что заставляет Windows послать окну сообщение WM_PAINT. При обработке этого сообщения перерисовываются те строки, которых не было видно до прокрутки окна (а не все строки, как в предыдущей версии программы).

  • Поскольку сообщение WM_PAINT обрабатывается быстрее, чем в предыдущей версии программы (т.к. перерисовываются не все строки, а только вновь открытые), теперь программа обрабатывает сообщение SB_THUMBTRACK вместо SB_THUMBPOSITION, т.е. теперь вертикальная прокрутка выполняется при движении ползунка, а не при отпускании левой клавиши мыши, как в предыдущей версии.

[   ОГЛАВЛЕНИЕ   ]


 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.
 
Rambler's Top100