Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Теллес М. - Borland C++ Builder. Библиотека программиста - 1998

.pdf
Скачиваний:
790
Добавлен:
13.08.2013
Размер:
4.35 Mб
Скачать

Borland C++ Builder (+CD). Библиотека программиста 101

его значение по умолчанию есть true. Далее мы запоминаем текущую страницу (ту, которая была отображена) для последующего использования.

Совет

Откуда мы знаем, что AllowChange — выходной параметр метода? В основном CBuilder передает объекты, которые не должны изменяться методом, по значению или по указателю. Параметры же, которые могут быть изменены методом, передаются по ссылке. Ссылка на объект это имя объекта, перед которым стоит символ & (амперсанд), например, bool &AllowChanges, а не bool AllowChanges.

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

Проверка разрешения на перемещение

Случаем, противоположным уходом со страницы, является запрещение пользователю выбора определенной страницы по щелчку на ее закладке в PageControl. Этот случай более сложный, чем предыдущий. Microsoft в своей безграничной мудрости в Windows 95 не предоставила

управляющему элементу страничному диалогу возможности не позволять выбор заданной страницы. Некоторые страничные диалоги, пришедшие из третьих рук, предоставляют такую возможность, но все, что написано с использованием стандартного Windows 95 Tab Control, не позволяет так делать. CBuilder, естественно, где только возможно использует зашитые в

операционной системе управляющие элементы для обеспечения совместимости с другими приложениями. Поэтому вы не можете просто взять и сделать страницу недоступной.

Замечание

На самом деле возможно сделать так, чтобы страница вела себя как недоступная. Это непросто, поэтому мы и не рассматриваем этого подробно. В общем, то, что вам надо сделать, это создать новый «подкласс» (компонент, наследующий от) объекта PageControl и отслеживать сообщение о нажатии кнопки мыши (WM_LBUTTONDOWN) на закладке страниц. Когда вы перехватите это сообщение, определите, на закладке какой именно страницы был произведен щелчок. Если страница не должна быть доступна, не давайте управляющему элементу страничного диалога получить сообщение о нажатии кнопки мыши.

Для обработки случая перехода на страницу, а не с нее, мы обработаем другое событие PageControl. В этом случае мы добавим обработчик для сообщения OnPageChange. Давайте рассмотрим очередной пример, в котором это осуществляется для запрещения перехода на страницу.

Перейдите на вторую страницу диалога, либо изменив свойство ActivePage объекта PageControl в Object Inspector, или же просто щелкнув на закладке второй страницы на форме в окне редактора форм. На отображенную чистую страницу положите две кнопки. Первую озаглавьте «Страница 3 разрешена», а вторую — «Страница 3 запрещена». Если пользователь нажмет на первую кнопку, ему будет разрешено перейти на третью страницу. Нажатие на вторую кнопку запретит пользователю переход на третью страницу. Все просто и ясно. На рис. 4.13 показана обновленная вторая страница нашего PageControl.

Borland C++ Builder (+CD). Библиотека программиста 102

Рис. 4.13. Вторая страница страничного диалога

Добавьте обработчик для первой кнопки (Страница 3 разрешена), а в него добавьте следующий код:

void __fastcall TPageDlg::Button1Click(TObject *Sender)

{

FbAllowPageThree = true;

}

Так же добавьте обработчик и для второй кнопки со следующим кодом:

void __fastcall TPageDlg::Button2Click(TObject *Sender)

{

FbAllowPageThree = false;

}

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

__fastcall TPagesDlg::TPagesDlg(TComponent* AOwner) :TForm(AOwner)

{

FnCurTab = 0; FbAllowPageThree = true;

}

Блокирование закладки

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

Borland C++ Builder (+CD). Библиотека программиста 103

Когда выбирается страница в страничном диалоге, она сначала выдает форме, на которой расположен элемент PageControl событие OnTabChanging для поверки того, можно ли уйти с этой страницы. Однако это нам нисколько не помогает, поскольку нас интересует вовсе не активная страница. А интересует нас та страница, на которой пользователь щелкнул мышью, то есть та, на которую он хочет перейти. К сожалению, событие OnTabChanging не сможет поделиться с нами никакой информацией об этой странице (у него ее просто нет). Однако после того, как произошла смена текущей страницы, элемент PageControl посылает форме другое событие. Это событие называется OnTabChange (по изменении страницы). Добавьте новый обработчик для события OnTabChange и озаглавьте его HandlePageChange (обработка смены страницы). Следующий код добавьте в обработчик HandlePageChange:

void –fastcall TPagesDlg::HandlePageChange(TObject *Sender)

{

//Если третья страница становится активной,

//проверяем, разрешена ли она

if ( PageControl1->ActivePage->PageIndex == 2 )

{

if ( FbAllowPageThree == false )

{

switch ( FnCurTab )

{

case 0: // Первая страница

PageControl1->ActivePage = TabCheet1; break;

case 1: // Вторая страница

PageControl1->ActivePage = TabCheet2; break;

}

}

}

//Изменяем заголовок формы, чтобы отобразить

//номер текущей страницы

Caption = "Работаем с: " + PageControl1->ActivePage->Caption;

}

Когда пользователь выбирает новую страницу, вызывается обработчик события

HandlePageChange. Свойство ActivePage управляющего элемента PageControl будет переустановлено так, что станет указывать на выбранную страницу (предположим, что была выбрана третья страница, — будет указывать на третью). Мы проверяем, действительно ли была выбрана третья страница, при помощи свойства PageIndex, принадлежащего объекту ActivePage. Конечно, мы бы могли просто сравнить, является ли объект ActivePage эквивалентным объекту TabSheet3, но мне просто хотелось показать вам еще один способ определения номера страницы. В конце концов удостоверившись каким угодно способом, что выбрана именно третья страница, мы проверяем, можно ли туда перейти.

Если пользователь до этого нажимал кнопку Страница 3 запрещена, мы должны предотвратить переход на третью страницу. При этом переменная AllowPageThree установлена в false. В этом случае мы выясняем, какая же у нас была страница до этого (мы устанавливали номер последней страницы ранее, в методе OnPageChanging) и делаем эту страницу активной. Обратите внимание на то, что здесь нельзя применить свойство PageIndex для изменения свойства ActivePage. Изменяя

Borland C++ Builder (+CD). Библиотека программиста 104

свойство PageIndex, вы просто изменяете порядок следования страниц в массиве страниц внутри объекта PageControl. Вы просто переместите третью страницу на вторую позицию (и, следовательно, вторую страницу на третью позицию). Вместо этого мы просто приравниваем свойство ActivePage к объекту странице, который мы хотим сделать текущим (TabSheet1 или

TabSheet2).

И в завершение мы устанавливаем заголовок формы в строку «Работаем с: », объединенную с заголовком текущей страницы. Это даст пользователю наглядное представление о том, на которой странице он в данный момент работает, даже если вся остальная часть формы не видна. Даже если пользователю пришлось минимизировать форму, заголовок все равно будет Работаем с: страница 2 (если на данный момент текущей является вторая страница), и он все равно будет знать, где находится. Как ни странно, но мне несколько раз приходилось работать над проектами, в которых было необходимо предоставить пользователю подобные возможности. Что ж, век живи век учись.

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

Поскольку страничные диалоги находят все более широкое применение и постепенно становятся частью системы Windows 95, очень важно понять принципы работы и возможности, предоставляемые этим компонентом, чтобы использовать его в своих приложениях. CBuilder делает работу с этим управляющим элементом настолько простой, что было бы непростительно не использовать этот компонент, тем более, что он бывает полезен достаточно часто.

Сами рисуем свое меню

Чуть ранее мы обсудили списки, прорисовываемые их владельцем. Такие списки позволяли вам отображать в качестве элемента списка все, что захотите (текст, графику, цвета, шрифты). Наверное, вы уже обратили внимание на то, что меню похоже на список. Оба эти объекта позволяют отображать некий список элементов. В этом они очень схожи. Еще они схожи в следующем: и тот, и другой позволяют отображать элементы списка в каком угодно формате. С этой точки зрения, меню даже лучше списков. Меню, как мы увидим в этом примере, позволяет вам отображать только те элементы, которые вы действительно хотите отобразить, и даже позволяет во время исполнения выбирать осуществляет ли меню отображение того или иного элемента в каком-то своем формате, или нет. Итак, в этом примере мы рассмотрим некоторые возможности отображения элементов меню в CBuilder, а также возможности изменения их поведения в соответствии с целями и задачами вашего приложения.

Замечание

Вы найдете исходный код примера программы работы с собственными меню в директории

Chapter4\OwnerDrawMenu прилагаемого компакт-диска.

Если вы помните, в разговоре об отображаемых владельцем списках мы упоминали о том, что для обработки такого отображения вам необходимо отследить два сообщения Windows. Первое сообщение это WM_MEASUREITEM, которое посылается каждому элементу в меню. Это сообщение подразумевает, что вы сообщили меню, насколько высоким каждый элемент должен быть на экране. Сообщение Windows WM_MEASUREITEM чудным образом заключено в событие

OnMeasureItem форм CBuilder.

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

Borland C++ Builder (+CD). Библиотека программиста 105

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

Имеем дело с Windows API

Если вы просмотрите методы компонентов VCL TMainMenu и TMenuItem, то не найдете среди них ни одного, который бы был напрямую ассоциирован с меню, отображаемыми их владельцем. И все по одной простой причине таких там нет. Так что, если вы всерьез захотите заиметь такие в своем приложении, вам придется иметь дело непосредственно с Windows API. Не бойтесь это не будет кошмаром, как было бы, работай вы в Visual Basic или даже Delphi, которые применяют отличные от API описания переменных. Вместо этого вы работаете на C++, языке, который отлично совместим с языком C, на котором и был, собственно, написан API. Большой разговор о функциях Windows API и CBuilder предстоит нам в следующей главе.

Функция Windows API, с которой нам придется столкнуться в этом примере, называется ModifyMenu. Функция ModifyMenu имеет следующий синтаксис:

ModifyMenuA( HMENU hMnu, UINT uPosition, UINT uFlags, UINT uIDNewItem, LPCSTR lpNewItem );

где hMnu — ссылка (handle) на меню; uPosition — позиция элемента меню, который вы собираетесь изменить внутри меню; uFlags — множество возможных флагов, используемых при изменении этого элемента меню; uIDNewItem — идентификатор изменяемого элемента; lpNewItem — либо строка, отображаемая в качестве элемента меню, либо ссылка на меню, в зависимости от параметра uFlags.

Параметр uFlags — это то самое место, с которым связана всю путаница в работе с этой функцией API. Как правило вы будете определять его как MF_BYCOMMAND или MF_BYPOSITION. Значение MF_BYCOMMAND означает, что параметр uIDNewItem определяет идентификатор элемента меню (значение, которое мы определяем в свойстве Command элемента меню). Значение же MF_BYPOSITION показывает, что параметр uIDNewItem определяет отсчитывающийся от 0 индекс в список элементов меню для ссылки на меню. Использование этого аргумента будет означать, что первое значение будет 0 вне зависимости от значения свойства Command.

Вместе с флагом MF_BYCOMMAND или MF_BYPOSITION, вы можете установить еще один флаг, определяющий, какого типа будет элемент меню. Это может быть MF_STRING, MF_BITMAP или MF_OWNERDRAW. В случае MF_STRING параметр lpNewItem будет указывать на строку, используемую как текст элемента меню. В случае MF_BITMAP параметр будет являться ссылкой на растровый рисунок, а флаг MF_OWNERDRAW означает, что параметр не важен. Аргумент MF_BITMAP мы не будем использовать в данном примере.

Чем тратить прорву времени на объяснение того, каким образом различные флаги могут быть использованы и скомбинированы, куда проще показать это на примере. Итак, добавьте элемент главного меню с именем «Fred» в меню. Потом добавьте второй элемент с именем «Irving» и третий, с названием «Изменить». В пункт Fred добавьте два подпункта с именами «George» и «Ralph». Это и будут наши элементы меню, отображаемые их владельцем. Исключительно для

Borland C++ Builder (+CD). Библиотека программиста 106

того, чтобы показать, что изменения в одном месте не влияют на элементы меню в другом, добавьте подпункт в пункт меню Irving с любым, каким вам будет угодно, именем. В пункт меню Изменить добавьте два подпункта с именами «Сделать отображаемыми владельцем» и «Сделать нормальными». Эти два пункта будут использоваться для переключения состояний одного из наших элементов.

Добавьте новый обработчик для события формы OnCreate. Присвойте этому обработчику имя FormCreate. В этот новый обработчик добавьте следующий код:

void __fastcall TForm1::FormCreate(TObject *Sender)

{

ModifyMenu(MainMenu1->Handle, George1->Command,

MF_BYCOMMAND | MF_OWNERDRAW, George1->Command,

0); ModifyMenu(MainMenu1->Handle, Ralph1->Command,

MF_BYCOMMAND | MF_OWNERDRAW, Ralph1->Command,

0);

}

Как вы видите, мы используем функцию API ModifyMenu для того, чтобы изменить два элемента меню (George и Ralph соответственно) так, чтобы они стали элементами, отображаемыми их владельцем. Команда ModifyMenu будет пытаться изменить команду, ассоциированную с элементом меню, так что нам придется передавать ее дважды, чтобы избежать изменений. Параметр нового элемента меню (последний) в данном случае не используется, так что мы просто передаем команде 0.

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

void __fastcall TForm1::George1Click(TObject *Sender)

{

MessageBox(NULL, "Вы выбрали Джорджа!", "Подтверждение", MB_OK );

}

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

Отображение элементов меню

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

Borland C++ Builder (+CD). Библиотека программиста 107

Добавьте обработчик для события формы OnMeasureItem и назовите его HandleMeasureItem, а в него добавьте следующий код:

void __fastcall TForm1::HandleMeasureItem(TMessage& Msg)

{

MEASUREITEMSTRUCT *lpmis = (LPMEASUREITEMSTRUCT) Msg.Lparam;

lpmis->itemHeight = 12; lpmis->itemWidth = 50;

}

Этот метод всего лишь модифицирует структуру Measure Item. Обратите внимание на то, что поскольку направленное нам сообщение является объектом TMessage, мы должны преобразовать часть его (LParam) в указатель на структуру, с которой будем работать. Работа с меню, отображаемыми их владельцем не настолько прозрачна, как с элементами списка, но все же достаточно проста.

Далее, добавьте обработчик для метода формы OnDrawItem. Присвойте новому обработчику имя HandleDrawItem и добавьте в него следующий код:

void __fastcall TForm1::HandleDrawItem(TMessage& Msg)

{

DRAWITEMSTRUCT *lpdis = (DRAWITEMSTRUCT *) Msg.LParam; TCanvas *canvas = new TCanvas;

canvas->Handle = lpdis->hDC;

if ((int)lpdis->itemID == George1->Command ) canvas->Brush->Color = clRed;

else

canvas->Brush->Color = clGreen;

// Определяем прямоугольник

TRect r;

r.Left = lpdis->rcItem.left; r.Top = lpdis->rcItem.top; r.Right = lpdis->rcItem.right;

r.Bottom = lpdis->rcItem.bottom;

canvas->FillRect(r); delete canvas;

}

Еще раз, поскольку воплощение меню, отображаемого владельцем, не столь просто, как аналогичного списка, отмечу, что вы должны преобразовать часть объекта-структуры TMessage в указатель на объект DRAWITEMSTRUCT, который содержит все куски кода для отрисовки меню. Имея структуру, мы используем ссылку (handle) на контекст устройства (device context), хранящуюся в этом объекте, для создания нового объекта Canvas для использования в коде отрисовки. Работать с объектом Canvas куда проще, чем со ссылкой на контекст устройства, лежащего в его основе, так что это делается для нашей же пользы. Все, что нам остается сделать, это определить, какой цвет выбрать, отталкиваясь от идентификатора itemID в структуре и заполнить этим цветом прямоугольник, который передается нам в структуре. Просто, как пареная репа.

Borland C++ Builder (+CD). Библиотека программиста 108

Изменение состояния во время исполнения

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

Добавьте обработчик для подпункта Сделать отображаемыми владельцем в пункте меню Изменить. В этот обработчик (названный MakeOwnerDraw1Click) добавьте следующий код:

void __fastcall TForm1::MakeOwnerDraw1Click(TObject *Sender)

{

ModifyMenu(MainMenu1->Handle, Ralph1->Command,

MF_BYCOMMAND | MF_OWNERDRAW, Ralph1->Command,

0);

}

Если этот код кажется вам знакомым, то вы в принципе правы. Это тот же самый код, который мы использовали ранее для того, чтобы сделать элемент отображаемым владельцем. Следующий пункт меню, Сделать нормальным, более интересен. Добавьте для него обработчик, назовите его MakeNormal1Click, и добавьте в него следующий код:

void __fastcall TForm1::MakeNormal1Click(TObject *Sender)

{

ModifyMenu(MainMenu1->Handle, Ralph1->Command, MF_BYCOMMAND | MF_STRING, Ralph1->Command,

"Ральф");

}

Это более обычный для функции API ModifyMenu вид. Этот вызов функции переустановит элемент меню Ralph так, что он будет обычной строкой и установит текст для него в «Ральф». Команда для пункта меню останется той же самой, поскольку мы передаем один и тот же идентификатор команды в старой и новой позициях. Отметьте, что мы передаем флаг MF_STRING чтобы показать, что мы хотим изменить текст пункта меню так, чтобы он был нормальной строкой. Если вы теперь скомпилируете и запустите приложение, выбор этого пункта меню будет изменять первый пункт меню так, что в нем будет отображать либо цветной прямоугольник, либо строку текста Ральф»).

Замечание

Вы, наверное, обратите внимание на то, что первый раз, когда вы выбираете пункт меню Сделать нормальным и потом выбираете первый пункт меню, текст Ральф отображен большим, чем обычно, шрифтом. Если навести на этот пункт (Ральф) курсор, он опять отобразится нормальным шрифтом. Это глюк Windows 95/NT API.

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

Borland C++ Builder (+CD). Библиотека программиста 109

Время в панели состояния.

Нашим последним примером в экскурсе в VCL станет кое-что, в чем многие программисты нуждаются в своих приложениях, но лишь немногие способны осуществить. Во многих приложениях существует необходимость отображать текущее время <Невеселый каламбур получился Примеч. перев.> в одной из секций панели состояния (status bar). Хотя обычно рабочий стол Windows 95/NT отображает его в нижнем правом углу, это происходит не всегда. Пользователи, которые изменили у себя рабочий стол так, что время на нем не показывается, ожидают, что ваше приложение должно предоставить им эту информацию. CBuilder позволяет осуществить их желание настолько легко, что для вас не может быть никаких оправданий, если вы все же не пойдете им навстречу и не положите часы в ваше приложение. В этом примере мы как раз и рассмотрим процесс отображения текущего времени в панели состояния. Когда мы его напишем, вы узнаете достаточно для того, чтобы отображать все что захотите в панели состояния во время исполнения.

Замечание

Вы найдете исходный код программы, отображающей время в панели состояния, в директории Chapter4/TimeInAStatusBar прилагаемого к книге компакт-диска.

На рис. 4.14 показана форма, которую мы будем использовать в этом примере. Как вы видите, на форме находятся панель состояния, таймер (timer) и три поля редактирования. Поля редактирования находятся там исключительно для того, чтобы показать вам, что код, который мы собираемся добавить для формы, не окажет никакого влияния на эффективность и ход исполнения приложения. Установите интервал таймера равным 1000 миллисекунд (единица измерения времени для таймера миллисекунды, так что вам надо просто ввести в поле соответствующего свойства 1000), то есть одной секунде. В данном приложении секунды будут отображаться, хотя, возможно, вам нужны только часы и минуты. Как вы увидите далее, это зависит только от вас.

Рис. 4.14. Пример приложения с часами на панели состояния

Добавьте две секции (panel) в компонент панель состояния. Первую секцию сделайте равной примерно двум третям ширины панели состояния, а вторую растяните так, чтобы она заняла все оставшееся на панели состояния место. Эту вторую секцию мы и собираемся использовать для отображения времени, так что убедитесь, что она достаточно широка, чтобы на ней поместились значения полных часов, минут и секунд текущего времени.

После того, как все свойства формы установлены, добавьте в форму обработчик события Timer. Это событие будет происходить каждый раз, когда закончится очередной интервал таймера.

Borland C++ Builder (+CD). Библиотека программиста 110

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

Добавьте следующий код в обработчик события Timer1Timer (что является именем события по умолчанию, которое появится, если вы дважды щелкните на событии Timer в Object Inspector):

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{

StatusBar->Panels->Items[1]->Text = Now().TimeString();

}

Вот и все, вот и весь пример. Свойство Panels панели состояния содержит объекты, которые представляют отдельные секции отображения панели состояния. Внутри свойства Panels свойство Items содержит информацию о каждой секции, включая, как мы видим из кода, и информацию о тексте, отображаемом в секции. Скомпилируйте и запустите приложение, и вы увидите текущее время на панели состояния.

Не правда ли впечатляет, что такое ничтожное количество кода способно произвести такой мощный эффект? Это лучший пример основанной на компонентах разработки приложения, который только можно придумать. Написав одну-единственную строку кода, мы получили законченное приложение, отображающее текущее время на панели состояния.

Что мы узнали в этой главе?

Попытка просуммировать все, что сделали в данной главе, приведет к ее полному переписыванию,

поэтому мы лишь выделим основные моменты из нашего головокружительного экскурса в библиотеку визуальных компонентов (Visual Component Library, VCL) CBuilder.

Мы узнали, как создавать управляющие элементы динамически и как обращаться к динамическим управляющим элементам.

Мы научились перехватывать нажатия клавиш внутри полей редактирования для проверки

вводимых данных.

Мы узнали, как обрабатывать события drag-and-drop между управляющими элементами

CBuilder.

Мы научились обрабатывать сообщения, которые не обрабатываются напрямую событиями

CBuilder.

Мы узнали об управляющих элементах и меню, отображаемых их владельцем, и о том, как их создавать в CBuilder.

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

Глава 5. Библиотека стандартных шаблонов

Концепция шаблонов

Массивы и векторы

Множества и списки

Таблицы

Соседние файлы в предмете Программирование на C++