<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=396502&amp;view=findpost&amp;p=3545405</guid>
        <pubDate>Mon, 17 Nov 2014 08:06:52 +0000</pubDate>
        <title>Заменитель Format без SysUtils</title>
        <link>https://forum.sources.ru/index.php?showtopic=396502&amp;view=findpost&amp;p=3545405</link>
        <description><![CDATA[Fr0sT: <strong class='tag-b'><span class="tag-color tag-color-named" data-value="purple" style="color: purple"><span class='tag-size' data-value='14' style='font-size:14pt;'>Format без SysUtils</span></span></strong><br>
<br>
Сразу оговорюсь, что это не полный аналог Format, с немного другим синтаксисом (несовместимым - можно применять, если все строки форматирования находятся внутри программы). Используется системная функция <strong class='tag-b'>FormatMessage</strong>. Поддерживаются подстановки строк, целых и pointer-to-hex; поддерживаются спецификаторы ширины и точности. Вещественные числа, региональные установки - не поддерживаются.<br>
<br>
<strong class='tag-b'>Код</strong><br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// Частично позаимствовано из SysUtils.SysErrorMessage</div><div class="code_line">function FormatWinapi(const Patt: string; const Args: array of const): string;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Buffer: PChar;</div><div class="code_line">&nbsp;&nbsp;Len, i: Integer;</div><div class="code_line">&nbsp;&nbsp;InternalArgs: array of Pointer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;SetLength(InternalArgs, Length(Args));</div><div class="code_line">&nbsp;&nbsp;for i := Low(InternalArgs) to High(InternalArgs) do</div><div class="code_line">&nbsp;&nbsp; &nbsp;InternalArgs[i] := Pointer(Args[i].VPointer);</div><div class="code_line">&nbsp;&nbsp;Len := FormatMessage(</div><div class="code_line">&nbsp;&nbsp; &nbsp;FORMAT_MESSAGE_FROM_STRING or</div><div class="code_line">&nbsp;&nbsp; &nbsp;FORMAT_MESSAGE_ARGUMENT_ARRAY or</div><div class="code_line">&nbsp;&nbsp; &nbsp;FORMAT_MESSAGE_ALLOCATE_BUFFER, PChar(Patt), 0, 0, @Buffer, 0, Pointer(InternalArgs));</div><div class="code_line">&nbsp;&nbsp;try</div><div class="code_line">&nbsp;&nbsp; &nbsp;{ Convert to Delphi string }</div><div class="code_line">&nbsp;&nbsp; &nbsp;SetString(Result, Buffer, Len);</div><div class="code_line">&nbsp;&nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp;{ Free the OS allocated memory block }</div><div class="code_line">&nbsp;&nbsp; &nbsp;LocalFree(HLOCAL(Buffer));</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
<strong class='tag-b'>Применение</strong><br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp;MemLog.Lines.Add(FormatWinapi(&#39;Мама мыла %1.%nВымыто %2!.2d!%%.%nApplication находится по адресу %3!p!.&#39;, [&#39;раму&#39;, 9, Application]));</div></ol></div></div></div></div><br>
<br>
<strong class='tag-b'>Результат</strong><br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">Мама мыла раму.</div><div class="code_line">Вымыто 09%.</div><div class="code_line">Application находится по адресу 7EF49E00.</div></ol></div></div></div></div><br>
<br>
<span class='tag-size' data-value='12' style='font-size:12pt;'><strong class='tag-b'>Обработка ошибок</strong></span><br>
Функция FormatMessage возвращает 0 при ошибке, код ошибки получается через GetLastError. Поскольку мы избавляемся от SysUtils, никаких классов исключений не объявлено, и rais-ить ошибку мы не можем. Варианты решения:<br>
1) Проверять GetLastError после вызова FormatWinapi.<br>
2) Проверять результирующую строку после вызова FormatWinapi (при ошибке она будет пуста).<br>
3) Создать собственный класс Exception и rais-ить его.<br>
<br>
<strong class='tag-b'>Инфо</strong>:<br>
<a class='tag-url' href='http://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx' target='_blank'>FormatMessage</a><br>
<a class='tag-url' href='http://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx' target='_blank'>printf Type Field Characters</a>]]></description>
        <author>Fr0sT</author>
        <category>Все языки: Статьи, заготовки в FAQ</category>
      </item>
	
      </channel>
      </rss>
	