<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>Форум QUIK [тема: VCLua версия 1.0 для графического интерфейса (GUI) в QUIK]</title>
		<link>http://forum.quik.ru</link>
		<description>Новое в теме VCLua версия 1.0 для графического интерфейса (GUI) в QUIK форума  на сайте Форум QUIK [forum.quik.ru]</description>
		<language>ru</language>
		<docs>http://backend.userland.com/rss2</docs>
		<pubDate>Mon, 04 May 2026 11:30:39 +0300</pubDate>
		<item>
			<title>VCLua версия 1.0 для графического интерфейса (GUI) в QUIK</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message78554/topic9136/">VCLua версия 1.0 для графического интерфейса (GUI) в QUIK</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			Мои скрипты имеют общую структуру:<br />
====code====
<pre>-- если VCLua установлена локально для скрипта!
package.cpath=getScriptPath()..'/'.._VERSION:sub(5)..'/?.dll;'..package.cpath
VCL = require "vcl.core"
local app = VCL.Application()
local ProcessMessages = app.ProcessMessages
-- необходимая магическая строка, без которой ничего работать не будет
app:Initialize()
-- если внутри VCLua или в ваших колбэках случится ошибка, вызовется эта функция
local function print_error(s)
&nbsp;&nbsp;message(s,&nbsp;&nbsp;3)
&nbsp;&nbsp;PrintDbgStr(s..'&#92;n'..debug.traceback(nil,2))
end
VCL.SetErrorReporter(print_error)

U = VCL.UTF8
W = VCL.WinCP

-- никакого обращения к VCLua не должно быть в колбэках QUIK, если сделали form:Show() в main
function OnStop()
&nbsp;&nbsp;is_run = false
end

local function CreateFormStaticPart()
-- статическая часть формы, вручную или через json
end

local function CreateForm()
&nbsp;&nbsp;CreateFormStaticPart()
&nbsp;&nbsp;form.OnCl ose = function()
&nbsp;&nbsp;&nbsp;&nbsp;OnStop()&nbsp;&nbsp;-- можно убрать и тогда форма будет сворачиваться на закрытии
&nbsp;&nbsp;&nbsp;&nbsp;return 'caMinimize'
&nbsp;&nbsp;end
&nbsp;&nbsp;-- динамическая часть формы, обработчики сообщений
&nbsp;&nbsp;...
&nbsp;&nbsp;--
&nbsp;&nbsp;form:Show()
end

local function CloseForm(form, method)
&nbsp;&nbsp;-- в середине работы можно вызывать Hide вместо Free; после Hide можно сделать form:Show(), чтобы форма снова стала видимой
&nbsp;&nbsp;form&#91;method&#93;(form)
end

local function CloseAllForms()
&nbsp;&nbsp;CloseForm(form_1, 'Free')
&nbsp;&nbsp;...
&nbsp;&nbsp;CloseForm(form_n, 'Free')
end

function main()
&nbsp;&nbsp;-- создаём форму в потоке main, а не в основном потоке квика
&nbsp;&nbsp;CreateForm()
&nbsp;&nbsp;while is_run do
&nbsp;&nbsp;&nbsp;&nbsp;-- обновляем GUI, делаем свои дела
&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp;&nbsp;&nbsp;-- отрисовываем обновление стакана и обрабатываем события
&nbsp;&nbsp;&nbsp;&nbsp;ProcessMessages(app)
&nbsp;&nbsp;&nbsp;&nbsp;-- для простоты спим, в реальном скрипте используются сообщения и MsgWaitForMultipleObjectsEx
&nbsp;&nbsp;&nbsp;&nbsp;sleep(1)
&nbsp;&nbsp;end

&nbsp;&nbsp;CloseAllForms()
&nbsp;&nbsp;-- обрабатываем события закрытия форм
&nbsp;&nbsp;app:ProcessMessages()
end

</pre>
=============
<br />Пример стакана с программированием формы вручную, без json<br /><table class="forum-spoiler"><thead onclick="if (this.nextSibling.style.display=='none') { this.nextSibling.style.display=''; BX.addClass(this, 'forum-spoiler-head-open'); } else { this.nextSibling.style.display='none'; BX.removeClass(this, 'forum-spoiler-head-open'); } BX.onCustomEvent('BX.Forum.Spoiler:toggle', [{node: this}]); event.stopPropagation();"><tr><th><div>Скрытый текст</div></th></tr></thead><tbody class="forum-spoiler" style="display:none;"><tr><td>
====code====
<pre>-- если VCLua установлена локально для скрипта
package.cpath=getScriptPath()..'/'.._VERSION:sub(5)..'/?.dll;'..package.cpath
VCL = require "vcl.core"
local app = VCL.Application()
local ProcessMessages = app.ProcessMessages
-- необходимая магическая строка
app:Initialize()
-- если внутри VCLua или в ваших колбэках случится ошибка, вызовется эта функция
local function print_error(s)
&nbsp;&nbsp;message(s,&nbsp;&nbsp;3)
&nbsp;&nbsp;PrintDbgStr(s..'&#92;n'..debug.traceback(nil,2))
end
VCL.SetErrorReporter(print_error)

U = VCL.UTF8
W = VCL.WinCP -- в данном скрипте не используется

local tickers = {
&nbsp;&nbsp;&#91;'MXM5'&#93; = {class='SPBFUT', sec='MXM5'},
&nbsp;&nbsp;&#91;'CRM5'&#93; = {class='SPBFUT', sec='CRM5'},
&nbsp;&nbsp;&#91;'CNYRUB_TOM'&#93; = {class='CETS', sec='CNYRUB_TOM'},
}
local ticker = tickers&#91;'MXM5'&#93;
local depths = {SPBFUT = 20, CETS = 20, TQBR = 10}

local fmt = string.format

local is_run = true

local function Unsub()
&nbsp;&nbsp;local cnt = 0
&nbsp;&nbsp;while not Unsubscribe_Level_II_Quotes(ticker.class,ticker.sec) and cnt&#60;50 do sleep(1); cnt = cnt + 1 end
&nbsp;&nbsp;message(ticker.sec..fmt(' статус подписки %s после %d попыток',IsSubscribed_Level_II_Quotes(ticker.class,ticker.sec),cnt), 1)
end

-- никакого обращения к VCLua не должно быть в колбэках QUIK, если сделали form:Show() в main
function OnStop()
&nbsp;&nbsp;is_run = false
&nbsp;&nbsp;Unsub()
end

local function CreateFormStaticPart(sec)
by_name = {}
quotes = VCL.Form(nil, "quotes")
by_name.quotes = quotes
grid = VCL.StringGrid(quotes, "grid")
by_name.grid = grid
stat = VCL.Label(quotes, "stat")
by_name.stat = stat
lPrice = VCL.Label(quotes, "lPrice")
by_name.lPrice = lPrice
ePrice = VCL.FloatSpinEdit(quotes, "ePrice")
by_name.ePrice = ePrice
eQuantity = VCL.SpinEdit(quotes, "eQuantity")
by_name.eQuantity = eQuantity
lQuantity = VCL.Label(quotes, "lQuantity")
by_name.lQuantity = lQuantity
quotes._ = {
&nbsp;&nbsp;&nbsp;&nbsp;FormStyle = 'fsStayOnTop',
&nbsp;&nbsp;&nbsp;&nbsp;Width = 319,
&nbsp;&nbsp;&nbsp;&nbsp;Top = 577,
&nbsp;&nbsp;&nbsp;&nbsp;Font = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Size = 9,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;Left = 1563,
&nbsp;&nbsp;&nbsp;&nbsp;Height = 400,
}
grid._ = {
&nbsp;&nbsp;&nbsp;&nbsp;Columns = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 8446885,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Title = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Своя'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taCenter',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Font = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 16711935,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taRightJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 34,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 45,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taRightJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 8446885,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Title = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Сумма'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taLeftJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 45,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taRightJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 8446885,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Title = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Лоты'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taCenter',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 35,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taRightJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 8446885,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Title = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Цена'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taCenter',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 35,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taRightJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 10791167,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Title = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Цена'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taCenter',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 45,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taRightJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 10791167,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Title = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Лоты'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taCenter',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 45,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taRightJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 10791167,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Title = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Сумма'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taLeftJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 10791167,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Title = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Своя'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taCenter',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Font = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = 16711935,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taRightJustify',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 35,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;DefaultRowHeight = 17,
&nbsp;&nbsp;&nbsp;&nbsp;Align = 'alNone',
&nbsp;&nbsp;&nbsp;&nbsp;GridLineColor = 'clBtnFace',
&nbsp;&nbsp;&nbsp;&nbsp;FixedColor = 'clWindow',
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideBottom = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = stat,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;BorderStyle = 'bsNone',
&nbsp;&nbsp;&nbsp;&nbsp;AutoEdit = false,
&nbsp;&nbsp;&nbsp;&nbsp;Width = 319,
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideTop = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = quotes,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideRight = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = quotes,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrBottom',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideLeft = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = quotes,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;Options = '&#91;goFixedVertLine,goVertLine,goColSizing,goDblClickAutoSize,goSmoothScroll,goRowHighlight&#93;',
&nbsp;&nbsp;&nbsp;&nbsp;Anchors = '&#91;akTop,akLeft,akRight,akBottom&#93;',
&nbsp;&nbsp;&nbsp;&nbsp;Flat = true,
&nbsp;&nbsp;&nbsp;&nbsp;FixedCols = 0,
&nbsp;&nbsp;&nbsp;&nbsp;RowCount = 21,
}
stat._ = {
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideBottom = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = eQuantity,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrTop',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideLeft = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = quotes,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideRight = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = quotes,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrBottom',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;Alignment = 'taCenter',
&nbsp;&nbsp;&nbsp;&nbsp;Anchors = '&#91;akLeft,akRight,akBottom&#93;',
}
lPrice._ = {
&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Цена'),
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideBottom = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = ePrice,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrCenter',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideLeft = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = quotes,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;Anchors = '&#91;akLeft,akBottom&#93;',
}
ePrice._ = {
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideBottom = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = eQuantity,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrBottom',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;Increment = 0.001,
&nbsp;&nbsp;&nbsp;&nbsp;BorderSpacing = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Left = 5,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Right = 5,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;MaxValue = 2147483647.0,
&nbsp;&nbsp;&nbsp;&nbsp;Anchors = '&#91;akLeft,akRight,akBottom&#93;',
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideLeft = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = lPrice,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrBottom',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideRight = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = lQuantity,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;Caption = '0,00',
&nbsp;&nbsp;&nbsp;&nbsp;DecimalPlaces = 3,
&nbsp;&nbsp;&nbsp;&nbsp;MinValue = 0.0,
}
eQuantity._ = {
&nbsp;&nbsp;&nbsp;&nbsp;Width = 75,
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideBottom = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = quotes,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrBottom',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;BorderSpacing = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Left = 5,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Right = 5,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;Caption = '1',
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideRight = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = quotes,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrBottom',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;MaxValue = 2147483647.0,
&nbsp;&nbsp;&nbsp;&nbsp;Anchors = '&#91;akRight,akBottom&#93;',
&nbsp;&nbsp;&nbsp;&nbsp;MinValue = 1.0,
}
lQuantity._ = {
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideRight = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = eQuantity,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;AnchorSideBottom = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control = eQuantity,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Side = 'asrCenter',
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;Caption = U('Лот'),
&nbsp;&nbsp;&nbsp;&nbsp;Anchors = '&#91;akRight,akBottom&#93;',
}
&nbsp;&nbsp;form = quotes
end

-- переменные для связи между потоками скрипта
local cb_t, recv_t = {}, {}


local function CreateForm()
&nbsp;&nbsp;local sec = ticker.sec
&nbsp;&nbsp;CreateFormStaticPart(sec)
&nbsp;&nbsp;-- U чтобы не было кракозябр
&nbsp;&nbsp;form.Caption = ticker.class..'-'..sec..U(' стакан')
&nbsp;&nbsp;form.OnCl ose = function()
&nbsp;&nbsp;&nbsp;&nbsp;OnStop()&nbsp;&nbsp;-- можно убрать и тогда стакан будет сворачиваться на закрытии
&nbsp;&nbsp;&nbsp;&nbsp;return 'caMinimize'
&nbsp;&nbsp;end
&nbsp;&nbsp;local info = getSecurityInfo(ticker.class, ticker.sec)
&nbsp;&nbsp;if info then
&nbsp;&nbsp;&nbsp;&nbsp;-- настраиваем поле ввода цены согласно параметрам инструмента
&nbsp;&nbsp;&nbsp;&nbsp;by_name.ePrice.DecimalPlaces = info.scale
&nbsp;&nbsp;&nbsp;&nbsp;by_name.ePrice.Increment = info.min_price_step
&nbsp;&nbsp;end

&nbsp;&nbsp;local grid = by_name.grid
&nbsp;&nbsp;-- по нажатию левой кнопки мыши на некоторых ячейках стакана поле цены будет меняться
&nbsp;&nbsp;local function setp(c,r)
&nbsp;&nbsp;&nbsp;&nbsp;local price = grid:Cells(c &#60;= 1 and 3 or 4, r)
&nbsp;&nbsp;&nbsp;&nbsp;if price ~= "" then by_name.ePrice.Value = price end
&nbsp;&nbsp;end
&nbsp;&nbsp;local col_funcs = {setp, setp, &#91;7&#93; = setp, &#91;8&#93; = setp}
&nbsp;&nbsp;grid.OnMouseD own = function(_,Button,Shift,X,Y)
&nbsp;&nbsp;&nbsp;&nbsp;local col, row = grid:MouseToCell2(X,Y)
&nbsp;&nbsp;&nbsp;&nbsp;if row == 0 then return end
&nbsp;&nbsp;&nbsp;&nbsp;if Button == "mbLeft" and (col &#60; 2 or col &#62; 5) then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- нумерация в Lua от 1, а в Free Pascal от 0, поэтому col+1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;col_funcs&#91;col+1&#93;(col, row)
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
&nbsp;&nbsp;-- глубина стакана зависит от инструмента и от сервера, + 1 для заголовка
&nbsp;&nbsp;grid.RowCount = depths&#91;ticker.class&#93; + 1
&nbsp;&nbsp;-- некоторые параметры удобнее менять при исполнении, чем искать способ в LCL сделать автоматически как хочется
&nbsp;&nbsp;local function on_change_width()
&nbsp;&nbsp;&nbsp;&nbsp;local mid = form.Width // 2
&nbsp;&nbsp;&nbsp;&nbsp;by_name.eQuantity.Width = by_name.eQuantity.Left - mid + by_name.eQuantity.Width
&nbsp;&nbsp;end
&nbsp;&nbsp;-- вызывается при изменении ширины заголовков, делает ширины симметричными
&nbsp;&nbsp;grid.OnHeaderSi zed = function(o,_,index)
&nbsp;&nbsp;&nbsp;&nbsp;local c = o.Columns
&nbsp;&nbsp;&nbsp;&nbsp;c:Items(c.Count-1-index).Width = c:Items(index).Width
&nbsp;&nbsp;&nbsp;&nbsp;local rect = o:CellRect(o.ColCount-1, o.RowCount-1)
&nbsp;&nbsp;&nbsp;&nbsp;form.Width = rect.right
&nbsp;&nbsp;&nbsp;&nbsp;on_change_width()
&nbsp;&nbsp;end
&nbsp;&nbsp;-- высота стакана подстраивается по нажатию мыши на поле статистики
&nbsp;&nbsp;by_name.stat.OnMouseD own = function(_,Button,Shift,X,Y)
&nbsp;&nbsp;&nbsp;&nbsp;on_change_width()
&nbsp;&nbsp;&nbsp;&nbsp;local rect = grid:CellRect(grid.ColCount-1, grid.RowCount-1)
&nbsp;&nbsp;&nbsp;&nbsp;local h = form.Height + rect.bottom - grid.Height
&nbsp;&nbsp;&nbsp;&nbsp;form.Constraints.MinHeight = h
&nbsp;&nbsp;&nbsp;&nbsp;form.Height = h
&nbsp;&nbsp;end
&nbsp;&nbsp;-- НЕ модально показываем форму, поэтому потребуется регулярный вызов ProcessMessages
&nbsp;&nbsp;form:Show()

&nbsp;&nbsp;local was = IsSubscribed_Level_II_Quotes(ticker.class,sec)
&nbsp;&nbsp;local subscribed = Subscribe_Level_II_Quotes(ticker.class,sec)
&nbsp;&nbsp;local cnt = 0
&nbsp;&nbsp;if subscribed then
&nbsp;&nbsp;&nbsp;&nbsp;while not IsSubscribed_Level_II_Quotes(ticker.class,sec) and is_run do sleep(1); cnt = cnt + 1 end
&nbsp;&nbsp;end
&nbsp;&nbsp;message(sec..fmt(' подписка %s изначально %s после %d попыток',subscribed,was,cnt), cnt &#62; 5 and 3 or 1)

&nbsp;&nbsp;cb_t&#91;ticker.sec&#93; = {sent=0}
&nbsp;&nbsp;recv_t&#91;ticker.sec&#93; = {updates=0,received=0,class=ticker.class,depth=depths&#91;ticker.class&#93;,by_name=by_name}

&nbsp;&nbsp;-- в поле цены ставим цену последней сделки, если есть
&nbsp;&nbsp;local last = getParamEx(ticker.class, sec, "LAST")
&nbsp;&nbsp;if last then by_name.ePrice.Value = tonumber(last.param_value) end
end

local function CloseForm(form, method)
&nbsp;&nbsp;-- в середине работы можно вызывать Hide вместо Free; после Hide можно сделать form:Show(), чтобы форма снова стала видимой
&nbsp;&nbsp;form&#91;method&#93;(form)
end

local function CloseAllForms()
&nbsp;&nbsp;CloseForm(form, 'Free')
end

-- никакого обращения к VCLua не должно быть в колбэках QUIK, если сделали form:Show() в main
function OnQuote(class_code, sec_code)
&nbsp;&nbsp;local sent = cb_t&#91;sec_code&#93;
&nbsp;&nbsp;-- сохраняем номер срабатывания колбэка для данного sec_code
&nbsp;&nbsp;if sent then sent.sent = sent.sent + 1 end
end

-- чисто для скорости работы
local sc = VCL.GetCallable('TStringGrid','SetCells')
local BeginUpdate = VCL.GetCallable('TStringGrid','BeginUpdate')
local EndUpdate = VCL.GetCallable('TStringGrid','EndUpdate')
local tointeger = math.tointeger
local getQuoteLevel2 = getQuoteLevel2

-- реализация обновления стакана
local function updateGrid()
&nbsp;&nbsp;local sec = ticker.sec
&nbsp;&nbsp;local recv = recv_t&#91;sec&#93;
&nbsp;&nbsp;local s = cb_t&#91;sec&#93;.sent
&nbsp;&nbsp;local p,pq,q,last,pqs,quantity
&nbsp;&nbsp;-- если номер срабатывания колбэка вырос...
&nbsp;&nbsp;if recv.received &#60; s then
&nbsp;&nbsp;&nbsp;&nbsp;-- ...сохраним новый и обновим стакан
&nbsp;&nbsp;&nbsp;&nbsp;recv.received = s
&nbsp;&nbsp;&nbsp;&nbsp;local depth = recv.depth
&nbsp;&nbsp;&nbsp;&nbsp;local by_name = recv.by_name

&nbsp;&nbsp;&nbsp;&nbsp;local updates = recv.updates + 1
&nbsp;&nbsp;&nbsp;&nbsp;recv.updates = updates
&nbsp;&nbsp;&nbsp;&nbsp;updates = s - updates
&nbsp;&nbsp;&nbsp;&nbsp;-- выводим потери обновлений стакана
&nbsp;&nbsp;&nbsp;&nbsp;by_name.stat.Caption = fmt('%d/%d=%.1f%%',updates,s,updates/s*100)

&nbsp;&nbsp;&nbsp;&nbsp;local grid = by_name.grid
&nbsp;&nbsp;&nbsp;&nbsp;local qt = getQuoteLevel2(recv.class, sec)
&nbsp;&nbsp;&nbsp;&nbsp;pqs = qt.bid
&nbsp;&nbsp;&nbsp;&nbsp;BeginUpdate(grid)
&nbsp;&nbsp;&nbsp;&nbsp;if pqs then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last = tointeger(qt.bid_count)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q = 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local last1 = last + 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = 1,last do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pq = pqs&#91;last1 - i&#93;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p = pq.price
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,3,i,p)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quantity = pq.quantity
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,2,i,quantity)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q = q + tointeger(quantity)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,1,i,q)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if last &#60; depth then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = last1,depth do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,3,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,2,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,1,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;pqs = qt.offer
&nbsp;&nbsp;&nbsp;&nbsp;if pqs then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last = tointeger(qt.offer_count)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q = 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = 1,last do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pq = pqs&#91;i&#93;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p = pq.price
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,4,i,p)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quantity = pq.quantity
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,5,i,quantity)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q = q + tointeger(quantity)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,6,i,q)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if last &#60; depth then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = last+1,depth do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,4,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,5,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,6,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;EndUpdate(grid)
&nbsp;&nbsp;end
end

function main()
&nbsp;&nbsp;-- создаём форму в потоке main, а не в основном потоке квика
&nbsp;&nbsp;CreateForm()
&nbsp;&nbsp;while is_run do
&nbsp;&nbsp;&nbsp;&nbsp;-- обновляем стакан
&nbsp;&nbsp;&nbsp;&nbsp;updateGrid()
&nbsp;&nbsp;&nbsp;&nbsp;-- отрисовываем обновление стакана и обрабатываем события
&nbsp;&nbsp;&nbsp;&nbsp;ProcessMessages(app)
&nbsp;&nbsp;&nbsp;&nbsp;sleep(1)
&nbsp;&nbsp;end

&nbsp;&nbsp;CloseAllForms()
&nbsp;&nbsp;-- обрабатываем события закрытия форм
&nbsp;&nbsp;app:ProcessMessages()
end</pre>
=============
</td></tr></tbody></table><br />Пример стакана с загружаемой и обновляемой через json формой<br />json:<br /><table class="forum-spoiler"><thead onclick="if (this.nextSibling.style.display=='none') { this.nextSibling.style.display=''; BX.addClass(this, 'forum-spoiler-head-open'); } else { this.nextSibling.style.display='none'; BX.removeClass(this, 'forum-spoiler-head-open'); } BX.onCustomEvent('BX.Forum.Spoiler:toggle', [{node: this}]); event.stopPropagation();"><tr><th><div>Скрытый текст</div></th></tr></thead><tbody class="forum-spoiler" style="display:none;"><tr><td>
====code====
<pre>{
&nbsp;&nbsp;"class": "Form",
&nbsp;&nbsp;"items": &#91;
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"class": "StringGrid",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"items": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name": "grid",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"props": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Align": "alNone",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideBottom": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.stat.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideLeft": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideRight": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrBottom",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideTop": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Anchors": "&#91;akTop,akLeft,akRight,akBottom&#93;",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AutoEdit": false,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"BorderStyle": "bsNone",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Columns": &#91;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taRightJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 8446885,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Font": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 16711935,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Title": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Своя",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 34,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taRightJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 8446885,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Title": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taLeftJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Сумма",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 45,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taRightJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 8446885,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Title": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Лоты",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 45,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taRightJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 8446885,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Title": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Цена",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 35,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taRightJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 10791167,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Title": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Цена",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 35,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taRightJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 10791167,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Title": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Лоты",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 45,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taRightJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 10791167,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Title": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taLeftJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Сумма",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 45,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taRightJustify",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 10791167,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Font": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Color": 16711935,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Title": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Своя",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 35,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#93;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"DefaultRowHeight": 17,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"FixedColor": -2147483643,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"FixedCols": 0,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Flat": true,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"GridLineColor": -2147483633,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Options": "&#91;goFixedVertLine,goVertLine,goColSizing,goDblClickAutoSize,goSmoothScroll,goRowHighlight&#93;",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"RowCount": 21,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 319,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"class": "Label",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"items": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name": "stat",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"props": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Alignment": "taCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideBottom": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.eQuantity.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrTop",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideLeft": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideRight": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrBottom",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Anchors": "&#91;akLeft,akRight,akBottom&#93;",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"class": "Label",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"items": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name": "lPrice",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"props": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideBottom": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.ePrice.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideLeft": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Anchors": "&#91;akLeft,akBottom&#93;",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Цена",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"class": "FloatSpinEdit",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"items": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name": "ePrice",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"props": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideBottom": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.eQuantity.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrBottom",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideLeft": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.lPrice.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrBottom",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideRight": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.lQuantity.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Anchors": "&#91;akLeft,akRight,akBottom&#93;",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"BorderSpacing": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Left": 5,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Right": 5,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "0,00",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"DecimalPlaces": 3,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Increment": 0.001,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"MaxValue": 2147483647.0,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"MinValue": 0.0,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"class": "SpinEdit",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"items": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name": "eQuantity",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"props": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideBottom": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrBottom",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideRight": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrBottom",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Anchors": "&#91;akRight,akBottom&#93;",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"BorderSpacing": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Left": 5,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Right": 5,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "1",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"MaxValue": 2147483647.0,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"MinValue": 1.0,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Width": 75,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;}, {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"class": "Label",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"items": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name": "lQuantity",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"props": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideBottom": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.eQuantity.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Side": "asrCenter",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"AnchorSideRight": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Control": "quotes.eQuantity.vt-form",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Anchors": "&#91;akRight,akBottom&#93;",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Caption": "Лот",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;}, 
&nbsp;&nbsp;&#93;,
&nbsp;&nbsp;"name": "quotes",
&nbsp;&nbsp;"props": {
&nbsp;&nbsp;&nbsp;&nbsp;"Font": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Size": 9,
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;"FormStyle": "fsStayOnTop",
&nbsp;&nbsp;&nbsp;&nbsp;"Height": 400,
&nbsp;&nbsp;&nbsp;&nbsp;"Left": 1563,
&nbsp;&nbsp;&nbsp;&nbsp;"Top": 577,
&nbsp;&nbsp;&nbsp;&nbsp;"Width": 319,
&nbsp;&nbsp;},
}</pre>
=============
</td></tr></tbody></table>Скрипт<br /><table class="forum-spoiler"><thead onclick="if (this.nextSibling.style.display=='none') { this.nextSibling.style.display=''; BX.addClass(this, 'forum-spoiler-head-open'); } else { this.nextSibling.style.display='none'; BX.removeClass(this, 'forum-spoiler-head-open'); } BX.onCustomEvent('BX.Forum.Spoiler:toggle', [{node: this}]); event.stopPropagation();"><tr><th><div>Скрытый текст</div></th></tr></thead><tbody class="forum-spoiler" style="display:none;"><tr><td>
====code====
<pre>-- если VCLua установлена локально для скрипта
package.cpath=getScriptPath()..'/'.._VERSION:sub(5)..'/?.dll;'..package.cpath
VCL = require "vcl.core"
local app = VCL.Application()
local ProcessMessages = app.ProcessMessages
-- необходимая магическая строка
app:Initialize()
-- если внутри VCLua или в ваших колбэках случится ошибка, вызовется эта функция
local function print_error(s)
&nbsp;&nbsp;message(s,&nbsp;&nbsp;3)
&nbsp;&nbsp;PrintDbgStr(s..'&#92;n'..debug.traceback(nil,2))
end
VCL.SetErrorReporter(print_error)

U = VCL.UTF8
W = VCL.WinCP -- в данном скрипте не используется

local tickers = {
&nbsp;&nbsp;&#91;'MXM5'&#93; = {class='SPBFUT', sec='MXM5'},
&nbsp;&nbsp;&#91;'CRM5'&#93; = {class='SPBFUT', sec='CRM5'},
&nbsp;&nbsp;&#91;'CNYRUB_TOM'&#93; = {class='CETS', sec='CNYRUB_TOM'},
}
local ticker = tickers&#91;'MXM5'&#93;
local depths = {SPBFUT = 20, CETS = 20, TQBR = 10}

local fmt = string.format

local is_run = true

local function Unsub()
&nbsp;&nbsp;local cnt = 0
&nbsp;&nbsp;while not Unsubscribe_Level_II_Quotes(ticker.class,ticker.sec) and cnt&#60;50 do sleep(1); cnt = cnt + 1 end
&nbsp;&nbsp;message(ticker.sec..fmt(' статус подписки %s после %d попыток',IsSubscribed_Level_II_Quotes(ticker.class,ticker.sec),cnt), 1)
end

-- никакого обращения к VCLua не должно быть в колбэках QUIK, если сделали form:Show() в main
function OnStop()
&nbsp;&nbsp;is_run = false
&nbsp;&nbsp;Unsub()
end

require "loader"

local path_prefix = getScriptPaths()

local function FormFilename(sec)
&nbsp;&nbsp;return path_prefix..sec..'.json'
end

-- устанавливает глобальные переменные by_name, form
local function CreateFormStaticPart(sec)
&nbsp;&nbsp;local fn, ok = FormFilename(sec)
&nbsp;&nbsp;ok, form, _, by_name = pcall(jsonFormLoad,fn)
&nbsp;&nbsp;if not ok then
&nbsp;&nbsp;&nbsp;&nbsp;local e1 = form
&nbsp;&nbsp;&nbsp;&nbsp;fn = path_prefix..'quote-example.json'
&nbsp;&nbsp;&nbsp;&nbsp;ok, form, _, by_name = pcall(jsonFormLoad,fn)
&nbsp;&nbsp;&nbsp;&nbsp;if not ok then error(e1..'&#92;n'..form) end
&nbsp;&nbsp;end
end

local function UpdateForm(sec, form)
&nbsp;&nbsp;local fn = FormFilename(sec)
&nbsp;&nbsp;local ok, js = pcall(fileToJson, fn)
&nbsp;&nbsp;if not ok then
&nbsp;&nbsp;&nbsp;&nbsp;local e1 = js
&nbsp;&nbsp;&nbsp;&nbsp;ok, js = pcall(fileToJson, path_prefix..'quote-example.json')
&nbsp;&nbsp;&nbsp;&nbsp;if not ok then error(e1..'&#92;n'..js) end
&nbsp;&nbsp;end
&nbsp;&nbsp;jsonUpdateWithForm(js, form)
&nbsp;&nbsp;jsonToFile(js, fn, table.tojson)
end

-- переменные для связи между потоками скрипта
local cb_t, recv_t = {}, {}


local function CreateForm()
&nbsp;&nbsp;local sec = ticker.sec
&nbsp;&nbsp;CreateFormStaticPart(sec)
&nbsp;&nbsp;-- U чтобы не было кракозябр
&nbsp;&nbsp;form.Caption = ticker.class..'-'..sec..U(' стакан')
&nbsp;&nbsp;form.OnCl ose = function()
&nbsp;&nbsp;&nbsp;&nbsp;OnStop()&nbsp;&nbsp;-- можно убрать и тогда стакан будет сворачиваться на закрытии
&nbsp;&nbsp;&nbsp;&nbsp;return 'caMinimize'
&nbsp;&nbsp;end
&nbsp;&nbsp;local info = getSecurityInfo(ticker.class, ticker.sec)
&nbsp;&nbsp;if info then
&nbsp;&nbsp;&nbsp;&nbsp;-- настраиваем поле ввода цены согласно параметрам инструмента
&nbsp;&nbsp;&nbsp;&nbsp;by_name.ePrice.DecimalPlaces = info.scale
&nbsp;&nbsp;&nbsp;&nbsp;by_name.ePrice.Increment = info.min_price_step
&nbsp;&nbsp;end

&nbsp;&nbsp;local grid = by_name.grid
&nbsp;&nbsp;-- по нажатию левой кнопки мыши на некоторых ячейках стакана поле цены будет меняться
&nbsp;&nbsp;local function setp(c,r)
&nbsp;&nbsp;&nbsp;&nbsp;local price = grid:Cells(c &#60;= 1 and 3 or 4, r)
&nbsp;&nbsp;&nbsp;&nbsp;if price ~= "" then by_name.ePrice.Value = price end
&nbsp;&nbsp;end
&nbsp;&nbsp;local col_funcs = {setp, setp, &#91;7&#93; = setp, &#91;8&#93; = setp}
&nbsp;&nbsp;grid.OnMouseD own = function(_,Button,Shift,X,Y)
&nbsp;&nbsp;&nbsp;&nbsp;local col, row = grid:MouseToCell2(X,Y)
&nbsp;&nbsp;&nbsp;&nbsp;if row == 0 then return end
&nbsp;&nbsp;&nbsp;&nbsp;if Button == "mbLeft" and (col &#60; 2 or col &#62; 5) then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- нумерация в Lua от 1, а в Free Pascal от 0, поэтому col+1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;col_funcs&#91;col+1&#93;(col, row)
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
&nbsp;&nbsp;-- глубина стакана зависит от инструмента и от сервера, + 1 для заголовка
&nbsp;&nbsp;grid.RowCount = depths&#91;ticker.class&#93; + 1
&nbsp;&nbsp;-- некоторые параметры удобнее менять при исполнении, чем искать способ в LCL сделать автоматически как хочется
&nbsp;&nbsp;local function on_change_width()
&nbsp;&nbsp;&nbsp;&nbsp;local mid = form.Width // 2
&nbsp;&nbsp;&nbsp;&nbsp;by_name.eQuantity.Width = by_name.eQuantity.Left - mid + by_name.eQuantity.Width
&nbsp;&nbsp;end
&nbsp;&nbsp;-- вызывается при изменении ширины заголовков, делает ширины симметричными
&nbsp;&nbsp;grid.OnHeaderSi zed = function(o,_,index)
&nbsp;&nbsp;&nbsp;&nbsp;local c = o.Columns
&nbsp;&nbsp;&nbsp;&nbsp;c:Items(c.Count-1-index).Width = c:Items(index).Width
&nbsp;&nbsp;&nbsp;&nbsp;local rect = o:CellRect(o.ColCount-1, o.RowCount-1)
&nbsp;&nbsp;&nbsp;&nbsp;form.Width = rect.right
&nbsp;&nbsp;&nbsp;&nbsp;on_change_width()
&nbsp;&nbsp;end
&nbsp;&nbsp;-- высота стакана подстраивается по нажатию мыши на поле статистики
&nbsp;&nbsp;by_name.stat.OnMouseD own = function(_,Button,Shift,X,Y)
&nbsp;&nbsp;&nbsp;&nbsp;on_change_width()
&nbsp;&nbsp;&nbsp;&nbsp;local rect = grid:CellRect(grid.ColCount-1, grid.RowCount-1)
&nbsp;&nbsp;&nbsp;&nbsp;local h = form.Height + rect.bottom - grid.Height
&nbsp;&nbsp;&nbsp;&nbsp;form.Constraints.MinHeight = h
&nbsp;&nbsp;&nbsp;&nbsp;form.Height = h
&nbsp;&nbsp;end
&nbsp;&nbsp;-- НЕ модально показываем форму, поэтому потребуется регулярный вызов ProcessMessages
&nbsp;&nbsp;form:Show()

&nbsp;&nbsp;local was = IsSubscribed_Level_II_Quotes(ticker.class,sec)
&nbsp;&nbsp;local subscribed = Subscribe_Level_II_Quotes(ticker.class,sec)
&nbsp;&nbsp;local cnt = 0
&nbsp;&nbsp;if subscribed then
&nbsp;&nbsp;&nbsp;&nbsp;while not IsSubscribed_Level_II_Quotes(ticker.class,sec) and is_run do sleep(1); cnt = cnt + 1 end
&nbsp;&nbsp;end
&nbsp;&nbsp;message(sec..fmt(' подписка %s изначально %s после %d попыток',subscribed,was,cnt), cnt &#62; 5 and 3 or 1)

&nbsp;&nbsp;cb_t&#91;ticker.sec&#93; = {sent=0}
&nbsp;&nbsp;recv_t&#91;ticker.sec&#93; = {updates=0,received=0,class=ticker.class,depth=depths&#91;ticker.class&#93;,by_name=by_name}

&nbsp;&nbsp;-- в поле цены ставим цену последней сделки, если есть
&nbsp;&nbsp;local last = getParamEx(ticker.class, sec, "LAST")
&nbsp;&nbsp;if last then by_name.ePrice.Value = tonumber(last.param_value) end
end

local function CloseForm(form, method)
&nbsp;&nbsp;-- при закрытии сохраняем json с обновлениями сохранённых в json свойств
&nbsp;&nbsp;UpdateForm(ticker.sec, form)
&nbsp;&nbsp;-- в середине работы можно вызывать Hide вместо Free; после Hide можно сделать form:Show(), чтобы форма снова стала видимой
&nbsp;&nbsp;form&#91;method&#93;(form)
end

local function CloseAllForms()
&nbsp;&nbsp;CloseForm(form, 'Free')
end

-- никакого обращения к VCLua не должно быть в колбэках QUIK, если сделали form:Show() в main
function OnQuote(class_code, sec_code)
&nbsp;&nbsp;local sent = cb_t&#91;sec_code&#93;
&nbsp;&nbsp;-- сохраняем номер срабатывания колбэка для данного sec_code
&nbsp;&nbsp;if sent then sent.sent = sent.sent + 1 end
end

-- чисто для скорости работы
local sc = VCL.GetCallable('TStringGrid','SetCells')
local BeginUpdate = VCL.GetCallable('TStringGrid','BeginUpdate')
local EndUpdate = VCL.GetCallable('TStringGrid','EndUpdate')
local tointeger = math.tointeger
local getQuoteLevel2 = getQuoteLevel2

-- реализация обновления стакана
local function updateGrid()
&nbsp;&nbsp;local sec = ticker.sec
&nbsp;&nbsp;local recv = recv_t&#91;sec&#93;
&nbsp;&nbsp;local s = cb_t&#91;sec&#93;.sent
&nbsp;&nbsp;local p,pq,q,last,pqs,quantity
&nbsp;&nbsp;-- если номер срабатывания колбэка вырос...
&nbsp;&nbsp;if recv.received &#60; s then
&nbsp;&nbsp;&nbsp;&nbsp;-- ...сохраним новый и обновим стакан
&nbsp;&nbsp;&nbsp;&nbsp;recv.received = s
&nbsp;&nbsp;&nbsp;&nbsp;local depth = recv.depth
&nbsp;&nbsp;&nbsp;&nbsp;local by_name = recv.by_name

&nbsp;&nbsp;&nbsp;&nbsp;local updates = recv.updates + 1
&nbsp;&nbsp;&nbsp;&nbsp;recv.updates = updates
&nbsp;&nbsp;&nbsp;&nbsp;updates = s - updates
&nbsp;&nbsp;&nbsp;&nbsp;-- выводим потери обновлений стакана
&nbsp;&nbsp;&nbsp;&nbsp;by_name.stat.Caption = fmt('%d/%d=%.1f%%',updates,s,updates/s*100)

&nbsp;&nbsp;&nbsp;&nbsp;local grid = by_name.grid
&nbsp;&nbsp;&nbsp;&nbsp;local qt = getQuoteLevel2(recv.class, sec)
&nbsp;&nbsp;&nbsp;&nbsp;pqs = qt.bid
&nbsp;&nbsp;&nbsp;&nbsp;BeginUpdate(grid)
&nbsp;&nbsp;&nbsp;&nbsp;if pqs then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last = tointeger(qt.bid_count)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q = 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local last1 = last + 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = 1,last do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pq = pqs&#91;last1 - i&#93;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p = pq.price
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,3,i,p)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quantity = pq.quantity
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,2,i,quantity)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q = q + tointeger(quantity)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,1,i,q)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if last &#60; depth then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = last1,depth do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,3,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,2,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,1,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;pqs = qt.offer
&nbsp;&nbsp;&nbsp;&nbsp;if pqs then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last = tointeger(qt.offer_count)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q = 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = 1,last do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pq = pqs&#91;i&#93;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p = pq.price
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,4,i,p)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quantity = pq.quantity
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,5,i,quantity)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q = q + tointeger(quantity)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,6,i,q)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if last &#60; depth then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = last+1,depth do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,4,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,5,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc(grid,6,i,'')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;EndUpdate(grid)
&nbsp;&nbsp;end
end

function main()
&nbsp;&nbsp;-- создаём форму в потоке main, а не в основном потоке квика
&nbsp;&nbsp;CreateForm()
&nbsp;&nbsp;while is_run do
&nbsp;&nbsp;&nbsp;&nbsp;-- обновляем стакан
&nbsp;&nbsp;&nbsp;&nbsp;updateGrid()
&nbsp;&nbsp;&nbsp;&nbsp;-- отрисовываем обновление стакана и обрабатываем события
&nbsp;&nbsp;&nbsp;&nbsp;ProcessMessages(app)
&nbsp;&nbsp;&nbsp;&nbsp;sleep(1)
&nbsp;&nbsp;end

&nbsp;&nbsp;CloseAllForms()
&nbsp;&nbsp;-- обрабатываем события закрытия форм
&nbsp;&nbsp;app:ProcessMessages()
end</pre>
=============
</td></tr></tbody></table><br />Файлы на диске расположены так:<br />
====code====
<pre>vcl-quotes&#92;5.3&#92;vcl&#92;core.dll -- это мне для тестов, у вас нету
vcl-quotes&#92;5.4&#92;vcl&#92;core.dll
vcl-quotes&#92;CRM5.json -- эти два файла создаются при исполнении quote-example-json.lua, в зависимости от настроек внутри
vcl-quotes&#92;MXM5.json
vcl-quotes&#92;quote-example.json
vcl-quotes&#92;quote-example.lua
vcl-quotes&#92;quote-example-json.lua</pre>
=============
Все эти json можно загрузить в vt-form и поковыряться. <br />
			<i>18.04.2025 16:03:28, funduk.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message78554/topic9136/</link>
			<guid>http://forum.quik.ru/messages/forum10/message78554/topic9136/</guid>
			<pubDate>Fri, 18 Apr 2025 16:03:28 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
		<item>
			<title>VCLua версия 1.0 для графического интерфейса (GUI) в QUIK</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message78553/topic9136/">VCLua версия 1.0 для графического интерфейса (GUI) в QUIK</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			<B>Скачивание</B><br /><br />Я настоятельно не рекомендую пользоваться Lua 5.3 в квике для скриптов, которые используют много объектов, созданных в DLL, поэтому публично выкладываю пока что только версию для 5.4.<br />Качать её на данный момент можно <noindex><a href="https://github.com/hipBali/vclua-tools/blob/lcl3.2/vt-form/dist54/vcl/core.dll" target="_blank" rel="nofollow">тут</a></noindex> (Download raw file) . На <noindex><a href="https://sourceforge.net/projects/vclua/files/" target="_blank" rel="nofollow">sourceforge</a></noindex> пока что немного более старая версия, хоть и тоже 1.0.<br />Документация к библиотеке см. выше. Можно скачать class reference.<br />Скачать vt-form можно <noindex><a href="https://github.com/hipBali/vclua-tools/blob/lcl3.2/vt-form/dist54/lar/vt-form.zip" target="_blank" rel="nofollow">тут</a></noindex> (Download raw file)<br /><br /><B>Установка VCLua 1.0</B><br /><br />Рекомендуемый вариант -- установка для каждого скрипта отдельно.<br /><ol><li>В папке со скриптом, откуда будет запускаться единственный использующий VCLua 1.0 скрипт, создайте иерархию папок 5.4/vcl и положите внутрь неё файл core.dll.<br /><li>В файле скрипта первой строкой добавьте<br /></ol>
====code====
<pre>package.cpath=getScriptPath()..'/'.._VERSION:sub(5)..'/?.dll;'..package.cpath</pre>
=============
Пример использования в следующем сообщении.<br /><br />Альтернативный вариант, годится, если у вас только один скрипт будет использовать VCLua 1.0, или все ваши гуи скрипты уже отлажены и не ломаются.<br /><ol><li>Создайте скрипт со строкой &quot;message(package.cpath, 1)&quot; и запустите его в квике.<br /><li>В окне сообщений появится строка, по которой можно понять, куда можно положить vcl\core.dll: в любую папку, предшествующую знаку вопроса.<br /><li>Например, при строке &quot;C:\BCS_Work\QUIK_BCS\?.dll;C:\BCS_Work\QUIK_BCS\. .\lib\lua\5.4\?.dll;C:\BCS_Work\QUIK_BCS\loadall.dll;.\?.dll&quot; можно использовать папки C:\BCS_Work\QUIK_BCS, C:\BCS_Work\QUIK_BCS\. .\lib\lua\5.4 (я использую эту) и текущую папку скрипта (.).<br /><li>В выбранной папке создаёте папку vcl и кладёте туда core.dll.<br /></ol>Пример использования в следующем сообщении.<br /><br /><B>Установка vt-form (0.9.2).</B><br /><br /><ol><li>Распакуйте архив vt-form.zip в отдельную папку<br /><li>Сделайте доступным для этой папки core.dll одним из двух вариантов выше.<br /><li>Добавьте main.lua из той папки в квик и запустите в Lua 5.4.<br /></ol>Вообще говоря, это обычный Lua скрипт, не имеющий связи с квиком, поэтому запускать его можно отдельно, если стоит интерпретатор Lua, главное установить core.dll так, чтобы скрипт её видел.<br />После этого можно в командной строке сделать так (если архив распакован в f:\Work\Dev\vt-form\vt-form\src):
====code====
<pre>f:&#92;Work&#92;Dev&#92;vt-form&#92;vt-form&#92;src&#62;c:&#92;Work&#92;Tools&#92;qlua&#92;bin&#92;lua54.exe main.lua</pre>
=============
<br />Если нужно использовать в своих скриптах json, полученный из vt-form, нужно глобально установить в квик Файлы copy.lua, json.lua, и loader.lua:<br /><ol><li>Создайте скрипт со строкой &quot;message(package.path, 1)&quot; и запустите его в квике.<br /><li>В окне сообщений появится строка, по которой можно понять, куда можно положить эти три файла: в любую папку, предшествующую знаку вопроса.<br /><li>Например, при строке &quot;C:\BCS_Work\QUIK_BCS\lua\?.lua;C:\BCS_Work\QUIK_BCS\lua\?\init.lua;C:\BCS_Work\QUIK_BCS\?.lua;C:\BCS_Work\QUIK_BCS\?\init.lua;C:\BCS_Work\QUIK_BCS\. .\share\lua\5.4\?.lua;C:\BCS_Work\QUIK_BCS\. .\share\lua\5.4\?\init.lua;.\?.lua;.\?\init.lua&quot; их можно положить в папки C:\BCS_Work\QUIK_BCS\lua, C:\BCS_Work\QUIK_BCS, C:\BCS_Work\QUIK_BCS\. .\share\lua\5.4 (у меня они тут) или в текущю папку скрипта (.).<br /></ol>Пример использования в следующем сообщении. <br />
			<i>18.04.2025 15:51:17, funduk.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message78553/topic9136/</link>
			<guid>http://forum.quik.ru/messages/forum10/message78553/topic9136/</guid>
			<pubDate>Fri, 18 Apr 2025 15:51:17 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
		<item>
			<title>VCLua версия 1.0 для графического интерфейса (GUI) в QUIK</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message78552/topic9136/">VCLua версия 1.0 для графического интерфейса (GUI) в QUIK</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			Сразу предупрежу, использовать GUI в QUIK через сторонние библиотеки -- это не для нубов &nbsp;<img src="http://forum.quik.ru/upload/main/smiles/5/icon_wink.png" border="0" data-code=":wink:" data-definition="SD" alt=":wink:" style="width:16px;height:16px;" title="Шутливо" class="bx-smile" /> <br />Откуда качать, как устанавливать и примеры кода -- в следующих двух сообщениях.<br /><br /><br />VCLua - это название графической библиотеки для Lua.<br /><br />У неё есть несколько версий и они все между собой не совместимы (то есть код на Lua, годящийся для создания GUI с использованием одной из версий VCLua типа 0.5, 0.6.2, 0.9.2 и 1.0, не будет работать с другой версией VCLua). Причины этого среди прочего в том, что разные версии VCLua используют внутри разные версии LCL - графической библиотеки для Free Pascal.<br /><br />Я значительно расширил VCLua 0.9.2, почти полностью переписав, и зарелизил <noindex><a href="https://github.com/hipBali/vclua" target="_blank" rel="nofollow">версию 1.0.0</a></noindex>, использующую LCL 3.2. Общие принципы программирования остались те же.<br /><br />Последние полгода она стабильно работает на QUIK 11 и 12 под Lua 5.4.<br /><br />Я использую для рисования стаканов<br /><br />[FILE ID=12542]<br /><br />и управления скриптом<br /><br />[FILE ID=12541]<br /><br /><br />Доступна очень подробная <noindex><a href="https://github.com/hipBali/vclua?tab=readme-ov-file#documentation" target="_blank" rel="nofollow">документация</a></noindex>, но она на английском и про добавление GUI в отдельностоящий скрипт на Lua, про QUIK там ни слова.<br /><br />Есть графическая утилита для рисования формы <noindex><a href="https://github.com/hipBali/vclua-tools/tree/lcl3.2/vt-form" target="_blank" rel="nofollow">vt-form</a></noindex>, которую потом можно сохранить в json и использовать (в т.ч. менять) в своих скриптах.<br /><br />Здесь я попытаюсь дополнительно задокументировать на русском то, что важно для программирования GUI через VCLua 1.0 для QUIK.<br /><br /><ol><li>Библиотека основана на визуальных контролах LCL 3.2, поэтому всю документацию этих контролов следует искать в <noindex><a href="https://dsiders.gitlab.io/lazdocsnext/lcl/index.html" target="_blank" rel="nofollow">документации к LCL</a></noindex> (для более новой версии, чем 3.2), а не в документации к VCLua. Однако то, какие из этих контролов доступны, и какие их поля и методы доступны, как их вызывать из Lua, следует искать в <noindex><a href="https://github.com/hipBali/vclua/blob/lcl3.2/docs/vclua_ref.html" target="_blank" rel="nofollow">class reference</a></noindex> (нажмите Download raw file) к VCLua. Как контролы выглядят и что делают их поля, можно вживую увидеть или в <noindex><a href="https://github.com/hipBali/vclua-tools/tree/lcl3.2/vt-form" target="_blank" rel="nofollow">vt-form</a></noindex>, или установив <noindex><a href="https://www.lazarus-ide.org/" target="_blank" rel="nofollow">Lazarus</a></noindex>, или почитав <noindex><a href="https://wiki.freepascal.org/" target="_blank" rel="nofollow">вики по free pascal</a></noindex><br /><li>LCL уже давно использует кодировку символов UTF8, в отличие от ранних версий VCLua и в отличие от QUIK, который до сих пор на 1251. Поэтому, чтобы видеть русские символы в VCLua, нужно конвертировать из квиковской 1251 в UTF8 с помощью функции VCL.UTF8. Обратно через VCL.WinCP, что нужно, например, для сохранения файлов, путь к которым получен из диалога VCLua.<br /><li>Если у вас несколько скриптов будут использовать VCLua, то лучше использовать разные файлы core.dll. В противном случае после закрытия одного из скриптов вы не сможете его запустить второй раз, пока не закроете все остальные скрипты (и тем самым не выгрузите библиотеку core.dll из памяти). Также при использовании одного файла core.dll есть ограничение на то, что главные формы разных скриптов должны иметь разные названия (у всех компонентов LCL есть внутренние названия).<br /><li>LCL является однопоточной библиотекой, а скрипты в квике как минимум двухпоточные. Поэтому, чтобы избежать падений VCLua, а вместе с ней и квика, следует обновлять GUI только из того же потока, где была запущена основная форма. Начиная с версии VCLua 1.0 стало возможным запускать GUI из потока квика main вместо главного потока. Я делаю только так, вариант со стартом в главном потоке квика не тестирую. В частности, я не пытался стартовать GUI из кода индикатора, но это возможно.<br /><li>Необдуманная установка обработчиков событий может привести к <noindex><a href="https://github.com/hipBali/vclua/blob/lcl3.2/docs/README.md#implementation-details" target="_blank" rel="nofollow">утечкам памяти и падениям скрипта</a></noindex>, особенно если устанавливать их из разных потоков.<br /><li>В документации большой <noindex><a href="https://github.com/hipBali/vclua/blob/lcl3.2/docs/README.md#error-handling" target="_blank" rel="nofollow">раздел</a></noindex> посвящён тому, как обрабатывать ошибки при использовании библиотеки и почему для этого нельзя использовать GUI самой библиотеки. Для квика я во всех скриптах использую один и тот же код как в примере стакана ниже.<br /><li>Размер dll 6.7 мегабайт, все LCL dll большие. Даже если вы выкинете из библиотеки те контролы, которые вы не используете, и перекомпилируете, сильно меньше она не станет.<br /></ol> <br />
			<img src="https://forum.quik.ru/bitrix/components/bitrix/forum.interface/show_file.php?fid=12541&" width="1163" height="879" /><br /><img src="https://forum.quik.ru/bitrix/components/bitrix/forum.interface/show_file.php?fid=12542&" width="2257" height="1971" /><br /><i>18.04.2025 15:42:53, funduk.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message78552/topic9136/</link>
			<guid>http://forum.quik.ru/messages/forum10/message78552/topic9136/</guid>
			<pubDate>Fri, 18 Apr 2025 15:42:53 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
	</channel>
</rss>
