Несколько мелочей на всякий случай
В этой статье хочется показать кое-какие полезности, которые могут пригодиться для программировании.
Способы вывода русских символов в консоль и графическое окно.
Один из способов я упоминал в статье файлы,
это сохранение исходника в файле с форматом Unicode. Я покажу другие.
Прежде
всего есть превосходная библиотека ALBOM_FONT с открытым исходным кодом на
FreeBasic. Используя ее, достаточно после
команды Screen или ScreenRes вставить макрос:
#Include Once "albom_font.bi" и операторы Print и Input начнут признавать
русские символы в графическом окне. Скачать можно в соответствующей
колонке сайта.
Следующие два способа используют преобразование с помощью
функций API.
1) Используя функцию MultiByteToWideChar
#INCLUDE "windows.bi" Function PrintRus(Byval text As String) As Wstring Ptr Var blen = (Len(text)*2)+2 Dim As Wstring Ptr wbuf wbuf = Allocate( blen ) MultiByteToWideChar(CP_ACP, 0,text , -1, wbuf, blen) Print *wbuf Deallocate(wbuf) End Function PrintRus ("Выводим русские символы в консоль") Sleep
Ничего страшного в примере нет. В функции выделяется буфер в формате
юникодовой строки, куда и заносится преобразованное значение функцией
MultiByteToWideChar. Есть и обратная операция с помощью WideCharToMultiByte.
2) Используя функцию CharToOem
#INCLUDE "windows.bi" Dim As String st="Выводим русские символы в консоль" CharToOem(st,st) Print st: Sleep
Эта функция хороша тем, что может преобразовывать прямо в исходный буфер
как в примере выше. Если же надо преобразовывать символы в другой буфер, то его
надо выделять вручную (например с помощью Allocate). Или если заранее известно
кол-во символов в строке, то можно установить фиксированный буфер строки (dim as
string*256 dest) Есть и обратная операция преобразования с помощью функции
OemToChar.
Макрос IIF
Данный макрос это расширение стандартных условных операторов. Позаимствован из языка Си. Его синтаксис:
result = IIf ( condition, if_true, if_false )
- Result - результат работы макроса
- condition - сравниваемая инструкция или задаваемое условие
- if_true - result будет равен этому параметру , если condition истинно
- if_false - result будет равен этому параметру , если condition ложно
Пример:
? IIF(3>5,3,5) Sleep
В данном примере в первом параметре идет сравнение двух чисел . Поскольку
результат 3>5 является ложным, то макрос вернул третий параметр.
Открытие дополнительного окна консоли
Иногда при выводе графики может понадобится выводить текстовую информацию в другое окно. Это может быть какая-нибудь отладочная информация. Для этого можно воспользоваться функцией Open Cons.
Синтаксис:
Open Cons For output As #1
Open Cons For input As #1
Ничего особенного, как при открытии обычных файлов для записи или чтения.
Пример:
Dim a As String Screen 1 Draw "BM160,100" Dim As String drawbox = "U80R50D80L50" Draw "X" & Varptr(drawbox) Open Cons For Output As #1 Print #1,"Please write something and press ENTER" Line Input #1,a Print #1, "You wrote : ";a Close Sleep
Как видите, здесь уже при использовании оператора Print или Input надо
указывать идентификатор консоли.
Пенсионер GOSUB может еще поработать
На оф. сайте FreeBasic один из участников показал три примера использования отправленного в отставку оператора GOSUB. Каждая из этих симуляцией для своей версии установки компилятора. Все три компилируем как обычно fbc -s console
1 симуляция для версии совместимой с QB:
#Lang "qb" Dim C As Integer C = 5 For I As Integer = 0 To 5 Gosub CounterDown Next I Sleep End CounterDown: Print C Sleep 1 C -= 1 Return
2 симуляция для версии совместимой с FbLite:
#Lang "fblite" Option Gosub Dim C As Integer = 5 For I As Integer = 0 To 5 Gosub CounterDown Next I Sleep End CounterDown: Print C Sleep 1000 C -= 1 Return
3 симуляция для текущей версии FreeBasic , но тут следует оговориться.
Напрямую использовать команды Gosub и Return нельзя. Можно конечно жахнуть оба
макроса Gosub и Return , и описать их заново, но тогда останемся без функций и
процедур или придется и под них макросы писать :) Проще дать другое имя, как в
примере ниже:
#DEFINE _GoSub Asm Call #DEFINE _Label Asm #DEFINE _Return Asm Ret Dim C As Integer = 5 For I As Integer = 0 To 5 _GoSub CounterDown Next I Sleep End _Label CounterDown: Print C Sleep 1000 C -= 1 _Return
Печать
По своей сути в Freebasic печать сделана очень неважно, можно сказать почти никак. Именно поэтому, хоть у меня и нет принтера(точнее сломан) , я в своей библиотеке window9 реализовал самое необходимое для печати. Что касается средств FreeBasic:
Это все та же команда Open только с постфиксом Lpt .
Запускается принтер так:
Open Lpt( "LPT:" + printerName + ",EMU=TTY", For Output, As #1 )
Разбив первый параметр строки, получим:
- "LPT:" - параметр для Windows и Linux , для DOS "LPT1"
- printerName - имя принтера
- ",EMU=TTY" - специфично для Windows , будет использоваться GDI для преобразования текста в рисунок
- Остальное должно быть понятно из главы файлы
Печатается текст так же как и в файлы:
Print #1, "Hello, world!"
И освобождается дескриптор:
Close #1
Если не знаете имя принтера, не нужно пытаться подбирать его как пароль. Этим вы можете вызвать BSOD
Лучшим вариантом создать диалог для выбора принтера и выбрать в нем существующий. Пример ниже создал автор (v1ctor) FreeBasic:
#INCLUDE "windows.bi" #INCLUDE "win/commdlg.bi" Function selectPrinter( ) As String Dim As PrintDlg pd pd.lStructSize = Sizeof( PrintDlg ) If PrintDlg(@pd) = FALSE Then Exit Function End If Dim As DEVNAMES Ptr dn = GlobalLock( pd.hDevNames ) Function = *Cast( Zstring Ptr,_ Cast( Byte Ptr, dn )+ dn->wDeviceOffset ) GlobalUnlock( dn ) End Function Dim As String printerName printerName = selectPrinter( ) If( Len( printerName ) = 0 ) Then Print "No printer selected" End 1 End If If( Open Lpt( "LPT:" + printerName + _ ",EMU=TTY", For Output, As #1 ) <> 0 ) Then Print "Error: Open failed" End 1 End If Print #1, "Hello, world!" Close #1
Еще одна особенность Constructor и Destructor
Если записать процедуру вместе с конструктором или деструктором в любом месте кода, то можно установить ее первой запускаемой, либо последней соответственно. То есть они начнут выполняться перед самой первой строчкой кода, либо в случае с деструктором самой последней строчкой кода. Это может понадобится при инициализации каких-то данных, либо освобождении задействованных ресурсов.
Пример:
Sub BB Destructor Print "End" Sleep End Sub Print "1 string" Print "2 string" Print "3 string" Sub AA Constructor Print "first string" End Sub
Как видите конструктор стоит последним , но выполняется первым, а
деструктор наоборот. И это еще не все. Если установить несколько конструкторов и
деструкторов, то можно и между ними устанавливать приоритет. Для конструкторов
меньший приоритет обеспечивает запуск самым первым. Для деструкторов меньший
приоритет обеспечивает завершение самым последним. Приоритет должен быть в
диапазоне от 101 и выше.
Пример:
Print "1 string" Print "2 string" Print "3 string" Sub AA Constructor 102 Print "Second srting" End Sub Sub BB Constructor 101 Print "first string" End Sub Sleep
Пожалуй все для этой статьи. Всего доброго!
содержание | назад | вперед