Меняем цвет scroll bar в приложении mfc


Содержание

Элементы управления (MFC) Controls (MFC)

Элементы управления — это объекты, используемые для ввода данных и работы с ними. Controls are objects that users can interact with to enter or manipulate data. Как правило, они отображаются в диалоговых окнах и на панелях инструментов. They commonly appear in dialog boxes or on toolbars. В этом документе рассматриваются три основных типа элементов управления. This topic family covers three main kinds of controls:

Стандартные элементы управления Windows, включая создаваемые владельцем элементы управления Windows common controls, including owner-drawn controls

Элементы управления ActiveX ActiveX Controls

Другие классы элементов управления из библиотеки MFC Other control classes supplied by the Microsoft Foundation Class Library (MFC)

Стандартные элементы управления Windows Windows Common Controls

В ОС Windows всегда существовал ряд стандартных элементов управления Windows. The Windows operating system has always provided a number of Windows common controls. Эти объекты элементов управления являются программируемыми и редактор диалоговых окон Visual C++ поддерживает их добавление в диалоговые окна. These control objects are programmable, and the Visual C++ dialog editor supports adding them to your dialog boxes. Библиотека MFC предоставляет классы, инкапсулирующие все эти элементы управления, как показано в таблице Стандартные элементы управления Windows и классы MFC. The Microsoft Foundation Class Library (MFC) supplies classes that encapsulate each of these controls, as shown in the table Windows Common Controls and MFC Classes. (Для некоторых элементов в таблице существуют связанные разделы с дальнейшим описанием. (Some items in the table have related topics that describe them further. Если для элементов управления связанные разделы отсутствуют, см. документацию по классу MFC.) For controls that lack topics, see the documentation for the MFC class.)

Класс CWnd является базовым для всех классов окон, включая все классы элементов управления. Class CWnd is the base class of all window classes, including all of the control classes.

Элементы управления ActiveX ActiveX Controls

Элементы управления ActiveX, ранее известные как элементы управления OLE, можно использовать в диалоговых окнах в приложениях для Windows или на HTML-страницах в Интернете. ActiveX controls, formerly known as OLE controls, can be used in dialog boxes in your applications for Windows, or in HTML pages on the World Wide Web. Более подробную информацию см. в разделе Элементы управления ActiveX MFC. For more information, see MFC ActiveX Controls.

Другие классы элементов управления MFC Other MFC Control Classes

Наряду с классами, инкапсулирующими все стандартные элементы управления Windows и поддерживающими программирование пользовательских элементов управления ActiveX (или использование элементов управления ActiveX, предоставляемых другими пользователями), MFC предоставляет следующие свои классы элементов управления: In addition to classes that encapsulate all of the Windows common controls and that support programming your own ActiveX controls (or using ActiveX controls supplied by others), MFC supplies the following control classes of its own:

Сведения о стандартных элементах управления Windows Finding Information About Windows Common Controls

В следующей таблице содержится краткое описание стандартных элементов управления Windows, включая класс-оболочку MFC элемента управления. The table below briefly describes each of the Windows common controls, including the control’s MFC wrapper class.

Стандартные элементы управления Windows и классы MFC Windows Common Controls and MFC Classes

Элемент управления Control Класс MFC MFC class Описание Description Новые в Windows 95 New in Windows 95
анимация animation CAnimateCtrl CAnimateCtrl Отображение последовательных кадров видеоролика AVI. Displays successive frames of an AVI video clip Да Yes
button button CButton CButton Кнопки, вызывающие действия; также используется для флажков, переключателей и полей групп. Pushbuttons that cause an action; also used for check boxes, radio buttons, and group boxes Нет No
поле со списком combo box CComboBox CComboBox Комбинация текстового поля и поля со списком. Combination of an edit box and a list box Нет No
элемент выбора даты и времени date and time picker CDateTimeCtrl CDateTimeCtrl Позволяет выбирать определенное значение даты или времени. Allows the user to choose a specific date or time value Да Yes
поле ввода edit box CEdit CEdit Поля для ввода текста. Boxes for entering text Нет No
расширенное поле со списком extended combo box CComboBoxEx CComboBoxEx Поле со списком с возможностью отображения изображений. A combo box control with the ability to display images Да Yes
заголовок header CHeaderCtrl CHeaderCtrl Кнопка, которая появляется над столбцом текста. Определяет ширину отображаемого текста. Button that appears above a column of text; controls width of text displayed Да Yes
сочетание клавиш hotkey CHotKeyCtrl CHotKeyCtrl Окно, позволяющее создавать сочетания клавиш для быстрого выполнения действий. Window that enables user to create a «hot key» to perform an action quickly Да Yes
список изображений image list CImageList CImageList Коллекция изображений, используемых для управления большими наборами значков и точечных рисунков (на самом деле список изображений не является элементом управления — он поддерживает списки, используемые другими элементами управления). Collection of images used to manage large sets of icons or bitmaps (image list isn’t really a control; it supports lists used by other controls) Да Yes
list list CListCtrl CListCtrl Окно, отображающее список текста со значками. Window that displays a list of text with icons Да Yes
список list box CListBox CListBox Поле, содержащее список строк. Box that contains a list of strings Нет No
календарь месяца month calendar CMonthCalCtrl CMonthCalCtrl Элемент управления, отображающий сведения о дате. Control that displays date information Да Yes
ход выполнения progress CProgressCtrl CProgressCtrl Окно, в котором отображается ход выполнения длительной операции. Window that indicates progress of a long operation Да Yes
главная панель rebar CRebarCtrl CRebarCtrl Панель инструментов, которая может содержать дополнительные дочерние окна в виде элементов управления. Tool bar that can contain additional child windows in the form of controls Да Yes
ввод с форматированием rich edit CRichEditCtrl CRichEditCtrl Окно, в котором можно выполнять редактирование с форматированием символов и абзацев (см. раздел Классы, связанные с элементами управления Rich Edit). Window in which user can edit with character and paragraph formatting (see Classes Related to Rich Edit Controls) Да Yes
полоса прокрутки scroll bar CScrollBar CScrollBar Полоса прокрутки, используемая как элемент управления в диалоговом окне (не в окне). Scroll bar used as a control inside a dialog box (not on a window) Нет No
ползунок slider CSliderCtrl CSliderCtrl Окно, содержащее элемент управления «Ползунок» с необязательными делениями. Window containing a slider control with optional tick marks Да Yes
кнопка «Счетчик» spin button CSpinButtonCtrl CSpinButtonCtrl Пара кнопок со стрелками для увеличения или уменьшения значения. Pair of arrow buttons user can click to increment or decrement a value Да Yes
статический текст static-text CStatic CStatic Текст для надписей других элементов управления. Text for labeling other controls Нет No
строка состояния status bar CStatusBarCtrl CStatusBarCtrl Окно для отображения сведений о состоянии, аналогичное классу MFC CStatusBar . Window for displaying status information, similar to MFC class CStatusBar Да Yes
вкладка tab CTabCtrl CTabCtrl Аналог разделителей в записной книжке. Используется в диалоговых окнах с вкладками или таблицах свойств. Analogous to the dividers in a notebook; used in «tab dialog boxes» or property sheets Да Yes
панель инструментов toolbar CToolBarCtrl CToolBarCtrl Окно с генерирующими команды кнопками, аналогичное классу MFC CToolBar . Window with command-generating buttons, similar to MFC class CToolBar Да Yes
подсказка tool tip CToolTipCtrl CToolTipCtrl Небольшое всплывающее окно с описанием назначения кнопки панели инструментов или другого инструмента. Small pop-up window that describes purpose of a toolbar button or other tool Да Yes
дерево tree CTreeCtrl CTreeCtrl Окно, в котором отображается иерархический список элементов. Window that displays a hierarchical list of items Да Yes

Что вы хотите узнать подробнее What do you want to know more about

Отдельный элемент управления: см. таблицу Стандартные элементы управления Windows и классы MFC в этом разделе, содержащую ссылки на все элементы управления. An individual control: see the table Windows Common Controls and MFC Classes in this topic for links to all controls

КАК сделать текст на экране прокручиваемым?

До сих пор мы как-то обходили эту тему. Вроде бы выводим графику, текст в рабочую область окна и всё гладко. Но так только до поры до времени. Представьте, что вы решили создать программу управляющую работой парового котла. Термодатчик каждую секунду снимает данные с термопары и отправляет на порт вашего компьютера. Программа считывает данные с порта и. Что с ними делать дальше? Можно, конечно, записывать их в файл, дописывая в конец всё новые данные показания. Так обычно и делается. А считывать их оттуда кто будет? Если пользователь должен будет открывать потом этот файл через «Блокнот» или «Wordpad», он будет долго ругаться. Гораздо лучше сделать всё в одной программе. На экране будет длинная таблица со значениями, прокрутив которую, вы сможете просмотреть всю историю. Да что там все эти специализированные программы. Все текстовые редакторы от Блокнота до Word имеют полосу прокрутки. Вы пользуетесь ими каждый день, совсем этого не замечая.

Для того, чтобы экран можно было прокручивать, надо добавить к окну полосу прокрутки или Scroll Bar. Не важно, будете вы выводить текст в главное окно или в диалоговое. Полосу прокрутки можно приделать даже к кнопке!

Разбёрём полосу прокрутки главного окна. Важно понимать, что когда пользователь перемещается по полосе вниз, его текст тем временем ползёт вверх. Кроме того, стрелки полосы прокрутки можно перемещать кнопками мыши, а можно стрелками клавиатуры и клавишами Page Up и Page Down. Можно ещё нажать левую кнопку мыши сверху или снизу движка, и он проскочит сразу несколько линий.

Все эти сообщения полосы Scroll Bar мы научимся обрабатывать сами. Вы сами сможете задавать переместиться тексту по нажатию кнопки PageDown до конца или на три строчки. Диапазон полосы полосы прокрутки и положение её движка тоже можно изменить в любой момент времени.

Полосы прокрутки бывают вертикальными и горизонтальными. В зависимости от типа, полоса посылает сообщения: WM_HSCROLL (горизонтальная) и WM_VSCROLL (вертикальная).

Как не странно, почему-то у всех пользователей полоса прокрутки вызывает дрожь в коленях и зубную боль. Не скрою, и я долго обходил эту тему, а потом долго нед ней бился. Поэтому в этой главе будет целых три примера. Они помогут разобраться с полосой

Начнём с очень полезной программы, которая, возможно будет вам ещё долго хорошим другом. И это не метафора. В любом языке программирования: C++, Java и др, где работают с палитрой 256 цветов, цвет получают сложением красного, зелёного и синего. Так называемая модель RGB. Занимаясь WEB-дизайном и задавая цвет гиперссылок, текста и фона, вы тоже сталкиваетесь с этой моделью, только цвет кодируется его 16-ричным эквивалентом. Так белый цвет RGB(0,0,0) будет в 16-ричной системе FFFFFF. А синий RGB(57,0,255) будет представлен как 390FF. Часто, чтобы подобрать нужный цвет в тех же программах на API или в WEB-дизайне вы долго подбирали цифры, чтобы получить более приятный оттенок. Вам никогда не хотелось этот процесс подбора автоматизировать?
Мне да, поэтому я написал следующую программу. Она сложна тем, что в ней всего много (как и подобает нормально работающей программе, которая приносит пользу). Но мы постараемся во всём разобраться.
Выглядеть это будет так:

Как видите, три полосы прокрутки, которые меняют значения трёх цветов. Эти значения моментально выводятся в три поля ввода. Кроме того, в правой части окна размещён цветной эллипс на белом фоне. Он будет менять свой цвет в зависимости от выбранных вами значений красного, синего и зелёного. Но и это ещё не всё. Под эллипсом размешёно окошечко, в котором будут меняться значения цвета в 16-ричном коде, откуда их всегда можно скопировать и вставить в исходник HTML-документа.

Но прежде, чем знакомиться с такой сложной программой, давайте познакомимся с полосой прокрутки. Что с ней можно делать?

1. Создание полосы прокрутки.
Поскольку это обычный элемент управления, создаётся Scroll Bar точно также, функцией CreateWindow. Вот пример создания одной горизонтальной полосы из этого примера:

hGreenScroll=CreateWindow(«scrollbar», NULL,
WS_CHILD|WS_VISIBLE|SBS_HORZ, 20, 160, 200, 25,
hWnd,(HMENU)-1, hInstance, NULL);

Тип элемента «scrollbar», расположение указывается в стиле SBS_HORZ или SBS_VERT. Дальше идут координаты левого верхнего угла, ширина и длина.

2. Задание диапазона Scroll Bar. Для этого существует специальная API функция SetScrollRange. Зачем надо задавать диапазон. Не лучше ли увеличивать значения, пока пользователю не надоест?
Совершенно очевидно, что для тех же цветов, их значения не могут принимать значения больше 255 и меньше 0. Если мы управляем сложным процессом, дорогое оборудование может выйти из строя или «зависнуть», если мы зададим скажем номер порта, который не существует или отрицательным.
Итак, вот как задаётся диапазон:

SetScrollRange(hRedScroll, SB_CTL, nxMin, nxMax, TRUE);
Здесь hRedScroll — идентификатор окна, созданного CreateWindow, SB_CTL — дескриптор полосы прокрутки, если она используется, как элемент управления; nxMin и nxMax — минимальное и максимальное значения для данной полосы. Последнее значение — булевское. Будет ли происходить перерисовка при установке нового диапазона.

3. Установка положения движка. После создания полос прокрутки и задания их диапазона, мы хотим установить движки на них в центральное положение. Для этого надо задать команду движку: «Встань в положение 127». Эти слова произносит API-функция SetScrollPos. Вот как это она делает:

SetScrollPos(hRedScroll, SB_CTL, nxPos, TRUE);

hRedScroll — это то окну, которому мы это говорим, SB_CTL — дескриптор полосы, nxPos — числовое значение, в данном случае, 127. Значение последнего аргумента — то же, что и в предыдущей функции.

4. Обработка сообщений
В зависимости от действий пользователя, полоса прокрутки передаёт следующие сообщения:

Сообщение Действие
SB_LINEUP Полоса передвинута на линию вверх (вертикальная)
SB_LINEDOWN Полоса передвинута на линию вниз
SB_LINELEFT Сдвиг на линию влево
SB_LINERIGHT Сдвиг на линию вправо
SB_PAGEUP Сдвиг на страницу вверх
SB_PAGEDOWN Сдвиг на страницу вниз
SB_PAGELEFT Сдвиг на влево
SB_PAGERIGHT Сдвиг на вправо
SB_THUMBPOSITION Позиция движка была изменена
SB_THUMBTRACK Позиция движка была перемещена (эти два события обрабатывают вместе)

Вот как выглядит обработка сообщений полосы:

//была передвинута горизонтальная полоса прокрутки
case WM_HSCROLL:

//сдвиг на страницу вправо
case SB_PAGERIGHT:
nxPos+=10;
break;

//сдвиг на линию вправо
case SB_LINERIGHT:
nxPos++;
break;

case SB_PAGELEFT:
nxPos-=10;
break;

//Передвинем движок на изменённую позицию
SetScrollPos(hRedScroll, SB_CTL, nxPos, TRUE);
break;

В каждой ветви этого условия должна отмечаться какая-то переменная (nxPos), и в конце обработки, мы сами устанавливаем движок на эту изменившуюся позицию. Без нашей команды движок двигаться не будет.

5. КАК связать полосу с какими-то событиями?
Ну вот мы и добрались до главного. Мы уже умеем двигать движок, если пользователь перемещает его мышкой. Но как связать с полосой какое-то событие?
Точно так же! У нас есть какая-то переменная nxPos, на неё и опираемся. Если мы выводим таблицу, то надо задать вывод от значений массива, начиная с элемента nxPos, допустим. Чтобы вывести в поле ввода значение nxPos, как мы это делаем в данной программе, достаточно использовать функцию SetDlgItemInt, которая задаёт число в элементе управления.

6. КАК узнать, какую полосу передвинул пользователь?
Ну, с главным окном всё ясно. Прокручиваем его по вертикали — WM_VSCROLL, по горизонатли — WM_HSCROLL. Всё предельно просто. Ну, а если у нас три полосы и все горизонтальные?
Тогда обрабатывая WM_HSCROLL, мы должны спросить какую полосу предвинул пользователь?
У меня в программе это делается так:

if(hRedScroll==(HWND)lParam) i=0;
if(hGreenScroll==(HWND)lParam) i=1;
if(hBlueScroll==(HWND)lParam) i=2;

Берётся какая-то абстрактная переменная i, которая хранит 0, если была передвинута первая полоса, 1 — если вторая и 2 — если третья. Идентификатор окна, сделавшего перемещение хранится в lParam. По всем сообщениям изменяется одна и та же nxPos, а после всех сообщений, вспоминаем, чему была равна i и в зависимости от этого, перемещаем соответствующую полосу на nxPos.
Мой пример встречается во многих книжках и наборах типовых программ. И часто авторы для своего удобства создают массив окон, массив полос прокруток, полей ввода и других элементов управления. Я посчитал, что в такой программе вы точно не разберётесь и написал свою. Если уж я понял, то вы и подавно разберётесь.

А вот и текст программы:

//Идентификаторы элементов управления
#define ID_EDITRED 1
#define ID_EDITGREEN 2
#define ID_EDITBLUE 3
#define ID_EXIT 4
#define ID_EDITHEX 5

BOOL RegClass(WNDPROC, LPCTSTR, UINT);
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInstance;

char szProgName[]=»ProgName»;
char sz ;

char *string=»Установка цвета»; //текст в окне
char *string1=»Ваш цвет: «;
char *string2=»16-ричный код цвета:»;

char Buf[]=»AAAAAA»; //буфер для 16-ричных значений

int i=0;
int red=128, green=128, blue=128; //значения цветов

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR IpszCmdParam, int nCmdShow)
<
hInstance=hInstance;
HWND hWnd;
MSG Msg;

if(!RegClass(WndProc, szClassName, COLOR_WINDOW))
return FALSE;

//Создание главного окна приложения
if(!(hWnd=CreateWindow(szProgName, «RGB Viewer»,
WS_OVERLAPPEDWINDOW,
100, 100, //координаты окна
530, 400,
NULL, NULL,
hInstance, NULL))) return 0;
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
while(GetMessage(&Msg, 0, 0,0))
DispatchMessage(&Msg);
return Msg.wParam;
>


BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)
<
WNDCLASS WndClass;


Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > return(Register > >


LRESULT CALLBACK WndProc(HWND hWnd, UINT Message,
WPARAM wParam, LPARAM lParam)
<
static HWND hRedScroll, hGreenScroll, hBlueScroll; //окна-прокрутки
static HWND hEditRed, hEditGreen, hEditBlue; //окна-со значениями цвета
static HWND hEditHex; //окно с 16-ричным кодом цвета
static HWND hExit; //кнопка выхода

static int nxPos, nxMin, nxMax, nyPos, nyMin, nyMax; //значения для всех полос

HDC hDC;
HBRUSH hBrush; //кисть для рисования эллипса
PAINTSTRUCT PaintStruct;
RECT Rect, Client; //области отрисовки

nxPos=128; //Среднее положение движка
nxMin=0; //Минимальное положение движка
nxMax=255; //Максимальное положение движка

//Создание трёх полос для каждого цвета
hRedScroll=CreateWindow(«scrollbar», NULL,
WS_CHILD|WS_VISIBLE|SBS_HORZ, 20, 60, 200, 25,
hWnd,(HMENU)-1, hInstance, NULL);

hGreenScroll=CreateWindow(«scrollbar», NULL,
WS_CHILD|WS_VISIBLE|SBS_HORZ, 20, 160, 200, 25,
hWnd,(HMENU)-1, hInstance, NULL);


hBlueScroll=CreateWindow(«scrollbar», NULL,
WS_CHILD|WS_VISIBLE|SBS_HORZ, 20, 260, 200, 25,
hWnd,(HMENU)-1, hInstance, NULL);

//Установка диапазона полосы прокрутки
//nxMin, nxMax — максимальные значения, TRUE — необходимость перерисовки
SetScrollRange(hRedScroll, SB_CTL, nxMin, nxMax, TRUE);
SetScrollRange(hGreenScroll, SB_CTL, nxMin, nxMax, TRUE);
SetScrollRange(hBlueScroll, SB_CTL, nxMin, nxMax, TRUE);

//Cледующая функция устанавливает ползунок в нужное положение
//nxPos — новое положение ползунка. TRUE — необходимость перерисовки
SetScrollPos(hRedScroll, SB_CTL, nxPos, TRUE);
SetScrollPos(hGreenScroll, SB_CTL, nxPos, TRUE);
SetScrollPos(hBlueScroll, SB_CTL, nxPos, TRUE);

//Создание полей ввода со значениями цветов
hEditRed=CreateWindowEx(WS_EX_STATICEDGE, «edit», «127»,
WS_CHILD|WS_VISIBLE|WS_BORDER, 240, 60, 30, 25,
hWnd,(HMENU)ID_EDITRED, hInstance, NULL);

hEditGreen=CreateWindowEx(WS_EX_STATICEDGE, «edit», «127»,
WS_CHILD|WS_VISIBLE|WS_BORDER, 240, 160, 30, 25,
hWnd,(HMENU)ID_EDITGREEN, hInstance, NULL);

hEditBlue=CreateWindowEx(WS_EX_STATICEDGE, «edit», «127»,
WS_CHILD|WS_VISIBLE|WS_BORDER, 240, 260, 30, 25,
hWnd,(HMENU)ID_EDITBLUE, hInstance, NULL);

//Поле ввода с 16-ричным кодом цвета
hEditHex=CreateWindowEx(WS_EX_CLIENTEDGE, «edit», «7F7F7F»,
WS_CHILD|WS_VISIBLE|WS_BORDER, 380, 260, 60, 25,
hWnd,(HMENU)ID_EDITHEX, hInstance, NULL);


//Кнопка выхода
hExit=CreateWindowEx(WS_EX_CLIENTEDGE, «button», «Выход»,
WS_CHILD|WS_VISIBLE|WS_BORDER|BS_DEFPUSHBUTTON, 200, 315, 100, 25,
hWnd,(HMENU)ID_EXIT, hInstance, NULL);

//Обработка сообщения прокрутки по горизонтали
case WM_HSCROLL:

//Проверяем на какой полосе было перемещение
if(hRedScroll==(HWND)lParam) i=0;
if(hGreenScroll==(HWND)lParam) i=1;
if(hBlueScroll==(HWND)lParam) i=2;

case SB_PAGERIGHT: //На страницу вправо
nxPos+=10;
Mas[i]+=10;
break;

case SB_LINERIGHT: //На одну линию вправо
nxPos+=1;
Mas[i]+=1;
break;

case SB_PAGELEFT: //На страницу влево
nxPos-=10;
Mas[i]-=10;
break;

case SB_LINELEFT: //На линию влево
nxPos-=1;
Mas[i]-=1;
break;

case SB_TOP: //Максимальное значение
nxPos=nxMax;
Mas[i]=nxMax;
break;

case SB_BOTTOM: //Минимальное значение
nxPos=nxMax;
Mas[i]=nxMax;
break;

case SB_THUMBPOSITION: //Любое перемещение
case SB_THUMBTRACK:
nxPos=HIWORD(wParam);
break;

//Если позиция больше максимальной
if(nxPos>nxMax)
<
nxPos=nxMax; //Устанавливаем на граничную максимальную
Mas[i]=nxMax;
>

//Если позиция меньше минимальной
if(nxPos

if(nxPos==nxMax)
//Если положение движка достигло максимума, блокировать его
switch(i) <
case 0: EnableScrollBar(hRedScroll, SB_CTL, ESB_DISABLE_RIGHT); break;
case 1: EnableScrollBar(hRedScroll, SB_CTL, ESB_DISABLE_RIGHT); break;
case 2: EnableScrollBar(hRedScroll, SB_CTL, ESB_DISABLE_RIGHT); break;
>

//Вспоминаем, какая полоса была сдвинута
switch(i) <
case 0:
//Перемещаем движок
SetScrollPos(hRedScroll, SB_CTL, nxPos, TRUE);
//Выводим в поле ввода новое значение
SetDlgItemInt(hWnd, ID_EDITRED, nxPos,0);
break;

case 1:
SetScrollPos(hGreenScroll, SB_CTL, nxPos, TRUE);
SetDlgItemInt(hWnd, ID_EDITGREEN,nxPos,0);
break;

case 2:
SetScrollPos(hBlueScroll, SB_CTL, nxPos, TRUE);
SetDlgItemInt(hWnd, ID_EDITBLUE,nxPos,0);
break;
>

//Новые значения переменных цвета получены из полей ввода
red=GetDlgItemInt(hWnd, ID_EDITRED, NULL, 0);
green=GetDlgItemInt(hWnd, ID_EDITGREEN, NULL, 0);
blue=GetDlgItemInt(hWnd, ID_EDITBLUE, NULL, 0);

//Задаём границы области перерисовки по эллипсу
Client.left=330;
Client.top=60;
Client.right=480;
Client.bottom=220;

//Вызываем сообщение WM_PAINT по перерисовке области
//эллипса

InvalidateRect(hWnd, &Client, 1);
//Записываем в буфер 16-ричные эквиваленты цветов
sprintf(Buf, «%X%X%X», red, green ,blue);
//Выводим буфер в поле 16-ричного вывода
SetDlgItemText(hWnd, ID_EDITHEX,Buf);

//Сообщшение рисования
case WM_PAINT:
hDC = BeginPaint(hWnd, &PaintStruct);
GetClientRect(hWnd, &Rect);
//Прозрачный режим фона
SetBkMode(hDC, TRANSPARENT);
//Белый прямоугольник под эллипсом
Rectangle(hDC, 330, 60, 480, 220);
//Создаём кисть с новыми цветами
hBrush=CreateSolidBrush(RGB(red, green, blue));
//Делаем её активной
SelectObject(hDC, hBrush);
//Рисуем эллипс
Ellipse(hDC, 350,80,460,200);

//Выводим текст в окно
TextOut(hDC, 60,20,string, strlen(string));
TextOut(hDC, 370,20,string1, strlen(string1));
TextOut(hDC, 325, 234, string2, strlen(string2));

//Выводим текст над полями ввода разного цвета
SetTextColor(hDC, RGB(255,0,0));
TextOut(hDC, 240,42,»Red:»,4);
SetTextColor(hDC, RGB(0,255,0));
TextOut(hDC, 234,140,»Green:», 6);
SetTextColor(hDC, RGB(0,0,255));
TextOut(hDC, 240,240,»Blue:», 5);


EndPaint(hWnd, &PaintStruct);

case WM_COMMAND:
switch(LOWORD(wParam))<

//Завершение работы по кнопке «Выход»
case ID_EXIT:
DestroyWindow(hWnd);
return 0;
break;


case WM_DESTROY:
DeleteObject(hBrush);
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd,Message, wParam, lParam);

Заключение. Мы вроде бы всё так подробно обсудили до, что после как бы и говорить-то не о чем. Однако, есть некоторые моменты, которые здесь встречаются впервые.

Здесь я специально часть переменных, которые будут выведены TextOut объявил в начале, в виде переменных типа char*, это позволяет менять текст переменной, не меняя функции TextOut и соответственно длины строки. Она будет вычисляться автомтически.

Также ещё раз вспоминим, что для перерисовки главного окна, то есть принудительного вызова WM_PAINT, можно применять InvalidateRect. Существенным может показаться и то, что во избежания мерцания при каждом перемещении движка (особенно это заметно, когда движок ведёшь), я перерисовываю только область эллипса. Для этого я специально создал экземпляр структуры RECT под названием Client. Заполнив его поля параметрами эллипса, я, тем самым, задал лишь небольшой квадратик, который стоит перерисовывать. Всё же окно остаётся неизменным.

И самое интересное — вывод 16-ричного кода. Здесь я применил старый верный трюк языка Си, функцию sprintf. Вобще-то в Windows ей не место, это вам любой скажет, но здесь она уж очень хорошо смотрится. Да и как без неё — разве что применять алгоритм преобразования десятичных чисел в 16-ричные. В библиотеке классов MFC есть класс CString, который позволяет представить строку не как набор сиволов, а вроде бы даже, как самостоятельный тип данных. Спасибо ему за это!

Пример 2 «Таблица значений».

В следующем примере я научу вас создавать таблицы со значениями, которые даже можно прокручивать. Во многих книгах есть примеры вывода таблицы в главное окно и его прокрутка. Но, как мы с вами уже говорили, клиентскую область окна надо беречь и стараться оберегать для более важных вещей, чем временная информация. Кроме того, стоит вам прокрутить вниз такую таблицу хотя бы на одну высоту экрана, как заголовки столбцов «уползут» вверх и вы перестанете понимать, что это за цифры. А это недопустимо.

Поэтому сейчас я научу вас делать такую таблицу, которую никто больше не научит. Вывод таблицы в диалоговое окно! А? Каково! В этой программе я намеренно ввёл много элементов украшения, чтобы вы видели не только учебные программы, а реально работающие законченные окна. С такими программами работать приятнее, пусть даже мы на них только учимся.

Итак, о чём пойдёт речь? В этой таблице будет некоторая полезная информация — значения чисел от 0 до 255, эти же значения в квадрате, двойка в степени этого числа, 1 делённая на это число и экспоненциальная функция этого числа. Каждому значению будет отведён свой столбец в таблице. Итак, столбцов пять, строк 255. Представляем себе массив 255Х5. Поскольку числа будут дробные, тип данных будет double, но не float, поскольку для функции exp() нужны данные типа double. Кроме того, длины типа float может просто не хватить. К концу списка значения будут огромные!
Итак, подключаем в начале программы библиотеку math.h, объявляем массв:

Теперь надо спроектировать диалоговое окно, нарисовав его в редакторе ресурсов. Добавляем к программе новое окно и оформляем его следующим образом:

В свойствах диалогового окна, меняем заголовок на «Таблица», а идентификатор на IDD_TABLE. Кнопка так и будет IDOK. Перетащим в окно вертикальную полосу прокрутки, которую назовём IDC_SCROLL. В отличие от прошлого примера, полоса будет вертикальная и создана не динамически, а в виде ресурса.
Создадим под полосой прокрутки статический текст по имени IDC_STATIC. В его свойствах поставьте флажки на Border во вкладке Styles и Static Edge, и флажки: Modal Frame во вкладке Extended Styles.

Вот описание этого окна из файла ресурсов:

IDD_TABLE DIALOGEX 0, 0, 342, 201
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION «Таблица»
FONT 8, «MS Sans Serif»
BEGIN
DEFPUSHBUTTON «OK»,IDOK,145,180,50,14
SCROLLBAR IDC_SCROLL,310,10,20,155,SBS_VERT //полоса прокрутки и её координаты
LTEXT «1»,IDC_STATIC,310,170,20,15,WS_BORDER,
WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE
END

Создадим для этого окна функцию окна TableProc(), объявив её в начале программы:

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

Сделаем вызов нашего диалогового окна из меню. Для этого в главное меню добавим пункт IDM_TABLE, который будет называться «Таблица».

case IDM_TABLE:
DialogBox(hInst, (LPCTSTR)IDD_TABLE, hWnd, (DLGPROC)TableProc);
break;

Мы создали массив Mas. Теперь надо заполнить его числами. Лучше всего это сделать по сообщению WM_INITDIALOG в функции TableProc. На этом этапе инициализируются все переменные, с которыми будет работать диалоговое окно IDD_TABLE.

int i,j;
.
case WM_INITDIALOG:
for(i=0; i

При желании всегда будет можно заменить exp(i) на sqrt(i), если вам нужна не экспонента, а корень. В данном случае можно использовать те функции math.h, которые вам больше нужны.


К моменту вывода на экран диалогового окна, массив уже будет заполнен значениями.

Теперь, чтобы программа получилась красивой, займёмся графикой. Я включил в программу целый ряд кистей — синюю для фона, жёлтую для таблицы и чёрную для тени.

hBlue=CreateSolidBrush(RGB(0,130,255));
hYellow=CreateSolidBrush(RGB(255,255,170));
hBlack=CreateSolidBrush(RGB(0,0,0));

Нарисуем синий прямоугольник во весь фон, жёлтый — там, где будет таблица, а чёрный — её тень.

//Заливаем фон синим
SelectObject(hDC, hBlue);
Rectangle(hDC, 0,0, 640,480);

//Делаем тень таблицы
SelectObject(hDC, hBlack);
Rectangle(hDC, 20,20,420,270);

//Заливаем пространство таблицы жёлтым
SelectObject(hDC, hYellow);
Rectangle(hDC, 10,10,400,250);

Чтобы у таблицы были чёткие границы, я создал перо, толщиной 3 линии.
hPen=CreatePen(0,3,RGB(0,0,0));
SelectObject(hDC, hPen);

Место, где будет «шапка» таблицы отгорожено линией.
MoveToEx(hDC, 10,50, NULL);
LineTo(hDC, 400,50);

Выведем в неё названия заголовков. Чтобы не было белого фона под текстом, зададим режим отображения прозрачным.

//Фон прозрачный
SetBkMode(hDC, TRANSPARENT);

//Меняем цвет текста
SetTextColor(hDC, RGB(136,65,55));

//Выводим заголовки столбцов
TextOut(hDC, 26,20,»Num», 3);
TextOut(hDC, 100,20,»Num^2″, 5);
TextOut(hDC, 180,20,»2^Num», 5);
TextOut(hDC, 255,20,»1/Num», 5);
TextOut(hDC, 330,20,»Num», 3);

Теперь окно готово. Остаётся только выводить в него строки таблицы Mas в зависимости от положения полосы прокрутки. Что-то мы забыли сделать. Ах да, обработать сообщения от самой полосы! Без этого ничего в этом красивом окне не будет.
Так как на этот раз мы работаем с вертикальной полосой, то сообщение будет WM_VSCROLL.
Переменная, которую мы будем менять, будет называться yPos. Её значение будет постоянно выводиться в статическом окне IDC_STATIC, а также в зависимости от него, будут выводиться значения массива.

j=50;
for(i=yPos; i MAX) yPos=MAX;
//Установить движок на выбранную позицию
SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);
//Вывести текст в статический элемент
SetDlgItemInt(hDlg, IDC_STATIC, yPos, 0);
//Перерисовка
InvalidateRect(hDlg, &Client, 1);
InvalidateRect(hDlg, &Client1, 1);
break;

//На линию вверх
case SB_LINEUP:
yPos—;
//Если положение движка меньше 0, установить на 0
if(yPos

//На страницу вверх
case SB_PAGEUP:
yPos-=10;
if(yPos

//На страницу вниз
case SB_PAGEDOWN:
//Перемещаемся на 10 позиций
yPos+=10;
if(yPos>MAX) yPos=MAX;
SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);
SetDlgItemInt(hDlg, IDC_STATIC, yPos, 0);
InvalidateRect(hDlg, &Client, 1);
InvalidateRect(hDlg, &Client1, 1);

//Сообщение при перетаскивании
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
yPos=HIWORD(wParam); //получаем текущую позицию прокрутки
SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);
SetDlgItemInt(hDlg, IDC_STATIC, yPos, 0);
InvalidateRect(hDlg, &Client, 1);
InvalidateRect(hDlg, &Client1, 1);

Здесь есть несколько хитростей, в которые я вас посвящу.
Во-первых, посольку мы не создавали эту полосу динамически, идентификатора окна типа HWND у неё нет. Однако, для SetScrollPos он нужен. Как быть? Мы знаем, что идентификатор окна можно получить при обработке сообщения, как старшее слово lParam. Так мы и сделаем:

SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);

Даже если бы у нас было несколько вертикальных полос прокрутки, окно бы «поняло» от которой исходит сообщение в данный момент. Состояние движка, а значит переменной yPos мы выводим функцией SetDlgItemInt. И всё работает. Остаётся только маленькое но. Перерисовка. Как только мы начнём нажимать на прокрутку, всё окно перерисуется и мы вообще потеряем таблицу. Чтобы этого не случилось, мы можем перерисовывать только прокрутку со статическим окном, да кнопку «Ok». Но посольку они в разных частях окна, придётся перерисовывать сразу две области — прокрутки и кнопки.
Создадим два экземпляра структуры Rect и заполним их соответствующими координатами:

RECT Client, Client1;

Client.left=464; //прокрутка
Client.top=16;
Client.right=496;
Client.bottom=300;

Client1.left=219; //кнопка
Client1.top=293;
Client1.right=293;
Client1.bottom=316;

При прокрутке окна, придётся два раза вызывать функцию InvalidateRect для разных областей.

case SB_LINEDOWN:
yPos++;
if(yPos>MAX) yPos=MAX;
SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);
SetDlgItemInt(hDlg, IDC_STATIC, yPos, 0);

InvalidateRect(hDlg, &Client, 1); //Здесь перерисовка запускается сразу для двух
InvalidateRect(hDlg, &Client1, 1); //областей. Так придётся делать каждый раз

Напоследок, скажу, что такие таблицы, какую мы создали считаются непрофессиональными. С таким же успехом мы могли создавать её и в DOS. Дело здесь в другом — в том, что на примере этой таблицы мы смогли рассмотреть наиболее полно полосу прокрутки. В следующей главе, мы закрепим наши знания, рассмотрев производные от полосы прокрутки — спин — прокрутку без полосы и ползунок, которым вы привыкли регулировать громкость.

Задание.

Сделайте, пожалуйста, чтобы после каждой строки, выведенной в окно, проводилась бы горизонтальная линия для удобства чтения. Таким образом таблица будет разбита на строки. Линия эта должна быть чёрного цвета.

MFC — Scrollbars

A scrollbar is a graphical control element with which continuous text, pictures or anything else can be scrolled in two directions along a control by clicking an arrow. This control can assume one of two directions — horizontal or vertical. It is represented by CScrollBar class.

Here is the list of methods in CScrollBar class −

Enables or disables one or both arrows of a scroll bar.

Enables or disables one or both arrows of a scroll bar.

Retrieves information about the scroll bar using a SCROLLBARINFO structure.

Retrieves information about the scroll bar.

Retrieves the limit of the scroll bar.

Retrieves the current position of a scroll box.

Retrieves the current minimum and maximum scroll-bar positions for the given scroll bar.

Sets information about the scroll bar.

Sets the current position of a scroll box.

Sets minimum and maximum position values for the given scroll bar.

Shows or hides a scroll bar.

Let us look into a simple example of Scrollbar.

Step 1 − To add either horizontal or vertical scrollbar, you need to set the following highlighted properties of the dialog box to True.

Step 2 − When you run the above application, you will see that both horizontal and vertical scrollbars have been added.

Стилизация пользовательского скроллбара с помощью CSS и Jquery

Наверняка вы видели сайты с оригинальными полосами прокрутки. Это достигается с помощью нового CSS scroll свойства webKit-scrollbar . К сожалению, оно работает только в браузерах на движке WebKit . Но поддерживается jQuery почти во всех обозревателях. Давайте выполним стилизацию скроллбара.

Данное свойство поддерживается версиями Google Chrome для настольных компьютеров и мобильных устройств, Apple Safari , Flock , OmniWeb . Даже если вы создаете дизайн только для этих браузеров без использования jQuery , то сможете охватить только 72% пользователей интернета. Но если у вас нет аллергии на программирование, то можете быть уверены, что каждый ваш посетитель увидит красиво стилизованный скроллбар.

Стилизация скроллбара

Полосы прокрутки реализованы там, где длина контента превышает ширину окна контейнера. Благодаря этому вы получаете возможность стилизовать iframe , элементы div и поле ввода текста. В iframe и текстовой области окна браузеры автоматически добавляют полосу прокрутки в нижней части, когда содержимое выходит за пределы видимой области. Тем не менее, в контейнерах необходимо предоставлять дополнительную информацию для браузеров. Установка свойству overflow значения scroll говорит браузерам о том, что нужно выводить полосы прокрутки в случае переполнения окна контентом:

Это код scrolling CSS покажет полосу прокрутки такой (справа)

Использование псевдоэлементов CSS для настройки скроллбара

IE5.5 был первым браузером, поддерживающим основные стили для скроллинга. Используя свойство scrollbar-face-color , можно были изменить цвет полос прокрутки. Хотя это и не добавляло большого разнообразия, но все же лучше, чем стандартная полоса прокрутки в браузере. Поскольку это свойство по-прежнему поддерживается в Internet Explorer , его можно использовать для пользователей, предпочитающих этот браузер.

Для WebKit-браузерах в CSS существует множество вариантов стилизации: изменение цвета и ширины полосы прокрутки, ползунков. Элементы скроллинга можно выбрать с помощью следующих псевдоэлементов.

  1. ::webkit-scrollbar — позволяет настроить ширину и цвет полосы прокрутки. Когда этот псевдоэлемент указан, WebKit выключает свой встроенный рендеринг скроллбара и использует настройки, указанные для div scroll CSS . Обратите внимание, что при этом будут выбраны все полосы прокрутки, присутствующие на странице. Если нужно настроить скроллбар для определенного элемента, необходимо применить это свойство к конкретному элементу:
  1. ::-webkit-scrollbar-thumb – Это ползунок скроллбара ( чем вы держите и прокручиваете страницу ). Он может иметь цвет или использовать градиент в качестве фона. Пример реализации:
  1. ::-webkit-scrollbar-track – позволяет настроить трек скроллбара ( путь движения ползунка ). Синтаксис псевдоэлемента для CSS scroll :


  1. ::-webkit-scrollbar-button – разработчики CSS3 не упускают из виду маленькие кнопки на концах полосы прокрутки. Их также можно настроить, так как они помогают, когда страница длинная и скроллбар становится слишком маленьким для прокрутки. Это свойство стиля верхнего и нижнего углов ( или левого и правого для горизонтальных полос прокрутки ):
  1. ::-webkit-scrollbar-corner – позволяет справиться с ситуацией, когда появляются обе полосы прокрутки и пересекаются в углу:

Вот несколько примеров, которые демонстрируют силу свойства scrolling CSS .

Настройка скроллбара с помощью Jquery

Если вам нравится программирование front-end , вы можете использовать Jquery-плагин JScrollPane . Он довольно прост в использовании. После того, как вы загрузили и подключили соответствующие файлы в заголовке документа, нужно вызвать одну Javascript-функцию для инициализации панели прокрутки. Вы можете легко изменить дизайн полосы прокрутки с помощью CSS или выбрать одну из существующих тем.

С помощью этого плагина вы можете создавать скроллинг для всех типов браузеров. Так что я бы посоветовал вам воспользоваться им, чтобы сэкономить время и охватить сразу все браузеры:

Если вы захотите изменить настройки CSS scroll по умолчанию, предоставленные JScrollPane , нужно редактировать стили соответствующих элементов:

Вывод

Пользовательские скроллбары больше не являются редкостью. Вы найдете их на большинстве сайтов и блогов. А с JScrollPane стало гораздо проще создавать и отображать стилизованные полосы прокрутки во всех браузерах. Надеюсь, этот урок оказался для вас полезным.

Данная публикация представляет собой перевод статьи « Scrollbar styling using CSS and Jquery » , подготовленной дружной командой проекта Интернет-технологии.ру

изменить заголовок bar цвет приложения mfc

Я хочу изменить цвет заголовка моего приложения mfc. Я использовал метод OnNcPaint(). Но изменения выполняются на клиентской области, а не в строке заголовка.

Создан 11 авг. 17 2020-08-11 09:27:09 ms123

1 ответ

Без сомнения, вы могли бы это сделать, но это почти наверняка действительно плохая идея, чтобы сделать это.

Пользовательский интерфейс работает хорошо, когда он предсказуем и последователен! Изменения, которые вы пытаетесь сделать, не являются предсказуемыми и несовместимыми.

Как вы будете иметь дело с различными версиями ОС, тематическими/неповрежденными, будущими версиями ОС, которые могут быть совершенно разными в том, как они создают неклиентские регионы?

С помощью Google вы найдете способы сделать это как here

Создан 11 авг. 17 2020-08-11 10:26:46 xMRi

Меняем цвет scroll bar в приложении mfc

������� Microsoft Forms 2.0 scrollbar ����� �������� BackColor read/write

� ��������� �������� ����. ������ — 0Kb

Sr.No. Name & Description
1
8 ��� 06, 11:50����[2857817] �������� | ���������� �������� ����������
Re: ��� �������� ���� ���������� [new]
ILL HEAD
������� ����� �� ��� �����
� ��� ������ ������/��������

������� Microsoft Forms 2.0 scrollbar ����� �������� BackColor read/write


������� ������� ILL HEAD!

���������� 8 ��� 06, 12:07����[2857837] �������� | ���������� �������� ����������

Re: ��� �������� ���� ���������� [new]
����������-����������
1.�� ����� �� �� �������� ��� ���-������� ���������� ���������?
2. � ��� ����� ������� ������� ������������ ���������� �� ������� Microsoft Forms 2.0 scrollbar ?
1. � ����� ��� ��� ��� ������� ? � ������������ ����� ������� ���������� ����� ���������
2. ������� ��� ������� ��� — �� ����� �������� — ��� �������
������� ����� �� ������� ��� ��������� — ���� ��� ���������������
� ����� �� ����� �� ������� � ����� ��������� ����
(����� ��� ������������ . + ���� ����������� � ������ ����� � ������ ������) 8 ��� 06, 12:14����[2857841] �������� | ���������� �������� ����������
Re: ��� �������� ���� ���������� [new]
ILL HEAD
����������-����������
1.�� ����� �� �� �������� ��� ���-������� ���������� ���������?
2. � ��� ����� ������� ������� ������������ ���������� �� ������� Microsoft Forms 2.0 scrollbar ?
1. � ����� ��� ��� ��� ������� ? � ������������ ����� ������� ���������� ����� ���������
2. ������� ��� ������� ��� — �� ����� �������� — ��� �������
������� ����� �� ������� ��� ��������� — ���� ��� ���������������
� ����� �� ����� �� ������� � ����� ��������� ����
(����� ��� ������������ . + ���� ����������� � ������ ����� � ������ ������)

2. ��, ��������, ��� ���� ����� ��� ������� ������� ������ ��������������� ������� Microsoft Forms 2.0 scrollbar. -) 8 ��� 06, 12:24����[2857853] �������� | ���������� �������� ����������

Re: ��� �������� ���� ���������� [new]
api ShowScrollbar
The ShowScrollBar function shows or hides the specified scroll bar.

Declare Function ShowScrollBar Lib «user32» (ByVal hwnd As Long, ByVal wBar As Long, ByVal bShow As Long) As Long

� hWnd
[in] Handle to a scroll bar control or a window with a standard scroll bar, depending on the value of the wBar parameter.

� wBar
[in] Specifies the scroll bar(s) to be shown or hidden. This parameter can be one of the following values. Value Meaning
SB_BOTH
Shows or hides a window’s standard horizontal and vertical scroll bars.
SB_CTL
Shows or hides a scroll bar control. The hWnd parameter must be the handle to the scroll bar control.
SB_HORZ
Shows or hides a window’s standard horizontal scroll bars.
SB_VERT
Shows or hides a window’s standard vertical scroll bar.

One more step

Please complete the security check to access codepen.io

Why do I have to complete a CAPTCHA?

Completing the CAPTCHA proves you are a human and gives you temporary access to the web property.

What can I do to prevent this in the future?

If you are on a personal connection, like at home, you can run an anti-virus scan on your device to make sure it is not infected with malware.

If you are at an office or shared network, you can ask the network administrator to run a scan across the network looking for misconfigured or infected devices.

Another way to prevent getting this page in the future is to use Privacy Pass. You may need to download version 2.0 now from the Chrome Web Store.

Cloudflare Ray ID: 534a3d699dc38f61 • Your IP : 188.64.174.135 • Performance & security by Cloudflare

изменить заголовок bar цвет приложения mfc

Я хочу изменить цвет заголовка моего приложения mfc. Я использовал метод OnNcPaint(). Но изменения выполняются на клиентской области, а не в строке заголовка.

Создан 11 авг. 17 2020-08-11 09:27:09 ms123

1 ответ

Без сомнения, вы могли бы это сделать, но это почти наверняка действительно плохая идея, чтобы сделать это.

Пользовательский интерфейс работает хорошо, когда он предсказуем и последователен! Изменения, которые вы пытаетесь сделать, не являются предсказуемыми и несовместимыми.

Как вы будете иметь дело с различными версиями ОС, тематическими/неповрежденными, будущими версиями ОС, которые могут быть совершенно разными в том, как они создают неклиентские регионы?

С помощью Google вы найдете способы сделать это как here

Создан 11 авг. 17 2020-08-11 10:26:46 xMRi


КАК сделать текст на экране прокручиваемым?

До сих пор мы как-то обходили эту тему. Вроде бы выводим графику, текст в рабочую область окна и всё гладко. Но так только до поры до времени. Представьте, что вы решили создать программу управляющую работой парового котла. Термодатчик каждую секунду снимает данные с термопары и отправляет на порт вашего компьютера. Программа считывает данные с порта и. Что с ними делать дальше? Можно, конечно, записывать их в файл, дописывая в конец всё новые данные показания. Так обычно и делается. А считывать их оттуда кто будет? Если пользователь должен будет открывать потом этот файл через «Блокнот» или «Wordpad», он будет долго ругаться. Гораздо лучше сделать всё в одной программе. На экране будет длинная таблица со значениями, прокрутив которую, вы сможете просмотреть всю историю. Да что там все эти специализированные программы. Все текстовые редакторы от Блокнота до Word имеют полосу прокрутки. Вы пользуетесь ими каждый день, совсем этого не замечая.

Для того, чтобы экран можно было прокручивать, надо добавить к окну полосу прокрутки или Scroll Bar. Не важно, будете вы выводить текст в главное окно или в диалоговое. Полосу прокрутки можно приделать даже к кнопке!

Разбёрём полосу прокрутки главного окна. Важно понимать, что когда пользователь перемещается по полосе вниз, его текст тем временем ползёт вверх. Кроме того, стрелки полосы прокрутки можно перемещать кнопками мыши, а можно стрелками клавиатуры и клавишами Page Up и Page Down. Можно ещё нажать левую кнопку мыши сверху или снизу движка, и он проскочит сразу несколько линий.

Все эти сообщения полосы Scroll Bar мы научимся обрабатывать сами. Вы сами сможете задавать переместиться тексту по нажатию кнопки PageDown до конца или на три строчки. Диапазон полосы полосы прокрутки и положение её движка тоже можно изменить в любой момент времени.

Полосы прокрутки бывают вертикальными и горизонтальными. В зависимости от типа, полоса посылает сообщения: WM_HSCROLL (горизонтальная) и WM_VSCROLL (вертикальная).

Как не странно, почему-то у всех пользователей полоса прокрутки вызывает дрожь в коленях и зубную боль. Не скрою, и я долго обходил эту тему, а потом долго нед ней бился. Поэтому в этой главе будет целых три примера. Они помогут разобраться с полосой

Начнём с очень полезной программы, которая, возможно будет вам ещё долго хорошим другом. И это не метафора. В любом языке программирования: C++, Java и др, где работают с палитрой 256 цветов, цвет получают сложением красного, зелёного и синего. Так называемая модель RGB. Занимаясь WEB-дизайном и задавая цвет гиперссылок, текста и фона, вы тоже сталкиваетесь с этой моделью, только цвет кодируется его 16-ричным эквивалентом. Так белый цвет RGB(0,0,0) будет в 16-ричной системе FFFFFF. А синий RGB(57,0,255) будет представлен как 390FF. Часто, чтобы подобрать нужный цвет в тех же программах на API или в WEB-дизайне вы долго подбирали цифры, чтобы получить более приятный оттенок. Вам никогда не хотелось этот процесс подбора автоматизировать?
Мне да, поэтому я написал следующую программу. Она сложна тем, что в ней всего много (как и подобает нормально работающей программе, которая приносит пользу). Но мы постараемся во всём разобраться.
Выглядеть это будет так:

Как видите, три полосы прокрутки, которые меняют значения трёх цветов. Эти значения моментально выводятся в три поля ввода. Кроме того, в правой части окна размещён цветной эллипс на белом фоне. Он будет менять свой цвет в зависимости от выбранных вами значений красного, синего и зелёного. Но и это ещё не всё. Под эллипсом размешёно окошечко, в котором будут меняться значения цвета в 16-ричном коде, откуда их всегда можно скопировать и вставить в исходник HTML-документа.

Но прежде, чем знакомиться с такой сложной программой, давайте познакомимся с полосой прокрутки. Что с ней можно делать?

1. Создание полосы прокрутки.
Поскольку это обычный элемент управления, создаётся Scroll Bar точно также, функцией CreateWindow. Вот пример создания одной горизонтальной полосы из этого примера:

hGreenScroll=CreateWindow(«scrollbar», NULL,
WS_CHILD|WS_VISIBLE|SBS_HORZ, 20, 160, 200, 25,
hWnd,(HMENU)-1, hInstance, NULL);

Тип элемента «scrollbar», расположение указывается в стиле SBS_HORZ или SBS_VERT. Дальше идут координаты левого верхнего угла, ширина и длина.

2. Задание диапазона Scroll Bar. Для этого существует специальная API функция SetScrollRange. Зачем надо задавать диапазон. Не лучше ли увеличивать значения, пока пользователю не надоест?
Совершенно очевидно, что для тех же цветов, их значения не могут принимать значения больше 255 и меньше 0. Если мы управляем сложным процессом, дорогое оборудование может выйти из строя или «зависнуть», если мы зададим скажем номер порта, который не существует или отрицательным.
Итак, вот как задаётся диапазон:

SetScrollRange(hRedScroll, SB_CTL, nxMin, nxMax, TRUE);
Здесь hRedScroll — идентификатор окна, созданного CreateWindow, SB_CTL — дескриптор полосы прокрутки, если она используется, как элемент управления; nxMin и nxMax — минимальное и максимальное значения для данной полосы. Последнее значение — булевское. Будет ли происходить перерисовка при установке нового диапазона.

3. Установка положения движка. После создания полос прокрутки и задания их диапазона, мы хотим установить движки на них в центральное положение. Для этого надо задать команду движку: «Встань в положение 127». Эти слова произносит API-функция SetScrollPos. Вот как это она делает:

SetScrollPos(hRedScroll, SB_CTL, nxPos, TRUE);

hRedScroll — это то окну, которому мы это говорим, SB_CTL — дескриптор полосы, nxPos — числовое значение, в данном случае, 127. Значение последнего аргумента — то же, что и в предыдущей функции.

4. Обработка сообщений
В зависимости от действий пользователя, полоса прокрутки передаёт следующие сообщения:

Сообщение Действие
SB_LINEUP Полоса передвинута на линию вверх (вертикальная)
SB_LINEDOWN Полоса передвинута на линию вниз
SB_LINELEFT Сдвиг на линию влево
SB_LINERIGHT Сдвиг на линию вправо
SB_PAGEUP Сдвиг на страницу вверх
SB_PAGEDOWN Сдвиг на страницу вниз
SB_PAGELEFT Сдвиг на влево
SB_PAGERIGHT Сдвиг на вправо
SB_THUMBPOSITION Позиция движка была изменена
SB_THUMBTRACK Позиция движка была перемещена (эти два события обрабатывают вместе)

Вот как выглядит обработка сообщений полосы:

//была передвинута горизонтальная полоса прокрутки
case WM_HSCROLL:

//сдвиг на страницу вправо
case SB_PAGERIGHT:
nxPos+=10;
break;

//сдвиг на линию вправо
case SB_LINERIGHT:
nxPos++;
break;

case SB_PAGELEFT:
nxPos-=10;
break;

//Передвинем движок на изменённую позицию
SetScrollPos(hRedScroll, SB_CTL, nxPos, TRUE);
break;

В каждой ветви этого условия должна отмечаться какая-то переменная (nxPos), и в конце обработки, мы сами устанавливаем движок на эту изменившуюся позицию. Без нашей команды движок двигаться не будет.

5. КАК связать полосу с какими-то событиями?
Ну вот мы и добрались до главного. Мы уже умеем двигать движок, если пользователь перемещает его мышкой. Но как связать с полосой какое-то событие?
Точно так же! У нас есть какая-то переменная nxPos, на неё и опираемся. Если мы выводим таблицу, то надо задать вывод от значений массива, начиная с элемента nxPos, допустим. Чтобы вывести в поле ввода значение nxPos, как мы это делаем в данной программе, достаточно использовать функцию SetDlgItemInt, которая задаёт число в элементе управления.

6. КАК узнать, какую полосу передвинул пользователь?
Ну, с главным окном всё ясно. Прокручиваем его по вертикали — WM_VSCROLL, по горизонатли — WM_HSCROLL. Всё предельно просто. Ну, а если у нас три полосы и все горизонтальные?
Тогда обрабатывая WM_HSCROLL, мы должны спросить какую полосу предвинул пользователь?
У меня в программе это делается так:

if(hRedScroll==(HWND)lParam) i=0;
if(hGreenScroll==(HWND)lParam) i=1;
if(hBlueScroll==(HWND)lParam) i=2;

Берётся какая-то абстрактная переменная i, которая хранит 0, если была передвинута первая полоса, 1 — если вторая и 2 — если третья. Идентификатор окна, сделавшего перемещение хранится в lParam. По всем сообщениям изменяется одна и та же nxPos, а после всех сообщений, вспоминаем, чему была равна i и в зависимости от этого, перемещаем соответствующую полосу на nxPos.
Мой пример встречается во многих книжках и наборах типовых программ. И часто авторы для своего удобства создают массив окон, массив полос прокруток, полей ввода и других элементов управления. Я посчитал, что в такой программе вы точно не разберётесь и написал свою. Если уж я понял, то вы и подавно разберётесь.

А вот и текст программы:

//Идентификаторы элементов управления
#define ID_EDITRED 1
#define ID_EDITGREEN 2
#define ID_EDITBLUE 3
#define ID_EXIT 4
#define ID_EDITHEX 5

BOOL RegClass(WNDPROC, LPCTSTR, UINT);
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInstance;

char szProgName[]=»ProgName»;
char sz ;

char *string=»Установка цвета»; //текст в окне
char *string1=»Ваш цвет: «;
char *string2=»16-ричный код цвета:»;

char Buf[]=»AAAAAA»; //буфер для 16-ричных значений

int i=0;
int red=128, green=128, blue=128; //значения цветов

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR IpszCmdParam, int nCmdShow)
<
hInstance=hInstance;
HWND hWnd;
MSG Msg;

if(!RegClass(WndProc, szClassName, COLOR_WINDOW))
return FALSE;

//Создание главного окна приложения
if(!(hWnd=CreateWindow(szProgName, «RGB Viewer»,
WS_OVERLAPPEDWINDOW,
100, 100, //координаты окна
530, 400,
NULL, NULL,
hInstance, NULL))) return 0;
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
while(GetMessage(&Msg, 0, 0,0))
DispatchMessage(&Msg);
return Msg.wParam;
>


BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)
<
WNDCLASS WndClass;

Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > Wnd > return(Register > >


LRESULT CALLBACK WndProc(HWND hWnd, UINT Message,
WPARAM wParam, LPARAM lParam)
<
static HWND hRedScroll, hGreenScroll, hBlueScroll; //окна-прокрутки
static HWND hEditRed, hEditGreen, hEditBlue; //окна-со значениями цвета
static HWND hEditHex; //окно с 16-ричным кодом цвета
static HWND hExit; //кнопка выхода

static int nxPos, nxMin, nxMax, nyPos, nyMin, nyMax; //значения для всех полос

HDC hDC;
HBRUSH hBrush; //кисть для рисования эллипса
PAINTSTRUCT PaintStruct;
RECT Rect, Client; //области отрисовки

nxPos=128; //Среднее положение движка
nxMin=0; //Минимальное положение движка
nxMax=255; //Максимальное положение движка

//Создание трёх полос для каждого цвета
hRedScroll=CreateWindow(«scrollbar», NULL,
WS_CHILD|WS_VISIBLE|SBS_HORZ, 20, 60, 200, 25,
hWnd,(HMENU)-1, hInstance, NULL);

hGreenScroll=CreateWindow(«scrollbar», NULL,
WS_CHILD|WS_VISIBLE|SBS_HORZ, 20, 160, 200, 25,
hWnd,(HMENU)-1, hInstance, NULL);


hBlueScroll=CreateWindow(«scrollbar», NULL,
WS_CHILD|WS_VISIBLE|SBS_HORZ, 20, 260, 200, 25,
hWnd,(HMENU)-1, hInstance, NULL);

//Установка диапазона полосы прокрутки
//nxMin, nxMax — максимальные значения, TRUE — необходимость перерисовки
SetScrollRange(hRedScroll, SB_CTL, nxMin, nxMax, TRUE);
SetScrollRange(hGreenScroll, SB_CTL, nxMin, nxMax, TRUE);
SetScrollRange(hBlueScroll, SB_CTL, nxMin, nxMax, TRUE);

//Cледующая функция устанавливает ползунок в нужное положение
//nxPos — новое положение ползунка. TRUE — необходимость перерисовки
SetScrollPos(hRedScroll, SB_CTL, nxPos, TRUE);
SetScrollPos(hGreenScroll, SB_CTL, nxPos, TRUE);
SetScrollPos(hBlueScroll, SB_CTL, nxPos, TRUE);

//Создание полей ввода со значениями цветов
hEditRed=CreateWindowEx(WS_EX_STATICEDGE, «edit», «127»,
WS_CHILD|WS_VISIBLE|WS_BORDER, 240, 60, 30, 25,
hWnd,(HMENU)ID_EDITRED, hInstance, NULL);

hEditGreen=CreateWindowEx(WS_EX_STATICEDGE, «edit», «127»,
WS_CHILD|WS_VISIBLE|WS_BORDER, 240, 160, 30, 25,
hWnd,(HMENU)ID_EDITGREEN, hInstance, NULL);

hEditBlue=CreateWindowEx(WS_EX_STATICEDGE, «edit», «127»,
WS_CHILD|WS_VISIBLE|WS_BORDER, 240, 260, 30, 25,
hWnd,(HMENU)ID_EDITBLUE, hInstance, NULL);

//Поле ввода с 16-ричным кодом цвета
hEditHex=CreateWindowEx(WS_EX_CLIENTEDGE, «edit», «7F7F7F»,
WS_CHILD|WS_VISIBLE|WS_BORDER, 380, 260, 60, 25,
hWnd,(HMENU)ID_EDITHEX, hInstance, NULL);


//Кнопка выхода
hExit=CreateWindowEx(WS_EX_CLIENTEDGE, «button», «Выход»,
WS_CHILD|WS_VISIBLE|WS_BORDER|BS_DEFPUSHBUTTON, 200, 315, 100, 25,
hWnd,(HMENU)ID_EXIT, hInstance, NULL);

//Обработка сообщения прокрутки по горизонтали
case WM_HSCROLL:

//Проверяем на какой полосе было перемещение
if(hRedScroll==(HWND)lParam) i=0;
if(hGreenScroll==(HWND)lParam) i=1;
if(hBlueScroll==(HWND)lParam) i=2;

case SB_PAGERIGHT: //На страницу вправо
nxPos+=10;
Mas[i]+=10;
break;

case SB_LINERIGHT: //На одну линию вправо
nxPos+=1;
Mas[i]+=1;
break;


case SB_PAGELEFT: //На страницу влево
nxPos-=10;
Mas[i]-=10;
break;

case SB_LINELEFT: //На линию влево
nxPos-=1;
Mas[i]-=1;
break;

case SB_TOP: //Максимальное значение
nxPos=nxMax;
Mas[i]=nxMax;
break;

case SB_BOTTOM: //Минимальное значение
nxPos=nxMax;
Mas[i]=nxMax;
break;

case SB_THUMBPOSITION: //Любое перемещение
case SB_THUMBTRACK:
nxPos=HIWORD(wParam);
break;

//Если позиция больше максимальной
if(nxPos>nxMax)
<
nxPos=nxMax; //Устанавливаем на граничную максимальную
Mas[i]=nxMax;
>

//Если позиция меньше минимальной
if(nxPos

if(nxPos==nxMax)
//Если положение движка достигло максимума, блокировать его
switch(i) <
case 0: EnableScrollBar(hRedScroll, SB_CTL, ESB_DISABLE_RIGHT); break;
case 1: EnableScrollBar(hRedScroll, SB_CTL, ESB_DISABLE_RIGHT); break;
case 2: EnableScrollBar(hRedScroll, SB_CTL, ESB_DISABLE_RIGHT); break;
>

//Вспоминаем, какая полоса была сдвинута
switch(i) <
case 0:
//Перемещаем движок
SetScrollPos(hRedScroll, SB_CTL, nxPos, TRUE);
//Выводим в поле ввода новое значение
SetDlgItemInt(hWnd, ID_EDITRED, nxPos,0);
break;

case 1:
SetScrollPos(hGreenScroll, SB_CTL, nxPos, TRUE);
SetDlgItemInt(hWnd, ID_EDITGREEN,nxPos,0);
break;

case 2:
SetScrollPos(hBlueScroll, SB_CTL, nxPos, TRUE);
SetDlgItemInt(hWnd, ID_EDITBLUE,nxPos,0);
break;
>

//Новые значения переменных цвета получены из полей ввода
red=GetDlgItemInt(hWnd, ID_EDITRED, NULL, 0);
green=GetDlgItemInt(hWnd, ID_EDITGREEN, NULL, 0);
blue=GetDlgItemInt(hWnd, ID_EDITBLUE, NULL, 0);

//Задаём границы области перерисовки по эллипсу
Client.left=330;
Client.top=60;
Client.right=480;
Client.bottom=220;

//Вызываем сообщение WM_PAINT по перерисовке области
//эллипса

InvalidateRect(hWnd, &Client, 1);
//Записываем в буфер 16-ричные эквиваленты цветов
sprintf(Buf, «%X%X%X», red, green ,blue);
//Выводим буфер в поле 16-ричного вывода
SetDlgItemText(hWnd, ID_EDITHEX,Buf);

//Сообщшение рисования
case WM_PAINT:
hDC = BeginPaint(hWnd, &PaintStruct);
GetClientRect(hWnd, &Rect);
//Прозрачный режим фона
SetBkMode(hDC, TRANSPARENT);
//Белый прямоугольник под эллипсом
Rectangle(hDC, 330, 60, 480, 220);
//Создаём кисть с новыми цветами
hBrush=CreateSolidBrush(RGB(red, green, blue));
//Делаем её активной
SelectObject(hDC, hBrush);
//Рисуем эллипс
Ellipse(hDC, 350,80,460,200);

//Выводим текст в окно
TextOut(hDC, 60,20,string, strlen(string));
TextOut(hDC, 370,20,string1, strlen(string1));
TextOut(hDC, 325, 234, string2, strlen(string2));

//Выводим текст над полями ввода разного цвета
SetTextColor(hDC, RGB(255,0,0));
TextOut(hDC, 240,42,»Red:»,4);
SetTextColor(hDC, RGB(0,255,0));
TextOut(hDC, 234,140,»Green:», 6);
SetTextColor(hDC, RGB(0,0,255));
TextOut(hDC, 240,240,»Blue:», 5);


EndPaint(hWnd, &PaintStruct);

case WM_COMMAND:
switch(LOWORD(wParam))<

//Завершение работы по кнопке «Выход»
case ID_EXIT:
DestroyWindow(hWnd);
return 0;
break;


case WM_DESTROY:
DeleteObject(hBrush);
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd,Message, wParam, lParam);

Заключение. Мы вроде бы всё так подробно обсудили до, что после как бы и говорить-то не о чем. Однако, есть некоторые моменты, которые здесь встречаются впервые.

Здесь я специально часть переменных, которые будут выведены TextOut объявил в начале, в виде переменных типа char*, это позволяет менять текст переменной, не меняя функции TextOut и соответственно длины строки. Она будет вычисляться автомтически.

Также ещё раз вспоминим, что для перерисовки главного окна, то есть принудительного вызова WM_PAINT, можно применять InvalidateRect. Существенным может показаться и то, что во избежания мерцания при каждом перемещении движка (особенно это заметно, когда движок ведёшь), я перерисовываю только область эллипса. Для этого я специально создал экземпляр структуры RECT под названием Client. Заполнив его поля параметрами эллипса, я, тем самым, задал лишь небольшой квадратик, который стоит перерисовывать. Всё же окно остаётся неизменным.

И самое интересное — вывод 16-ричного кода. Здесь я применил старый верный трюк языка Си, функцию sprintf. Вобще-то в Windows ей не место, это вам любой скажет, но здесь она уж очень хорошо смотрится. Да и как без неё — разве что применять алгоритм преобразования десятичных чисел в 16-ричные. В библиотеке классов MFC есть класс CString, который позволяет представить строку не как набор сиволов, а вроде бы даже, как самостоятельный тип данных. Спасибо ему за это!

Пример 2 «Таблица значений».

В следующем примере я научу вас создавать таблицы со значениями, которые даже можно прокручивать. Во многих книгах есть примеры вывода таблицы в главное окно и его прокрутка. Но, как мы с вами уже говорили, клиентскую область окна надо беречь и стараться оберегать для более важных вещей, чем временная информация. Кроме того, стоит вам прокрутить вниз такую таблицу хотя бы на одну высоту экрана, как заголовки столбцов «уползут» вверх и вы перестанете понимать, что это за цифры. А это недопустимо.

Поэтому сейчас я научу вас делать такую таблицу, которую никто больше не научит. Вывод таблицы в диалоговое окно! А? Каково! В этой программе я намеренно ввёл много элементов украшения, чтобы вы видели не только учебные программы, а реально работающие законченные окна. С такими программами работать приятнее, пусть даже мы на них только учимся.

Итак, о чём пойдёт речь? В этой таблице будет некоторая полезная информация — значения чисел от 0 до 255, эти же значения в квадрате, двойка в степени этого числа, 1 делённая на это число и экспоненциальная функция этого числа. Каждому значению будет отведён свой столбец в таблице. Итак, столбцов пять, строк 255. Представляем себе массив 255Х5. Поскольку числа будут дробные, тип данных будет double, но не float, поскольку для функции exp() нужны данные типа double. Кроме того, длины типа float может просто не хватить. К концу списка значения будут огромные!
Итак, подключаем в начале программы библиотеку math.h, объявляем массв:

Теперь надо спроектировать диалоговое окно, нарисовав его в редакторе ресурсов. Добавляем к программе новое окно и оформляем его следующим образом:

В свойствах диалогового окна, меняем заголовок на «Таблица», а идентификатор на IDD_TABLE. Кнопка так и будет IDOK. Перетащим в окно вертикальную полосу прокрутки, которую назовём IDC_SCROLL. В отличие от прошлого примера, полоса будет вертикальная и создана не динамически, а в виде ресурса.
Создадим под полосой прокрутки статический текст по имени IDC_STATIC. В его свойствах поставьте флажки на Border во вкладке Styles и Static Edge, и флажки: Modal Frame во вкладке Extended Styles.

Вот описание этого окна из файла ресурсов:

IDD_TABLE DIALOGEX 0, 0, 342, 201
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION «Таблица»
FONT 8, «MS Sans Serif»
BEGIN
DEFPUSHBUTTON «OK»,IDOK,145,180,50,14
SCROLLBAR IDC_SCROLL,310,10,20,155,SBS_VERT //полоса прокрутки и её координаты
LTEXT «1»,IDC_STATIC,310,170,20,15,WS_BORDER,
WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE
END

Создадим для этого окна функцию окна TableProc(), объявив её в начале программы:

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

Сделаем вызов нашего диалогового окна из меню. Для этого в главное меню добавим пункт IDM_TABLE, который будет называться «Таблица».

case IDM_TABLE:
DialogBox(hInst, (LPCTSTR)IDD_TABLE, hWnd, (DLGPROC)TableProc);
break;

Мы создали массив Mas. Теперь надо заполнить его числами. Лучше всего это сделать по сообщению WM_INITDIALOG в функции TableProc. На этом этапе инициализируются все переменные, с которыми будет работать диалоговое окно IDD_TABLE.

int i,j;
.
case WM_INITDIALOG:
for(i=0; i

При желании всегда будет можно заменить exp(i) на sqrt(i), если вам нужна не экспонента, а корень. В данном случае можно использовать те функции math.h, которые вам больше нужны.

К моменту вывода на экран диалогового окна, массив уже будет заполнен значениями.

Теперь, чтобы программа получилась красивой, займёмся графикой. Я включил в программу целый ряд кистей — синюю для фона, жёлтую для таблицы и чёрную для тени.

hBlue=CreateSolidBrush(RGB(0,130,255));
hYellow=CreateSolidBrush(RGB(255,255,170));
hBlack=CreateSolidBrush(RGB(0,0,0));

Нарисуем синий прямоугольник во весь фон, жёлтый — там, где будет таблица, а чёрный — её тень.

//Заливаем фон синим
SelectObject(hDC, hBlue);
Rectangle(hDC, 0,0, 640,480);

//Делаем тень таблицы
SelectObject(hDC, hBlack);
Rectangle(hDC, 20,20,420,270);

//Заливаем пространство таблицы жёлтым
SelectObject(hDC, hYellow);
Rectangle(hDC, 10,10,400,250);

Чтобы у таблицы были чёткие границы, я создал перо, толщиной 3 линии.
hPen=CreatePen(0,3,RGB(0,0,0));
SelectObject(hDC, hPen);

Место, где будет «шапка» таблицы отгорожено линией.
MoveToEx(hDC, 10,50, NULL);
LineTo(hDC, 400,50);

Выведем в неё названия заголовков. Чтобы не было белого фона под текстом, зададим режим отображения прозрачным.

//Фон прозрачный
SetBkMode(hDC, TRANSPARENT);

//Меняем цвет текста
SetTextColor(hDC, RGB(136,65,55));

//Выводим заголовки столбцов
TextOut(hDC, 26,20,»Num», 3);
TextOut(hDC, 100,20,»Num^2″, 5);
TextOut(hDC, 180,20,»2^Num», 5);
TextOut(hDC, 255,20,»1/Num», 5);
TextOut(hDC, 330,20,»Num», 3);

Теперь окно готово. Остаётся только выводить в него строки таблицы Mas в зависимости от положения полосы прокрутки. Что-то мы забыли сделать. Ах да, обработать сообщения от самой полосы! Без этого ничего в этом красивом окне не будет.
Так как на этот раз мы работаем с вертикальной полосой, то сообщение будет WM_VSCROLL.
Переменная, которую мы будем менять, будет называться yPos. Её значение будет постоянно выводиться в статическом окне IDC_STATIC, а также в зависимости от него, будут выводиться значения массива.

j=50;
for(i=yPos; i MAX) yPos=MAX;
//Установить движок на выбранную позицию
SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);
//Вывести текст в статический элемент
SetDlgItemInt(hDlg, IDC_STATIC, yPos, 0);
//Перерисовка
InvalidateRect(hDlg, &Client, 1);
InvalidateRect(hDlg, &Client1, 1);
break;

//На линию вверх
case SB_LINEUP:
yPos—;
//Если положение движка меньше 0, установить на 0
if(yPos

//На страницу вверх
case SB_PAGEUP:
yPos-=10;
if(yPos

//На страницу вниз
case SB_PAGEDOWN:
//Перемещаемся на 10 позиций
yPos+=10;
if(yPos>MAX) yPos=MAX;
SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);
SetDlgItemInt(hDlg, IDC_STATIC, yPos, 0);
InvalidateRect(hDlg, &Client, 1);
InvalidateRect(hDlg, &Client1, 1);

//Сообщение при перетаскивании
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
yPos=HIWORD(wParam); //получаем текущую позицию прокрутки
SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);
SetDlgItemInt(hDlg, IDC_STATIC, yPos, 0);
InvalidateRect(hDlg, &Client, 1);
InvalidateRect(hDlg, &Client1, 1);

Здесь есть несколько хитростей, в которые я вас посвящу.
Во-первых, посольку мы не создавали эту полосу динамически, идентификатора окна типа HWND у неё нет. Однако, для SetScrollPos он нужен. Как быть? Мы знаем, что идентификатор окна можно получить при обработке сообщения, как старшее слово lParam. Так мы и сделаем:

SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);

Даже если бы у нас было несколько вертикальных полос прокрутки, окно бы «поняло» от которой исходит сообщение в данный момент. Состояние движка, а значит переменной yPos мы выводим функцией SetDlgItemInt. И всё работает. Остаётся только маленькое но. Перерисовка. Как только мы начнём нажимать на прокрутку, всё окно перерисуется и мы вообще потеряем таблицу. Чтобы этого не случилось, мы можем перерисовывать только прокрутку со статическим окном, да кнопку «Ok». Но посольку они в разных частях окна, придётся перерисовывать сразу две области — прокрутки и кнопки.
Создадим два экземпляра структуры Rect и заполним их соответствующими координатами:

RECT Client, Client1;

Client.left=464; //прокрутка
Client.top=16;
Client.right=496;
Client.bottom=300;

Client1.left=219; //кнопка
Client1.top=293;
Client1.right=293;
Client1.bottom=316;

При прокрутке окна, придётся два раза вызывать функцию InvalidateRect для разных областей.

case SB_LINEDOWN:
yPos++;
if(yPos>MAX) yPos=MAX;
SetScrollPos((HWND)lParam, SB_CTL, yPos, 1);
SetDlgItemInt(hDlg, IDC_STATIC, yPos, 0);

InvalidateRect(hDlg, &Client, 1); //Здесь перерисовка запускается сразу для двух
InvalidateRect(hDlg, &Client1, 1); //областей. Так придётся делать каждый раз

Напоследок, скажу, что такие таблицы, какую мы создали считаются непрофессиональными. С таким же успехом мы могли создавать её и в DOS. Дело здесь в другом — в том, что на примере этой таблицы мы смогли рассмотреть наиболее полно полосу прокрутки. В следующей главе, мы закрепим наши знания, рассмотрев производные от полосы прокрутки — спин — прокрутку без полосы и ползунок, которым вы привыкли регулировать громкость.

Задание.

Сделайте, пожалуйста, чтобы после каждой строки, выведенной в окно, проводилась бы горизонтальная линия для удобства чтения. Таким образом таблица будет разбита на строки. Линия эта должна быть чёрного цвета.

Форум программистов «Весельчак У»

Учимся программировать => Начинающим => Тема начата: Amadeus от 03-10-2013 19:57

Название: Цвет скролла на CListBox
Отправлено: Amadeus от 03-10-2013 19:57

Amadeus, твоя проблема в том, что ты не понимаешь, что такое MFC. Нет «mfc’шного CListBox’а», есть системный контрол, а MFC просто обёртка над ним. Те ты можешь с ним делать ВСЁ и ТОЛЬКО ТО, что можешь делать с системным листбоксом.

Отсюда вывод — всё делается ручками. Так что «верной дорогой идёте товарищ» (с)

Илон Маск рекомендует:  Логирование в базах данных interbase (firebird)
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL