Обучающие курсы:

Обучение профессии "Разработчик C#" + стажировка в Mail.ru
Обучение профессии "Разработчик Python" + трудоустройство
Обучение профессии "Веб-разработчик" + стажировка в Mail.ru


Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





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

Вернемся к функции TextOut. Задавать координаты в виде чисел не совсем удобно, поэтому чаще применяют другой способ позиционирования текста. Для этого нужно вычислить координаты клиентской части окна приложения при помощи функции GetciientRect. Мы уже знаем, как работает эта функция, и сейчас отобразим строку текста посередине клиентской области. В этом случае программный код будет выглядеть так, как представлено в листинге 5.4.
Листинг 5.4. Отображение текста посередине клиентской области окна приложения
.data
textOut DB "Text"
lenText EQU $-textOut
LOCAL hdc :HDC
LOCAL rect :RECT
LOCAL x, у :DWORD горизонтальная и вертикальная координаты
invoke GetciientRect, hWnd, ADDR rect
push EBX
mov
sub
EBX, rect.right
EBX, rect.left
mov x, EBX
mov EBX, rect.bottom
sub ЕВХ, rect.top
mov у, ЕВХ
pop ЕВХ
invoke TextOut, hdc, x, y, ADDR textOut, lenText

Как видно из исходного текста, координаты х и у будут точно указывать на середину клиентской области окна. Однако текст не будет располагаться симметрично относительно точек х и у, поскольку в нашем коде не учтен тот факт, что строка имеет определенную длину. Здесь возникает вопрос: каким образом подсчитать размер строки в логических единицах, чтобы правильно расположить текст в окне? Подобная задача довольно часто встречается в программистской практике.
Логично было бы предположить, что размер строки равен приблизительно горизонтальному размеру (ширине) символа, умноженному на количество символов в строке. Остается определить ширину символа. Ширину символа в логических единицах можно получить несколькими способами. Рассмотрим их по порядку.

Первый способ — с помощью функции GetTextMetrics. Функция имеет синтаксис:
BOOL GetTextMetrics(HDC hdc, LPTEXTMETRIC lptm)
В качестве параметров функция принимает дескриптор контекста устройства (hdc) и указатель (lptm) на структуру TEXTMETRIC, содержащую информацию о выбранном шрифте.
После вызова функции можно проанализировать значения полей в структуре TEXTMETRIC и сохранить некоторые из них для дальнейшего использования. Особенно интересными для нас являются два поля: tmAveCharwidth и tmHeight. Первое поле tmAveCharwidth определяет среднюю ширину шрифта, а второе tmHeight — его высоту. Этих данных вполне достаточно для того, чтобы написать программу, отображающую строку текста посередине окна и симметрично относительно его центра. Поскольку размеры системного шрифта не меняются в рамках одного сеанса работы с Windows, достаточно вызвать функцию GetTextMetrics только один раз при выполнении программы.

Исходный текст программы (назовем ее оиттм) представлен в листинге 5.5.
Листинг 5.5. Вывод строки посередине окна приложения
С ПОМОЩЬЮ функции G e t T e x t M e t r i c s
; OUTTM.ASM
.386
.model flat, stdcaii
option casemap :none
include \masm32\include\windows.. inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
; WinMain PROTO :DWORD, :DWORD, :DWORD,:DWORD WndProc PROTO
:DWORD,:DWORD,:DWORD, :DWORD
.data
szDisplayName DB "ПОЗИЦИОНИРОВАНИЕ ТЕКСТА С ИСПОЛЬЗОВАНИЕМ
GetTextMetric", О
CommandLine DD О
hWnd DD 0
hlnstance DD 0 szClassName DB "Demo_Class", 0 textOut
DB "Текст отображается функцией TextOut"
lenText EQU $-textOut
. code
start:
invoke GetModuleHandle, NULL
mov hlnstance, EAX
invoke GetCommandLine
mov CommandLine, EAX
invoke WinMain, hlnstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, 0
WinMain proc hlnst :DWORD, hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow DWORD
: Локальные переменные процедуры
LOCAL wc :WNDCLASSEX
; Заполнение структуры WNDCLASSEX требуемыми параметрами
mov wc.cbSize, sizeof WNDCLASSEX mov
CS_VREDRAW
mov wc.IpfnWndProc, offset WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
wc.style, CS HREDRAW or
push
pop
hlnst
wc.hlnstance
mov wc.hbrBackground, COLOR_BTNFACE+9
mov wc.IpszMenuName, NULL
mov wc.IpszClassName, offset szClassName
invoke Loadlcon, NULL, IDI_APPLICATION
mov wc.hlcon, EAX
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, EAX
mov wc.hlconSm, 0
invoke RegisterClassEx, ADDR wc
invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW, ADDR szClassName,\
ADDR szDisplayName, WS_OVERLAPPEDWINDOW,\
CW__USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, \
CW_USEDEFAULT, NULL, NULL, hlnst, NULL
mov hWnd,EAX
invoke ShowWindow,hWnd,SW_SHOWNORMAL
invoke UpdateWindow,hWnd

; Цикл обработки сообщений
StartLoop:
invoke GetMessage, ADDR msg, NULL, 0, 0
cmp ЕАХ, О
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:
mov EAX, msg.wParam
ret
WinMain endp
WndProc proc hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
LOCAL hdc :HDC
LOCAL rect :RECT
LOCAL tm :TEXTMETRIC
LOCAL tx, ty :DWORD
LOCAL x, у :DWORD
cmp uMsg, WM_LBUTTONDOWN
jne next_l
invoke GetDC, hWnd
mov hdc, EAX
invoke GetciientRect, hWnd, ADDR rect
; Позиционируем текст по горизонтали. Для этого получаем
; параметры шрифта и сохраняем их в переменных tx и ty
invoke GetTextMetrics, hdc, ADDR tm
mov EAX, tm.tmAveCharWidth
mov tx, EAX
mov EAX, tm.tmHeight
mov ty, EAX
push
mov
sub
EBX
EBX, rect.right
EBX, rect.left

; Вычисляем размер строки как произведение ширины символа(tx)
; на количество символов в строке (lenText)+1
mov ЕАХ, tx
mov ЕСХ, lenText
inc ECX
mul ECX
; Вычисляем начальную точку вывода текста по горизонтали
sub ЕВХ, ЕАХ
shr ЕВХ, 1
mov х, ЕВХ
; Позиционируем строку текста по вертикали
; с учетом высоты строки (ty)
mov ЕАХ, rect.bottom
sub EAX, rect.top
sub EAX, ty
shr EAX, 1
mov y, EAX invoke TextOut, hdc, x, y, ADDR textOut, lenText
invoke ReleaseDC, hWnd, hdc
ret
next_l:
cmp uMsg, WM_DESTROY
j ne next_2
invoke PostQuitM.es «* ^e, NULL
xor EAX, EAX
ret
next_2:
invoke DefWindowProc, hWin, uMsg, wParam, lParam
ret
WndProc endp
end start


 
 
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru