Аннотация: На данной лекции описываются «собственно» функции вывода текста в окно приложения или во всплывающее окно. Также даётся представление о метриках текста и правилах их использования при выводе текста в окно приложения Windows. Также даётся представление об «окнах-сообщениях» (Message Box).
12.1. Вывод текста в окно
Операционная система Microsoft Windows использует способ вывода текста на экран, кардинально отличающийся от вывода текста средствами MS-DOS (как это было описано нами в предыдущих лекциях). В MS-DOS работало только одно приложение , и весь экран отводился исключительно под её нужды. Программа могла рисовать текст в любой позиции экрана, где угодно и, главное, когда ей было угодно.
В Windows и других оболочках с WIMP интерфейсом дела обстоят по-другому. Поскольку в ней работает несколько приложений, то операционная система «следит» за изменением размера и перемещением окон, и при необходимости извещает приложения, что им необходимо перерисовать содержимое окна.
Уроки Javascript / Как подключить и вывести результат выполнения на экран
Для извещения в очередь приложений записывается сообщение с идентификатором WM_PAINT , о котором было сказано в предыдущих лекциях. Получив такое сообщение, функция окна должна выполнить перерисовку всего окна или его части, в зависимости от дополнительной информации, полученной вместе с сообщением WM_PAINT . Для облегчения работы по отображению содержимого окна весь вывод в окно обычно выполняют в одном месте приложения — при обработке сообщения WM_PAINT в функции окна. Алгоритм приложения должен быть продуман таким образом, чтобы в любой момент времени, после получения сообщения WM_PAINT , функция окна могла бы перерисовать своё окно или её часть, заданную своими координатами. Последнее нетрудно сделать, если приложение где-то в памяти хранит своё текущее состояние, пользуясь которым функция окна может перерисовать своё окно.
Это, в-общем, не означает, что приложение должно хранить в памяти битовый образ окна и восстанавливать его по-необходимости, хотя и это можно сделать. Приложение должно хранить информацию, на основании которой оно может в любой момент времени перерисовать окно.
Например, при обработке текстовой информации, приложение Windows должно сохранять промежуточные и окончательные результаты расчётов в оперативной памяти, чтобы оно могло «по требованию», в любой момент времени выдать на экран (или на принтер, другое графическое устройство) промежуточные и окончательные результаты расчётов. Таким образом, программа Windows отличается от консольной программы-фильтра тем, что она хранит и обрабатывает начальные, промежуточные и конечные результаты работы «все сразу», а не считывая данные и осуществляя вывод данных «в процессе их последовательности поступления». Значит, программа Windows , в отличие от консольной программы-фильтра, обладает «памятью прошлых периодов». И эту особенность необходимо активно использовать.
Для вывода текста на экран дисплея в окно приложения используются функции TextOut , DrawText , ExtTextOut и TabbedTextOut . Все эти функции используют контекст отображения, и наследуют из него параметры рисования (атрибуты текста), такие как выравнивание и цвет символов. Эти атрибуты текста задаются функциями SetTextAlign и SetTextColor . Только после вызова этих функция для изменения контекста можно выводить текст в устройство.
Набросок на фрагменте экрана — простая программа для скриншотов | Достойная замена LightShot
Описание функций TextOut , ExtTextOut , DrawText и TabbedTextOut смотри в приложении № I ( пункт 12.7) к данной лекции.
Примечание. Кроме выравнивания и цвета текста, в атрибутах контекста можно сменить шрифт , которым будет выводиться текст на устройство. По-умолчанию используется системный шрифт со следующими свойствами: пропорциональный, без засечек, растровый (не масштабируемый), кегль 10. Этот шрифт устанавливается на панели управления операционной системы.
Кроме того, шрифт можно изменить программно. Но это выходит за рамки рассмотрения данного курса.
12.2. Метрики текста
При выводе текста в окно или на устройство широко используются метрики шрифта. Основные метрики шрифта представлены на рисунке 12.1.
увеличить изображение
Рис. 12.1. Метрики текста.
Среди метрик шрифта чаще всего используются следующие параметры:
- tm.tmMaxCharWidth , — определяющий максимальную ширину литеры шрифта (используется как ширина символа по-умолчанию);
- tm.tmHeight , — определяющий высоту прописных символов;
- tm.tmHeight + tm.tmExternalLeading — задающий высоту символа вместе с вертикальным отступом по-умолчанию. Численно равно «одному интервалу» при выводе строки символов.
Эти метрики можно присвоить переменным, отвечающим за положение текста в окне, при инициализации приложения, а потом использовать для вывода текста в окно в обработчике сообщения WM_PAINT (смотри пример программы в приложении № IV «Ввод-вывод с использованием WinAPI» ). Более подробно о шрифтах и о метриках шрифтов смотри в работах [35, 38].
12.3. Примеры функций для вывода в «рабочую область окна»
В качестве функций, осуществляющих вывод в указанный контекст неформатированного текста, можно привести функции PrintHDC , PrintLn и PrintTabbedHDC , текст которых приведён в приложении № IV «Ввод-вывод с использованием WinAPI» . Эти функции автор рекомендует к использованию для вывода текст в Windows .
Однако прежде чем использовать эти функции, Вы должны инициализировать метрики шрифтов, хранящиеся в глобальных переменных и используемые в указанных выше функциях. Это можно сделать при помощи фрагмента кода, представленного в приложении № II ( пункт 12.8) к данной лекции.
12.4. Функция MessageBox
В предыдущей части лекции мы рассмотрели вопрос о выводе текста в окно приложения. Однако, как Вы заметили, для вывода в него текста необходимо проделать множество дополнительных операций. А что делать, чтобы вывести просто предупреждение пользователю, например, сообщить об ошибочном действии? Что же, посылать каждый раз сообщение WM_PAINT ? А если надо прервать выполнение программы?
К счастью, для вывода текста с предупреждением можно использовать функцию вывода «всплывающих сообщений» MessageBox . Именно эта функция использовалась в [38] для демонстрации первого приложения Windows . Программирование многих приложений WIMP -интерфейса «начинается и заканчивается» вызовом этой функции. Рассмотрим её особенности.
Функция MessageBox является порождением от так называемых диалоговых панелей («окон диалога»), вызываемых приложениями Windows и служащих для «упорядоченного ввода-вывода» с использованием «ресурсов приложений». В принципе, на таких языках, как Delphi, Visual Basic и др., программирование с использованием диалоговых панелей является основным и даже единственным способом создания диалоговых программ. Особенностью окон диалога является:
- их модальность — пока пользователь не завершит работу с окном диалога, он не может редактировать другие данные приложения;
- их наследственность — окна диалога работают не «сами по себе», как «перекрывающиеся окна», а «привязаны» к одному из приложений.
На этих особенностях основана работа программ «мастеров» (» Wizard «), когда происходит последовательное уточнение параметров и проведение полезных действий программы путём последовательного вывода диалоговых окон и уточнения характера дальнейших действий.
Что касается функции MessageBox , то её назначение — это информирование пользователя о каких либо событиях и «нештатных ситуаций» при работе с программой. Её следует использовать:
- Для выдачи отладочной информации о работе программы (т.е. использовать её вместо программы — отладчика кода приложения);
- Для информирования пользователя о начале или об окончании работы алгоритма;
- Для информирования пользователя об отсутствии какого-либо ресурса (файла, изображения, области памяти и т.п.) или о его неисправности. В этом случае программа может попросить освободить нужные ресурсы, загрузить файл и т.п. для продолжения работы приложения и исправления, таким образом, ситуации;
- Попросить пользователя выбрать одну из двух альтернатив;
- Спросить пользователя, согласен ли он завершить алгоритм раньше времени (не обязательно при его ошибке);
- (Самый распространённый случай). Создание «заглушки» — дополнительного вопроса с подтверждением, действительно ли пользователь хочет совершить критичное для него действие (сохранить данные в уже созданный файл, выйти из программы без сохранения данных и т.п.). При этом у программистов есть правило: «Лишней «заглушки» не бывает!» Так что используйте заглушки как много чаще, но обязательно используйте его в соответствии «с логикой алгоритма»; Примечание. Большая «защищённость» Windows Vista по сравнению с Windows XP от вредоносных программ в основном обеспечивается большим количеством «заглушек» в этой операционной системе (наряду, конечно же, с исправлением грубых ошибок в системных библиотеках);
Во «всплывающем сообщении» может быть от одной до трёх кнопок, значения которых назначены по-умолчанию для каждого из стилей сообщения. Кроме того, Вы можете задать пиктограмму и звук, сопровождающий его появление, используя один из предопределённых стилей сообщения. Некоторые стили Вы можете комбинировать, указывая их константы , разделённые знаком «логического ИЛИ» в соответствующих полях. И, конечно же, Вы можете произвольно менять текст сообщения и текст заголовка сообщения по своим нуждам. В-общем, дерзайте!
Описание параметров функции MessageBox смотри в приложении № III ( пункт 12.11) к данной лекции.
12.5. Резюме функций
На данной лекции Вы познакомились с функциями текстового вывода в окно приложения средствами WinAPI и SDK Windows . Это поможет Вам написать простейшие «просмотрщики» («вьюеры») текстовых данных. Также Вы познакомились с окнами «всплывающих сообщений» ( Message Box ) и убедились, что «лишних заглушек не бывает».
12.6. Резюме курса
Итак, Вы познакомились с функциями текстового вывода в различных языках программирования: Ассемблер , Си/C++, «почти все» разновидности Бейсика, Perl, Python и Prolog. Также автор коснулся темы вывода текста в стандартное окно Windows .
При написании данного курса автор не скрывал, что его лекции направлены, прежде всего, для написания программ текстовых фильтров и вьюеров. Со своей задачей автор справился. Теперь студенты, с помощью имеющихся знаний, могут писать любые текстовые фильтры и вьюеры для операционных систем MS-DOS , Windows и Linux.
Ограничением данных программ является возможность их запуска только из командной строки. Однако никто не мешает сделать над этими командами «надстройку с графическим интерфейсом» (в терминологии Linux — » Front End «). Эта задача является более лёгкой, чем программирование фильтров, и с ними обязан справиться любой системный программист.
Источник: intuit.ru
Ввод и вывод данных Win32 API
В этой статье мы научимся обрабатывать данные, поступающие с клавиатуры. В дальнейшем это будет полезным пособием при создании простейшего текстового редактора типа notepad.exe.
Ниже представлен листинг:
#include LRESULT CALLBACK WindowProcess(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCommandLine, int nCommandShow) < TCHAR className[] = L»Мой класс»; HWND hWindow; MSG message; WNDCLASSEX windowClass; windowClass.cbSize = sizeof(windowClass); windowClass.style = CS_HREDRAW | CS_VREDRAW; windowClass.lpfnWndProc = WindowProcess; windowClass.lpszMenuName = NULL; windowClass.lpszClassName = className; windowClass.cbWndExtra = NULL; windowClass.cbClsExtra = NULL; windowClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); windowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); windowClass.hInstance = hInst; if(!RegisterClassEx( MessageBox(NULL, L»Не получилось зарегистрировать класс!», L»Ошибка», MB_OK); return NULL; >hWindow = CreateWindow(className, L»Программа ввода символов», WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, NULL, CW_USEDEFAULT, NULL, (HWND)NULL, NULL, HINSTANCE(hInst), NULL ); if(!hWindow) < MessageBox(NULL, L»Не получилось создать окно!», L»Ошибка», MB_OK); return NULL; >ShowWindow(hWindow, nCommandShow); UpdateWindow(hWindow); while(GetMessage( TranslateMessage( DispatchMessage( >return message.wParam; > LRESULT CALLBACK WindowProcess(HWND hWindow, UINT uMessage, WPARAM wParameter, LPARAM lParameter) < HDC hDeviceContext; PAINTSTRUCT paintStruct; RECT rectPlace; HFONT hFont; static char text[2]=; switch (uMessage) < case WM_CREATE: MessageBox(NULL, L»Пожалуйста, вводите символы и они будут отображаться на экране!», L»ВНИМАНИЕ. «, MB_ICONASTERISK|MB_OK); break; case WM_PAINT: hDeviceContext = BeginPaint(hWindow, GetClientRect(hWindow, SetTextColor(hDeviceContext, NULL); hFont=CreateFont(90,0,0,0,0,0,0,0, DEFAULT_CHARSET, 0,0,0,0, L»Arial Bold» ); SelectObject(hDeviceContext,hFont); DrawText(hDeviceContext, (LPCWSTR)text, 1, EndPaint(hWindow, break; case WM_KEYDOWN: switch (wParameter) < case VK_HOME:case VK_END:case VK_PRIOR: case VK_NEXT:case VK_LEFT:case VK_RIGHT: case VK_UP:case VK_DOWN:case VK_DELETE: case VK_SHIFT:case VK_SPACE:case VK_CONTROL: case VK_CAPITAL:case VK_MENU:case VK_TAB: case VK_BACK:case VK_RETURN: break; default: text[0]=(char)wParameter; InvalidateRect(hWindow, NULL, TRUE); break; >break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWindow, uMessage, wParameter, lParameter); > return NULL; >
Данная программа выводит цифры и буквы, при этом не реагирует на нажатие дополнительных клавиш, типа enter, shift и т.д.
В функции WinMain() ничего нового. А в WindowProcess() мы добавили обработчики событий нажатия клавиши.
Нажатие любой клавиши автоматически посылает системе аппаратное сообщение, которое обрабатывается и высылается приложению. За эту операцию отвечает сообщение WM_KEYDOWN .
Его описание сложно и на данном этапе не имеет смысла, так как мы не включили кириллицу. При посылке этого сообщения в wParameter записывается значение нажатой клавиши. Конечно же, всё зависит от клавиатуры, раскладки. Поэтому всего кодов для клавиш много и мы не будем описывать, что делать при нажатии той или иной, а просто исключим значения не нужных нам клавиш.
С 87-й по 101-ю строки мы обрабатываем сообщение WM_KEYDOWN (нажатие клавиши). Сначала мы создаём переключатель switch для значения wParameter , куда записан идентификатор клавиши. С 90-й по 95-ю строки мы исключаем значения home, end, page up, page down, стрелка влево, стрелка вправо, стрелка вверх, стрелка вниз, delete, shift, space, ctrl, caps lock, alt, tab, backspace, enter соответственно. Возможно, на вашей клавиатуре есть ещё клавиши, вы можете также их исключить при необходимости, потому что при нажатии будет «абракадабра». То есть если в идентификаторе wParameter у нас эти значения, мы ничего не делаем – в 96-й строке оператор break .
А под значениями default у нас выполняется преобразование. В 66 строке мы создали статическую строку типа char из 2-х элементов. Статическая она, потому что в процессе работы программы мы неоднократно выходим из WindowProcess() в цикл обработки с GetMessage() , расположенный в WinMain() , а значение клавиши нам нужно сохранять. Ну а в 98 строке мы инициализируем её первый элемент wParameter -ом.
В следующей строке мы вызываем функцию InvalidateRect() , после чего выходим из WM_KEYDOWN . Первым параметром идёт – дескриптор окна, вторым – область будущего «затирания» окна ( NULL – всё окно перерисовывается в WM_PAINT ), третьим параметром идёт «затирание» фона (если TRUE , то стираем). При этом мы автоматически посылаем приложению message WM_PAINT и окно перерисовывается заново. Для чего это нужно?
Как мы помним в случаях сворачивания, перемещения окна вызывается WM_PAINT . Нам же это нужно сделать явно, то есть сделать окно недействительным, для того, чтобы сразу вывести значение нажатой клавиши на экран. Иначе она появится только тогда, когда мы начнём манипулировать окном.
Теперь возвратимся 65-й строке. В ней объявлен экземпляр класса HFONT , который отвечает за шрифт, его размер и другие премудрости. Он будет использоваться в WM_PAINT .
В 69-й строке есть обработчик сообщения WM_CREATE . Он срабатывает, когда создаётся окно, то есть вызывается функция CreateWindow() . На этом этапе решено создать дополнительное окно с сообщением для удобства (строки 70-72).
Наконец, обработчик WM_PAINT . С 75-й по 77-ю строки происходит вызов функций контекста устройства (описывалось в статье).
А с 78-й по 82-ю строки вызывается функция CreateFont() . С её помощи мы меняем шрифт, и размер буквы. Вот её описание:
HFONT CreateFont(int, // высота шрифта int, // ширина символов int, // угол наклона букв int, // угол наклона строки int, // толщина букв («жирность») DWORD, // курсив DWORD, // подчеркивание DWORD, // перечеркивание DWORD, // набор символов DWORD, // точность вывода DWORD, // точность отсечения DWORD, // качество вывода DWORD, // шаг между буквами LPCTSTR // имя шрифта );
Шрифт выставлен Arial Bold – то есть Arial жирным. В строке 83 мы задаём контексту изменённые параметры шрифта. С 84-й по 85-ю строки ничего нового. Мы вводим на экран полученный идентификатор клавиши, преобразованный в тип char . В функции DrawText() его нужно преобразовать к типу LPCWSTR , что она и требует.
Результат работы программы при вводе буквы «с» такой:
В следующей статье мы научимся обрабатывать дополнительные клавиши, переключать раскладку, создавать таймеры отсчёта.
Источник: cppstudio.com
Как создать окно для вывода результата?
Нужно создать программу с таким интерфейсом. Как написать функцию, чтобы вывести результат? Наверное, тут вообще не entry, а какой-то другой виджет должен быть.
from tkinter import * from tkinter import ttk from tkinter import messagebox root = Tk() def formula(): try: return entry_2.set(4/3*3.14*(entry.get()**3)) except: messagebox.showinfo(‘Введите число’) title = Label(root, text = ‘Программа для вычисления объема сферы’) title.configure(font = (‘arial’, 10, ‘bold’)) title.grid(row = 0, column = 0, columnspan = 2) hint = Label(root, text = ‘Введите радиус:’) hint.grid(row = 1, column = 0) entry = Entry(root) entry.grid(row = 1, column = 1) explanation = Label(root, text = ‘Результат вычислений:’) explanation.grid(row = 2, column = 0) entry_2 = Entry(root) entry_2.grid(row = 2, column = 1) but_result = Button(root, text = ‘Вычислить’, command = formula) but_result.grid(row = 3, column = 0, columnspan = 2) but_save = Button(root, text = ‘Сохранить’) but_save.grid(row = 4, column = 0) drop_down = ttk.Combobox(root, values = [‘Текст’, ‘HTML’]) drop_down.current(0) drop_down.grid(row = 4, column = 1) root.mainloop()
Источник: ru.stackoverflow.com