На этом шаге мы рассмотрим способ отображения текста в окне.
Под областью пользователя окна понимается изменяемая область, в которую Windows-программа выводит данные.
Любой тип данных (текст, растровое изображение и т.д.) выводится в графическом режиме. OWL осуществляет этот вывод с помощью реализации
Windows-функций GDI и функции Paint(), вызываемой при необходимости перерисовки окна.
Ниже приведем текст программы, отображающей текст в окне.
#include <owl\applicat.h> #include <owl\framewin.h> #include <owl\dc.h> //Класс приложения class TApp: public TApplication { public: TApp():TApplication(){} void InitMainWindow(); }; //Класс основного окна class TWndw:public TFrameWindow { public: TWndw(TWindow *parent,const char far *title); protected: void EvLButtonDown(UINT,TPoint &point); BOOL CanClose(); DECLARE_RESPONSE_TABLE (TWndw); }; DEFINE_RESPONSE_TABLE1 (TWndw, TFrameWindow) EV_WM_LBUTTONDOWN, END_RESPONSE_TABLE; TWndw::TWndw(TWindow *parent, const char far *title): TFrameWindow(parent,title) { // Определить расположение и размеры окна. Attr.X=100; Attr.Y=100; Attr.W=400; Attr.H=300; } void TWndw::EvLButtonDown(UINT,TPoint &point) { // Получить контекст устройства для области // пользовательского окна. TDC *DC= new TClientDC(HWindow); // Вывести текст в месте, указанном пользователем. DC->TextOut(point,"Щелчок!"); // Удалить контекст устройства. delete DC; } BOOL TWndw::CanClose() { int result=MessageBox("Вы действительно хотите закрыть окно?","Закрытие", MB_YESNO | MB_ICONQUESTION); if (result==IDYES) return TRUE; else return FALSE; } void TApp::InitMainWindow() { TFrameWindow *wndw=new TWndw(0,"Пример GDI-окна"); SetMainWindow(wndw); } int OwlMain(int,char *[]) { return TApp().Run(); }
Текст этой программы можно взять здесь.
Результат работы приложения изображен на рисунке 1:
Рис.1. Результат работы приложения
Когда вы запускаете программу, представленную в этом примере, на экране появится окно. Нажмите кнопку мыши,
и в том месте, куда указывает курсор мыши, появится слово "Щелчок!". Очевидно, программа перехватывает сообщение WM_LBUTTONDOWN;
но вместо того, чтобы по нажатию левой кнопки мыши вывести окно сообщений, она выводит текст. Эта операция реализована в функции отклика
на сообщение EvLButtonDown():
void TWndw::EvLButtonDown(UINT,TPoint &point) { // Получить контекст устройства для области // пользовательского окна. TDC *DC= new TClientDC(HWindow); // Вывести текст в месте, указанном пользователем. DC->TextOut(point,"Щелчок!"); // Удалить контекст устройства. delete DC; }
Эта функция не использует в качестве параметра виртуальный ключ-флаг, а использует координаты мыши, передаваемые в виде ссылки на объект класса TPoint, point.
Функция использует координаты, переданные в point, чтобы определить место для вывода текста.
Но первым делом EvLButtonDown() получает контекст устройства (Device Context, или DC) для области пользователя окна.
Это делается динамически с помощью оператора new, который в данном случае возвращает указатель на класс TDC. Мы уже отмечали, что
OWL поддерживает несколько классов DC, каждый для своего устройства. В данном случае функция использует TClientDC,
который обеспечивает доступ к внутренней оконной области пользователя. Прототип конструктора объекта DC выглядит следующим образом:
TClientDC(HWND wnd);
Как видите, чтобы получить DC для оконной области пользователя, необходимо передать дескриптор окна. К счастью, любое окно, производное от класса
TWindow, включает поле HWindow, содержащее этот дескриптор.
Получив DC, функция отображает на экране слово "Щелчок!" в точке, координаты которой переданы функции через point. Она выполняет это,
вызывая функцию-член TextOut() класса DC, являющуюся OWL-версией Windows-функции TextOut().
Ниже представлен прототип Windows API-версии функции TextOut() :
BOOL TextOut(HDC hDC, int X, int Y, LPSTR lpString, int nCount);
Здесь hDC - ссылка на контекст устройства, х и у - координаты точки, в которой вводится текст, lpString - указатель на строку,
оканчивающуюся нулем "\0", nCount - число символов в строке. OWL-версия функции TextOut() переопределяется двумя следующими прототипами:
BOOL TextOut(const TPoint &p, const char far *string, int count = -1); BOOL TextOut(int X, int Y, const char far *string, int count = -1);
В обоих случаях OWL-версия не требует дескриптора контекста устройства. TextOut() уже является частью объекта DC.
Объект знает свой собственный дескриптор, который хранится в защищенном поле Handle. Обе версии включают также количество вводимых символов, по умолчанию равное -1,
что предписывает функции вводить строку целиком. Благодаря этому стандартному значению, не требуется указывать количество символов в строке, если нужно вывести полную строку.
Наконец, OWL-версия TextOut() принимает координаты как в виде целых х и у, так и в виде объекта TPoint.
Возвращаясь к программе, отметим, что последняя строка использует оператор delete для удаления объекта TClientDC.
Замечания.
Поскольку объект TClientDC является производным от OWL-класса TDC, чтобы сделать его доступным, необходимо включить
заголовочный файл DC.H. Однако имейте в виду, что некоторые "малые" OWL-объекты используются в более значительных классах.
Эти классы уже содержат объявления таких базовых объектов. Например, класс TDC объявляет такие графические объекты, как точки, перья, кисти,
шрифты, растровые изображения, палитры и пиктограммы (иконки). Поэтому вы можете использовать соответствующие OWL-классы, не включая
их заголовочные файлы в вашу программу, как и было сделано в случае с TPoint в приведенном примере.
когда работа с ним закончена. Несоблюдение этого правила может повлечь неверную работу других приложений. Однако, в большинстве случаев классы,
производные от OWL-класса ТDС, освобождают соответствующий контекст устройства Windows когда объект TDC удаляется,
поэтому вам вряд ли придется освобождать контекст устройства Windows непосредственно в своей программе.
На следующем шаге мы рассмотрим Windows-функцию Paint().