1. Пользуйтесь тегами кода. - [code] ... [/code] 2. Точно указывайте язык, название и версию компилятора (интерпретатора). 3. Название темы должно быть информативным. В описании темы указываем язык!!!
Если в Дельфи исключения реализованы поверх SEH (а никакой причины не сделать этого я не вижу, система строго завязана под одну ОС, чего б не использовать везде только структурные исключения, если других-то и не может быть?), то все будет работать, разумеется... С другими языками - особенно с теми, которые работают не только на одной-единственной ОСи будет проблема. Естественно, что Ada exceptions не имеют к SEH никакого отношения, поэтому облом с ловлей исключений, выброшенных в CallBack-е.
with Ada.Exceptions; use Ada.Exceptions; with Ada.Task_Termination; use Ada.Task_Termination; with Ada.Task_Identification; use Ada.Task_Identification;
package Err is
protected End_Of is procedure World(C : Cause_Of_Termination; T : Task_ID; X : Exception_Occurrence); end End_Of;
end Err;
+
with Ada.Exceptions; with Ada.Text_IO;
package body Err is
protected body End_Of is procedure World(C : Cause_Of_Termination; T : Task_ID; X : Exception_Occurrence) is My_File : ada.Text_IO.File_Type; begin case C is when Normal => null; when Abnormal => Ada.Text_IO.Put_Line ("Abnormal termination of Task" & Image(T)); when Unhandled_Exception => Ada.Text_IO.Create(My_File, Ada.Text_IO.Out_File, "My.txt"); Ada.Text_IO.Put_Line (My_File, "Unhandled exception in Task : " & Image(T)); Ada.Text_IO.Put_Line (My_File, Exception_Information(X)); Ada.Text_IO.Put_Line (My_File, "End logging"); Ada.Text_IO.Close (My_File); end case;
end World; end End_Of;
end Err;
(Исправил на вывод в файл, иначе могут быть проблемы с запуском вне среды)... Что это дает?
Подключаешь этот пакет, и в самом начале основной процедуры:
with Err; use Err; with Ada.Task_Termination;
procedure Main is -- ... begin Ada.Task_Termination.Set_Dependents_Fallback_Handler(End_Of.World'Access); -- ...
Вот сейчас специально нашел машину с Windows XP, запустил там программу, которая из WndProc бросает исключение (то самое деление на 0). Вот чего показывает:
N:\Just_Test\debug\main Unhandled exception in Task : main_task_003E4008 Exception name: CONSTRAINT_ERROR Message: wndproc.adb:59 divide by zero Call stack traceback locations: 0x401e99 0x401f08 0x7e418732 0x7e418814 0x7e4189cb 0x7e4196c5 0x401e1d 0x4017a6 0x401235 0x4012a6 0x7c817075
End logging
, ну а потом программа благополучно рушится... То есть, что-то типа старой доброй паскалевской ExitProc. Сделать вроде ничего уже нельзя, но зато получить информацию о том, что произошло - можно... Для логирования - в самый раз...
P.S. В случае Ады проблем еще, похоже, добавляет GCC. Погугли на тему +"windows callback" +exceptions, и на тему dwarf2 vs sjlj exceptions
1. Зачем помимо INT ввели тип LONG, который от -2**31 до 2**31-1? В чём прикол?
2. У меня, например, есть функция. Принимает массив, который может быть ооочень длинным. Массив может быть передан в функцию либо сразу, как переменная, либо как результат вычисления выражения, либо как агрегат, то есть нужен именно in-параметр. Внутри функции над массивом производятся какие-то операции. Над самим параметром операции запрещены, поэтому первой строчкой функции стоит копирование copy_a: arr := a; Понятно, что если массив передаётся из переменной, то тут явно происходит то, что в Паскале делалось неявно. Но если массив передаётся как результат вычислений, то он изначально сидит на стеке, и если внутри функции все операции делаются с copy_a (а изначальное a даже не упоминается), то делать копирование из стека в стек просто бессмысленно. Умеет ли компилятор убирать копирование в таких случаях?
3. Агрегат при передаче в функцию не работает, если внутри только 1 параметр. f((a)) - это вызов функции от числа (a) или от массива (a)? Вот компилятор и запрещает так передавать 1-элементные массивы. Но если у разработчиков языка явно была клавиатура только с одним типом скобочек, то сейчас у всех есть [ и ], которые можно разрешить применять для агрегатов. f(a) - передача числа, f([a]) - передача 1-элементного массива, f((a)) - неопределённость, запретить, не нужна.
4. Подобно очень опасной описке в С между == и =, в Аде есть очень опасная возмжность написать and вместо and then, "благодаря" которой будет выполняться то, что выполняться не должно. Это серьёзный изъян языка. Зачем для операции, которая нафиг не нужна в большей части случаев (вычисление выражения по полной схеме), оставили привычную запись, а для реально нужной операции сделали непривычную и длиную запись? Почему бы не оставили and и or для неполного вычисления, а для полного сделали бы, например, and necessarily и or necessarily?
5. Тот код из архива занимает 100 кб, но компилируется в мегабайт. В этом мегабайте последние 2/3 - это чистый текст. Как его скомпилировать в более приемлемый размер?
1. Зачем помимо INT ввели тип LONG, который от -2**31 до 2**31-1? В чём прикол?
Ввели все типы, которые описаны в "Interfaces.C".
С типом Long_Integer вообще отдельная история, на разных системах у него может быть разная разрядность, поэтому он стоит особняком. Видимо, поэтому его и в Win32Ada добавили особняком. Опять же, грядет переход на 64-бита, кто знает, что там с long-ом будет...
Цитата
Умеет ли компилятор убирать копирование в таких случаях?
По крайней мере, должен уметь. Если не умеет - надо сообщать об этом, как о баге.
Цитата
Агрегат при передаче в функцию не работает, если внутри только 1 параметр
Угу. Давай договоримся, что если кто-то не умеет передавать одно значение через агрегат - это ни разу не проблема языка:
type T is array (Positive range <>) of integer; procedure Foo (arr : T) is begin for i in arr'Range loop Ada.Text_IO.Put_Line (Integer'Image (arr (i))); end loop; end Foo;
-- ... Foo (arr => (1 => 1)); -- Что-то не так?
Лишние скобки не нужны, не надо язык превращать в Perl...
Цитата
Зачем для операции, которая нафиг не нужна в большей части случаев (вычисление выражения по полной схеме), оставили привычную запись, а для реально нужной операции сделали непривычную и длиную запись?
С точки зрения англоязычного программиста как раз запись if A > 0 and then Arr (A) = Value then является более наглядной. "Выполнять второе действие только тогда, когда первое выполнилось". Аналогично и с or else. А то, что другой язык программирования приучил программиста писать and везде - это опять же не проблемы Ады.
Цитата
Тот код из архива занимает 100 кб, но компилируется в мегабайт. В этом мегабайте последние 2/3 - это чистый текст. Как его скомпилировать в более приемлемый размер?
> С точки зрения англоязычного программиста как раз запись if A > 0 and then Arr (A) = Value then является более наглядной. "Выполнять второе действие только тогда, когда первое выполнилось". Аналогично и с or else.
А запись if (f(A) > 0) and necessarily (g(A) > 0) тоже тогда наглядна - вычислять второе условие обязательно.
> А то, что другой язык программирования приучил программиста писать and везде - это опять же не проблемы Ады.
Опасность в том, что можно случайно забыть одно слово и получить некорректный код (полный аналог "случайно забыть один символ и..."). Да, в варианте с necessarily тоже опасность есть, что забудешь слово, и что-то не будет выполняться, но проявляться она будет намного реже, поскольку схема полного вычисления выражения нужна крайне редко (мне вообще никогда не пригождалась). Логично же для более частого случая применять более короткую запись, чтобы случайно не написать экзотический вариант.
, от размера осталась едва ли треть (275К). Из IDE это делается Switches -> Ada Linker -> (включить) Strip symbols в свойствах проекта.
Кстати, откомпилировал твой проект со всеми Warning-ами (в свойствах - кнопка Warnings, и щелкнуть на Activate every optional warning) - у меня от оранжевого аж в глазах зарябило. Там и предупреждения о лишних with/use, и о том, что типы не надо подключать, они уже подключены и ты делаешь двойную работу, и то, что неизменно в ходе процедуры/функции и можно его описать как constant... Боюсь даже включать Style Check...
> Кстати, откомпилировал твой проект со всеми Warning-ами
Так там по умолчанию не все включены?
> (в свойствах - кнопка Warnings, и щелкнуть на Activate every optional warning)
Блин, точно, есть такое подменю в том подменю.
> Там и предупреждения о лишних with/use, и о том, что типы не надо подключать, они уже подключены и ты делаешь двойную работу, и то, что неизменно в ходе процедуры/функции и можно его описать как constant...
В общем, включил я ВСЕ предупреждения. И выключил.
"Внимание: к формальному параметру нет обращения". То есть он какбэ предлагает мне убрать параметр из заголовка функции. Куда я его уберу, это функция для подстановки в качестве параметра функционального типа.
"Осторожно, к переменной после присваивания нет обращений". А шо робыть, если эта функция зачем-то возвращает не нужное мне значение, которое надо непременно куда-то записать.
Всё-таки, какие предупреждения надо поставить, а какие не надо?
Ещё вопрос: в модуле Parser.ads как функцию Val_Number (ну которая используется в Do_Function и Do_Func_List) перенести в параметры шаблона? А то она принимает Key_Arr, а он задан как тип, производный от того, что идёт в параметрах шаблона, то есть описать его до функции Val_Number нельзя.
То есть он какбэ предлагает мне убрать параметр из заголовка функции.
Нет, он предлагает тебе либо убрать параметр из заголовка, либо отключить выдачу предупреждения:
pragma Warnings (Off, "formal parameter ""lParam"" is not referenced"); pragma Warnings (Off, "formal parameter ""wParam"" is not referenced"); procedure Block( hWnd : in out Win32.Windef.HWND; Msg : in out Win32.UINT; wParam : in out Win32.WPARAM; lParam : in out Win32.LPARAM; Result : out Win32.LRESULT; Continue : out boolean) is pragma Warnings (On, "formal parameter ""lParam"" is not referenced"); pragma Warnings (On, "formal parameter ""wParam"" is not referenced"); begin Result := 0; Continue := False; end;
Цитата
"Осторожно, к переменной после присваивания нет обращений". А шо робыть, если эта функция зачем-то возвращает не нужное мне значение, которое надо непременно куда-то записать.
А вот тут есть 2 пути. Либо предупредить компилятор, что это особенность библиотеки (работа с функциями, которые все-таки должны вернуть результат) и на результат не надо обращать внимания, либо работать с определенными вещами не как с функциями, а как с процедурами.
По варианту №1: ты в файле wintestmain.adb внутри функции Graph используешь API-шную функцию SetPixel, из-за чего тебе нужна "лишняя" переменная С типа COLORREF, так? Можно сделать вот так:
function Graph(Func: Parsed_Function) return boolean is
procedure SetPixelProc (hDC : Win32.Windef.HDC; X : Win32.INT; Y : Win32.INT; crColor: Win32.Windef.COLORREF); pragma Import (StdCall, SetPixelProc, "SetPixel");
-- ... Дальше всё как было, но вместо обращения к функции SetPixel -- будет обращение к процедуре SetPixelProc - переменная С уже не нужна.
По варианту №2:
function Graph(Func: Parsed_Function) return boolean is
Всё-таки, какие предупреждения надо поставить, а какие не надо?
Все-таки, я бы оставил все...
Чуть позже закончу перевод очередных обзоров с AdaCore, один из них касается именно работы с предупреждениями, ссылку запощу сюда.
Цитата
А то она принимает Key_Arr, а он задан как тип, производный от того, что идёт в параметрах шаблона
Проблема не в этом. Проблема - в том, что тебе для того, чтобы получить тип Key_Arr, надо инстанцировать другой шаблонный модуль. Это невозможно сделать при описании параметров настройки.
Ещё такой момент: если включить галочки в Validiting Checking Mode, то программа падает при запуске на строчке NAN: constant f80 := Get_NAN;
Угу. Значит, включай все, кроме "Floating Point Values" (эта галка добавляет ключ gnatVf, при наличии которого любое действие с вещественными числами проверяется на валидность, а NaN - это невалидный результат операции)
Цитата
Дальше, проверка стиля. Ругается на то, что я выравниваю двоеточия табами. Как надо? Пробелы мне не нравятся.
Табами оно тем более не разрешит (если включено "No horizontal tabs"). Мы выравниваем пробелами. Все остальное не проходит проверку.
Цитата
"слишком длинная линия" Это он про комментарий из 70 русских букв, который он посчитал за 140.
Разбей на 2 строки, по 35 символов.
Цитата
Чисто внутренняя подпрограмма же, зачем мне её описывать
Потому что положено. Причем в алфавитном порядке. Если ты не сделаешь этого - это сделает сам компилятор, но Style Checker об этом ничего знать не хочет, он тебя предупреждает, что прототип подпрограмма не описан.
Цитата
Ещё несколько предупреждений внутри стандартного (не моего) пакета. Что делать?
Либо исправить и пересобрать стандартные пакеты, либо не обращать внимания.
Цитата
"неявное разыменование" В смысле?
В смысле,
Form.ID := To_HMENU(integer(LastID));
это неправильная запись. Правильно (и это сделает сам компилятор) - вот так:
> Проблема не в этом. Проблема - в том, что тебе для того, чтобы получить тип Key_Arr, надо инстанцировать другой шаблонный модуль. Это невозможно сделать при описании параметров настройки.
А как выкручиваться-то?
Ещё компилятор выдаёт предупреждение, если Initialize-Finalize-Adjust находятся в private -части ads файла. Что определение этой процедуры перекрывает определение на линии, где я объявил тип.
Ты ж выкрутился. Зачем тебе выносить эту функцию в параметры шаблона, расскажи? Как ты ее описывать собрался? Вот просто пример приведи, неважно, пускай некомпилируемый, как ты хочешь чтоб это работало...
Цитата
Ещё компилятор выдаёт предупреждение, если Initialize-Finalize-Adjust находятся в private -части ads файла. Что определение этой процедуры перекрывает определение на линии, где я объявил тип.
Насколько я помню, так себя ведет только GNAT, по этому поводу даже есть открытый баг в бегтрекере. Aonix ObjectAda не вякает по этому поводу. Тут есть 2 замечания: во-первых, если ты создаешь новый тип, первый в иерархии (то есть, наследуешься от Ada.Finalization.Controlled, а не от его потомка), то всегда добавляй перед прототипом описатель overriding. Во-первых, это поможет поймать опечатки, по-вторых, ты ясно указываешь компилятору, что тебе не надо перегружать функции, а надо именно заменить. И тогда предупреждение можно отключать
Во-вторых, чего не указываешь, что type Parsed_Function is tagged private; ? Он же теговый, поскольку наследуется от Controlled, который сам по себе теговый. Не, я понимаю, что компилятор сам это добавит (как и virtual в С++, если ты забыл случайно описать функцию как виртуальную в наследнике, когда у предка эта функция уже была виртуальна), но все-таки лучше делать это программисту, с первого взгляда должно быть видно, что за тип, в твоем случае этого не видно.
А вообще эта проблема (предупреждения при описании этих трех процедур в приватной части) растет вот отсюда: если у тебя есть нетэговый тип, то может быть вот такая заморочка (пример приводил Adam Beneschan)
package Pack2 is type T2 is new Pack1.T; -- для типа описана операция/процедура Op -- Естественно, T2 наследует Op
private overriding procedure Op (X : T2); end Pack2;
Теперь в зависимости от того, где будет вызываться T2.Op (в смысле, видима ли там приватная часть модуля Pack2 или нет) под P2.Op может подразумеваться разная функциональность. Где-то унаследованная от T1.Op, где-то - переопределенная.
Возможно поэтому компилятор при попытке описания функционала для потомков в приватной части (которая может быть не для всех видимой) ругается Warning-ами, не обращая особого внимания на то, где описан сам тип. Но это в любом случае баг.
Круто, теперь у моего разборщика выражений есть новый функционал: я могу в один и тот же разборщик подсовывать разные функции преобразования строки в число! (ирония)
> Вот просто пример приведи, неважно, пускай некомпилируемый, как ты хочешь чтоб это работало...
generic type Key_Base is (<>); type Number is private; type Key_Arr will be declared; -- как-то так with function Val_Number(Expression: Key_Arr; Position: access integer; V: access Number) return boolean; package Parser is ...
Ещё: "Info: instantiation of SMTH during elaboration. Implicit pragma Elaborate_All for SMTH generated."
Если после with module; use module; ещё вписать pragma Elaborate_All(module), то предупреждение и счезает, но появляется ошибка о циклической элаборации. Это надо как-то обходить, или воспринимать, как изъян архитектуры модулей?
Код
error: elaboration circularity detected info: "winapi.strings (body)" must be elaborated before "winapi.strings (body)" info: reason: pragma Elaborate_All in unit "winapi.strings (body)" info: "winapi.strings (body)" info: must be elaborated along with its spec: info: "winapi.strings (spec)" info: which is withed by: info: "winapi (body)" info: which must be elaborated along with its spec: info: "winapi (spec)" info: which is withed by: info: "winapi.conversions (spec)" info: which is withed by: info: "winapi.strings (body)"
gnatmake: *** bind failed.
Особенно вот это место:
"winapi (spec)" info: which is withed by: info: "winapi.conversions (spec)"
У меня в WinAPI.Strings не написано with WinAPI.
Иерархия такая:
WinAPI WinAPI.Strings WinAPI.Converstions
Каждый модуль использует то и только те, что ниже него в списке.
generic type Key_Base is (<>); type Key_Arr is array (Positive range <>) of Key_Base; type Number is private; with function Val_Number(Expression: Key_Arr; Position: access integer; V: access Number) return boolean; package Parser is -- ...
и звать так:
type Char_Arr is array (Positive range <>) of Character; function My_Func (Expression : Char_Arr; Position : access Integer; V : access f80) return Boolean is begin -- ... end My_Func;
package f80_Parser is new Parser(Character, Char_Arr, f80, My_Func); use f80_Parser;
Тогда тип Key_Arr из пакета Dictionaries не нужно создавать, его можно сразу передавать в пакет, уже готовый. Понимаешь, в чем тут проблема, да? В том, что тебе для описания функции My_Func (еще до инстанцирования шаблона) нужен тип-массив. Вот в нем и проблема... В принципе, все стандартные контейнеры поступают подобным образом: получают извне и тип элементов, и тип-индекс, и тип-массив. Если бы можно было сделать так, как ты хочешь - тип-массив однозначно был бы описан внутри шаблона. Но, увы, это невозможно.
Цитата
Если после with module; use module; ещё вписать pragma Elaborate_All(module), то предупреждение и счезает, но появляется ошибка о циклической элаборации. Это надо как-то обходить, или воспринимать, как изъян архитектуры модулей?
Взял твой код, вписал туда Elaborate_All всего в двух файлах, в трех местах:
1)
with Parser; pragma Elaborate_All (Parser);
(файл func_lib.ads) 2)
with Func_Lib; pragma Elaborate_All (Func_Lib); use Func_Lib; with WinAPI.Bitmaps; pragma Elaborate_All (WinAPI.Bitmaps); use WinAPI.Bitmaps;
(файл wintestmain.adb) , и полностью пересобрал программу (то есть, совсем полностью, удалил все, что было в папке, все *.o, *.ali, *.exe и сделал Build All). Ни одного предупреждения, связанного с элаборацией больше не присутствует. Не надо во всех модулях. где были Warning-и, это делать сразу. Исправляй ошибки/предупреждения по мере их поступления. Так что никакого изъяна в архитектуре нет...
1. От предупреждений я, вроде как, избавился. Правда, при включённой оптимизации ругается на конверсию LPARAM в PRECT. Что делать?
2. Стандартные вектора мне не понравились тем, что в них почему-то нет именно тех операций, которые мне нужны. Простейшие действия превращаются в пляски с бубном. Короче, я забил и свелосипедил.
3. В среде вкладочка Project View полезна, но как сделать так, чтобы она не показывала локальные подпрограммы в одном списке с глобальными, чтобы она иерархию подпрограмм показывала в виде дерева?
4. Если код имеет ошибки, то я вообще не понял, по какому принципу выбирается место, где они показываются, по-моему, по абсолютно случайному. Я ошибся в модуле A, компилятор показывает на ошибку в модуле B, использующем модуль A. Я поначалу долго думал, потом понял, что надо сразу свернуть все ошибки, найденный в модуле B и сразу смотреть на модуль A.
5. Напрягает, что навигация по модулям работает только после корректной компиляции проекта. А если я хочу залезть внутрь того модуля именно для того, чтобы дописать в него кое-что, что сделает проект компилирующимся? Что делать? Ааа, файл-открыть-папка вверх-папка с проектами-ещё одна папка-ой не туда, где же этот модуль-а, другая папка-о, наконец-то открыл.
6. Я так и не понял, как подружить отладочные пулы с объектами, живущими в глобальной области видимости. Ведь они умирают только при закрытии приограммы, а вывод утечек происходит до этого. Поэтому опять пришлось совершать извращение.
7. Стиль кода я не правил вообще. И делать это вручную не собираюсь. Есть автоматика для этого?
8. Как сделать программе иконку?
Пока что вышло вот это:
(правда, такие приколы уж очень медленно считаются).
1. От предупреждений я, вроде как, избавился. Правда, при включённой оптимизации ругается на конверсию LPARAM в PRECT. Что делать?
От этого предупреждения нельзя избавляться ни в коем случае (в смысле, глушить его), и просто не обращать внимания - тоже. Это может привести к серьезным проблемам. В частности, в доках на Gnat Pro приведен такой
пример(Показать/Скрыть)
-- Первый модуль package p1 is type int1 is new integer; type int2 is new integer; type a1 is access int1; type a2 is access int2; end p1;
with p1; use p1; package p2 is function to_a2 (Input : a1) return a2; end p2;
-- Второй модуль with Unchecked_Conversion; package body p2 is function to_a2 (Input : a1) return a2 is function to_a2u is new Unchecked_Conversion (a1, a2); begin return to_a2u (Input); end to_a2; end p2;
-- Программа with p2; use p2; with p1; use p1; with Text_IO; use Text_IO; procedure m is v1 : a1 := new int1; v2 : a2 := to_a2 (v1); begin v1.all := 1; v2.all := 0; put_line (int1'image (v1.all)); end;
В режимах -O0 и -O1 этот код печатает 0, в режиме -O2 будет напечатана 1-ца... Разумеется, будет показано и это же самое предупреждение.
Так что тебе надо либо включать pragma No_Strict_Aliasing для типа PRECT, либо в список ключей компиляции добавить -fno-strict-aliasing (я выбираю именно этот вариант), если выбрана оптимизация второго уровня и выше:
(просто допечатай это к списку ключей и пересобери проект, этого достаточно)
Цитата
3. В среде вкладочка Project View полезна, но как сделать так, чтобы она не показывала локальные подпрограммы в одном списке с глобальными, чтобы она иерархию подпрограмм показывала в виде дерева?
Никак. Это не предусмотрено. Задача у этого окна - не показывать, какая функция в какую вложена, а быстро просмотреть, какие сущности (модули, типы, переменные) описаны в файле. Для удобства такого просмотра список сущностей просто сортируется по алфавиту. Ну, или можно озадачиться и самому написать подобное окошечко, в котором будет нужный функционал. На Python-е.
Цитата
5. Напрягает, что навигация по модулям работает только после корректной компиляции проекта.
Это то есть как? Я вот только что взял проект ,который вообще не компилировал на домашней машине, открыл его, и даже до компиляции в нем прекрасно работает навигация по модулям. Хотя, я не знаю, какой ты смысл вкладываешь в понятие навигация. То, что можно в Project View видеть все папки, связанные с проектом, и открыть любой модуль, который находится в одной из этих папок - это факт. Повторяю: еще вообще до компиляции.
Цитата
7. Стиль кода я не правил вообще. И делать это вручную не собираюсь. Есть автоматика для этого?
Естественно. Закрываешь все файлы редактора, заходишь в Tools -> Consoles -> OS Shell, и в полученном окошке набираешь команду gnat pretty -rf F:\Programs\Ada\forum\main.adb (со своим файлом, разумеется). Потом открываешь обработанный файл в редакторе, и смотришь на разницу... Но сначала "потренируйся на кошках" (С), у тебя есть директивы препроцессора #if/#end, я не знаю, как Pretty Printer себя с ними поведет. Без него работает прекрасно:
> Так что тебе надо либо включать pragma No_Strict_Aliasing для типа PRECT, либо в список ключей компиляции добавить -fno-strict-aliasing (я выбираю именно этот вариант), если выбрана оптимизация второго уровня и выше:
Тогда данный вид оптимизации угробится во всём проекте? Включить прагму для одного типа я не могу, так как он определён в не моём модуле. Может определить свой тип, логически равный PRECT, и прагму для него включить? А в обработчике WM_SIZING работать именно с ним (а конверсия эта мне нужна именно для WM_SIZING).
> Это то есть как?
Я имею в виду, прямо в коде ткнуть правой кнопкой по названию модуля, переменной, функции и выбрать "перейти к описанию/реализации".