![]() |
Модераторы: Snowy, MetalFan, bems, Poseidon |
![]() ![]() ![]() |
|
mr_smit |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Здравствуйте. Давно я не программировал на Delphi. А тут задался целью сделать для своей машины (ВАЗ 11183) считыватель ошибок на микроконтроллере. Чтобы разобраться с протоколом, хочу для начала из своего приложения на ПК посмотреть/почитать данные. Диагностическая линия (k-line) представляет из себя "обычный ком порт" только с измененными логическими уровнями. 0 вольт - это логический 0, +12 вольт - это логическая единица. У ком порта 0 это минус 12 вольт. Собственно все переходники для машины и представляют собой просто согласователи этих самых уровней.
Скачал бесплатную программу Diagnostic Tools. Подключился к машине. Всё работает. Всё показывает. Взял снифер ком порта, посмотрел что шлет программа. Скачал описание протокола обмена. Чуда не произошло, всё строго по пунктам ![]() Не буду сильно вдаваться в подробности протокола. Собственно что меня интересует: 1. Чтобы начать диагностику, нам надо отправить: Запрос startCommunication: 81 10 F1 81 03 Ответ: 83 F1 10 C1 6B 8F 3F В ответе C1 означяет что ЭБУ готов с нами работать. Поставил компонент AsyncFree104 для работы с com портом:
Как мне прочитать ответ? И как оттуда вытащить C1 ? 2. Сдернул клемму. Прочитал ошибки свои. Для определения значений данного параметра используется десятичная (BCD) кодировка. Запрос ошибок readDTCByStatus: 84 10 F1 18 00 00 00 9D Ответ: 88 F1 10 58 02 04 43 E0 14 26 E0 24 P0443 - всё верно, 2 ошибки появилось. P1426 Первые 3 байта нас не интересуют. Нам интересно: 58 - положительный ответ, 02 - число ошибок, дальше ошибки разделенные E0. Последняя цифра во всех запросах/ответах - контрольная сумма (2 младших разряда). Как вытащить ошибки из этого ответа? У компонента есть:
Как принимать в этот Buf ? Если длинна его меняется. И как разобрать данные? Это сообщение отредактировал(а) mr_smit - 12.10.2011, 08:33 |
||||
|
|||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
1. В чем вопрос-то? Как вытащить четвертый байт из буффера?
2. Выделять с запасом -------------------- Обижено школьников: 8 |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Пока писал, сам сообразил. Вроде так:
Так? Это сообщение отредактировал(а) mr_smit - 12.10.2011, 08:56 |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
зависит от того что такое ReadBuffer, но похоже, да
-------------------- Обижено школьников: 8 |
|||
|
||||
mr_smit |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Да, забыл написать
Если так, то тогда ещё вопрос: BCD кодировка, как с ней работать? Как мне, например, в Memo отобразить ошибки? Это сообщение отредактировал(а) mr_smit - 12.10.2011, 09:06 |
||||
|
|||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
ну и там же наверное чтонить и возвращается из WriteData и ReadData
-------------------- Обижено школьников: 8 |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Хочу прочитать ошибки из тестового массива.
В мемо получается: P467 P2038 А должно: P0443 P1426 Как перевести из BCD формата в String? Это сообщение отредактировал(а) mr_smit - 12.10.2011, 09:48 |
|||
|
||||
AndreyIQ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 185 Регистрация: 5.2.2007 Репутация: 1 Всего: 8 |
|
|||
|
||||
mr_smit |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Оооооо....!!!! Спасибо! Работает. Кстати. Вот запрос параметров: 82 10 F1 21 01 A5 ЭБУ моей машины отвечает: 80 F1 10 26 61 01 3B 90 41 04 00 00 00 00 47 80 00 00 00 52 52 80 18 00 8E 00 5C 00 00 00 00 00 00 00 00 00 FF FF DD A4 47 02 CE 61 - Положительный ответ readDataByLocalIdentifier 01 - afterSalesServiceRecordLocalIdentifier (что то там....) .... 11-й байт - Температура охлаждающей жидкости .... Формула для расчета: N=E-40 [°C] E - передаваемое значение N - физическая величина У меня это значение 47. Берем windows калькулятор. Переводим 47 hex в dec. Получаем 71. Дальше 71-40=31°C. Соглашусь. На момент снятия данных машина часа полтора простояла на улице. До конца не остыла. Как бы мне теперь на Delphi так конвертнуть? |
||||
|
|||||
AndreyIQ |
|
||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 185 Регистрация: 5.2.2007 Репутация: 1 Всего: 8 |
|
||||
|
|||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Чего то у меня в ошибку вываливается на строке:
Может где то длинну массиву назначать? Это сообщение отредактировал(а) mr_smit - 12.10.2011, 11:48 |
|||
|
||||
AndreyIQ |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 185 Регистрация: 5.2.2007 Репутация: 1 Всего: 8 |
SetLength. Это сообщение отредактировал(а) AndreyIQ - 12.10.2011, 11:58 |
|||
|
||||
mr_smit |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Кажется понял, ReadBuffer у меня сейчас пустой, а я пытаюсь 4-й элемент массива прочитать.
А где её задавать? Сразу после чтения?
Добавлено @ 12:07
Так? И нужно ли буфер обнулять перед каждым вызовом? Или он автоматически каждый раз с нулевого значения записывается? Это сообщение отредактировал(а) mr_smit - 12.10.2011, 13:51 |
||||
|
|||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
1. Размер массиву ReadBuffer задавать ДО передачи его в качестве параметра функции ReadData. 2. Размер массива это Length, а SizeOf это размер переменной, которая хранит адрес массива в памяти. 3. Первый параметр в функции ReadData должен быть передан как ReadBuffer[0]. -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Чего то у меня не работает код
![]() Дело в том что, как я понимаю, поскольку по K-Line обмен идет по одному проводу, то в момент передачи, принимать ничего не надо! Закончили передавать - начинаем линию слушать. Вот как этот момент реализовать? Добавлено @ 15:39 Я когда сниффером обмен смотрю: Запрос startCommunication: 81 10 F1 81 03 Ответ: 81 10 F1 81 03 83 F1 10 C1 6B 8F 3F Реальный ответ это только 83 F1 10 C1 6B 8F 3F. А в начале идет запрос, просто он автоматом попадает на вход. Провод то связи один. Он и на передачу работает и на прием. Это сообщение отредактировал(а) mr_smit - 12.10.2011, 15:46 |
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Слушать постоянно. Отделять ответ от своего же "эха" потом. -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Какой именно код не работает? 1. Вы смогли самостоятельно разработать или где-то купить преобразователь СОМ-"однопроводная линия"? Это не так сложно теоретически, но я сомневаюсь, что вы его хоть как-то получили. А без него вы ничего не сможете сделать. 2. Вы изучили полностью тот компонент, который вы решили использовать? Наверняка нет. Все эти компоненты созданы по одному лекалу. И у них, у всех есть событие типа OnRxChar. Вот в нём, в этом событии и надо вызывать функцию ReadData. Кстати, заметьте. Это наверняка именно функция, а не процедура! 3. Умение пользоваться "сниффером" и т.п. очень полезное умение. Но оно мало помогает при недостаточном уровне знаний. Это сообщение отредактировал(а) northener - 13.10.2011, 00:10 -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Я сам спаял преобразователь USB <-> K-Line. Там ничего сложного. Он работает! Я несколько программ диагностики уже использовал. Все видят контроллер. Все параметры в режиме реального времени. С этим нет проблем.
![]()
Да, я уже тоже про это подумал. Просто с наскока разобраться не получилось. Буду копать глубже теперь. Сниффер классная вещь когда под рукой описание протокола. Наглядно всё видишь.
Теперь я понимаю что это точно работать не будет. Надо принимать только после окончания передачи. P.S. ReadData - это процедура, а не функция. Справку на компонент прилагаю. Присоединённый файл ( Кол-во скачиваний: 18 ) ![]() |
||||
|
|||||
mr_smit |
|
||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Стало быть как только выходной буффер освободился, т.е. все данные переданы - очищаем входной буффер, и читаем из него данные по событию DataRecived:
Правильно? Это сообщение отредактировал(а) mr_smit - 13.10.2011, 08:14 |
||||||||
|
|||||||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Итак, нам надо отправить запрос startCommunication. При положительном ответе на него отправить startDiagnosticSession. При положительном ответе на него периодически отправлять testerPresent чтобы ЭБУ видел что тестер до сих пор подключен. Попробовал пока вот так это изобразить:
Что скажете? Это сообщение отредактировал(а) mr_smit - 13.10.2011, 09:13 |
|||
|
||||
northener |
|
||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Теоретически правильно. Но на практике почти всегда неправильно. Ибо большинство таких компонент ххСОМPort игнорируют аппаратный FIFO СОМ-порта. А событие "Выходной буфер пуст" для них означает только то, что пуст выходной буфер драйвера СОМ-порта. Т.о. данное событие будет обработано гораздо раньше, чем СОМ-порт выдаст на линию всю предназначенную железяке посылку. Советую вам очищать входной буфер непосредственно перед посылкой команды железяке. И постоянно читать в событии
учитывая параметр Count. Принятое "эхо" вы сможете легко вычленить из приемного буфера. Ведь вы знаете, что вы посылали железяке. -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
||||
|
|||||
mr_smit |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
А как???
Если так, то постоянно перезаписываться будет [0] элемент. Как ReadBuffer получить заполненный моим запросом + ответ? Я чего то не пойму никак. |
||||
|
|||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Т.е. заведите переменную CurrentPos. Перед посылкой присваивайте ей 0. А затем
-------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
showmessage мне возвращает ноль ![]() Обмен смотрю сниффером. ЭБУ отвечает. Но ответ распознать не могу ![]() P.S. northener, сейчас попробую как вы говорите Это сообщение отредактировал(а) mr_smit - 13.10.2011, 15:49 |
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Можете обращаться ко мне в личку. -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
||||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Из справки:
Перевод: Читает указанное число байт из входного буфера. Если не достаточно данных для чтения, вызывается исключение
Количество байт во входном буфере Получается вот так что ли?
Это сообщение отредактировал(а) mr_smit - 14.10.2011, 09:20 |
||||||||||
|
|||||||||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Может быть так. Может быть нет. Надо пробовать и смотреть что получается. Поймите меня правильно. Я не знаком с именно этим компонентом xxCOMport. Как правило "ReadData" в подобных компонентах - функция возвращающая количество байт реально вычитанных из приемного буфера. -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Я взял этот компонент потому что у него можно задать произвольную скорость обмена. Мне нужна 10400. Может подскажите знакомый вам компонент. Может что попроще.
|
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Вообще-то произвольную скорость должен уметь ставить любой компонент. Особенно если он с исходниками. Посоветовать ничего не могу, потому что никаким никогда не пользовался. Только смотрел. Кроме библиотеки AsyncPro, но это слишком тяжелая вещь. -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Ещё раз.
Т.е. 1. Создаём таймер. Его период выбираем исходя из скорости СОМ-порта, на которой работает железяка и из максимального количества байт посылки/команды и ответа. (Один байт - это как минимум 10 бит, как максимум 12 бит. Зависит от наличия/отсутствия бита чётности и от длины стоп-бита(1,1.5,2). Плюс запас 50-500 ms из-за того, что Винда не есть система реального времени. 2. Перед посылкой запроса/команды к железяке очищаем приемный/передающий буфер СОМ-порта методами компонента. 3. Сбрасываем в ноль переменную CurrentPos. 4. Посылаем запрос/команду железяке. Запускаем таймер. Читаем в событии OnDataRecived всё в буфер ReadBuffer по адресу ReadBuffer[CurrentPos]. 5. По срабатыванию таймера смотрим, чему равен CurrentPos и что мы уже получили. После анализа принятого возвращаться к пункту 2. 5-бис Смотреть "чему равен CurrentPos и что мы уже получили" можно уже в событии OnDataRecived после выполнения процедуры ReadData. И если всё уже принято, то сбрасывать/дизейблить таймер. И после анализа принятого переходить к пункту 2. Это сообщение отредактировал(а) northener - 15.10.2011, 00:22 -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Вобщем вот так всё заработало:
![]() northener, спасибо |
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
-------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Единственное я не пойму почему запрос ошибок у меня не работает.
Сделал вывод массива на форму. Почему то запрос/ответ на чтение ошибок не проходит. Т.е. после нажатия на кнопку "ошибки" массив не обновляется. И в нем хранятся данные ещё с предыдущего запроса параметров. Странно. Вроде делаю CurrentPos:=0; ![]() |
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
В приведенном куске кода есть обнуление CurrentPos. Есть посылка команды WriteData. А где чтение ответа? -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
|
|||
|
||||
northener |
|
||||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Так. Я тогда не понимаю, чему вы радовались в ? И за что вы мне плюсик дали? Смотрим ваш кусок кода:
Добавлено через 13 минут и 27 секунд То ли лыжи не едут, то ли я ... Привожу полностью тот мой комментарий к коду, который начинался словами "А тут, в цикле, вы выводите из вашего приемного..." А тут, в цикле, уже выводите данные из вашего приемного буфера в Мемо! И что вы надеетесь увидеть в данный момент в вашем приёмном буфере? Да. После вызова метода компонента WriteData, компонент запустил свой механизм по передаче драйверу СОМ-порта данных для выдачи на линию. Плюс запустил в отдельном потоке функцию WaitCommEvent для получения события о том, что драйвер СОМ-порта что-то прочитал. И возможно даже драйвер уже успел что-то прочитать и сообщить об этом компоненту. Но ваша программа не сможет НИЧЕГО об этом узнать до выхода из той процедуры, кусок которой вы привели! Ибо пока вы не вышли из этой процедуры вашей программы, ваша программа не сможет обработать событие компонента ReadData. -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
||||||
|
|||||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
Плюс поставил за кусок кода:
В принципе я думал что просто не успевает массив заполнится данными. Но в режиме реального времени параметры у меня отображаются. Таймер настроен на 330 мс. Т.е. 3 раза в секунду считываю параметры. А как тогда тут поступить со считыванием ошибок по нажатию кнопки? Добавить как то задержку? Или 2 раза запрашивать? Почему когда я считываю данные - массив успевает обновляться, а когда ошибки считываю таким же образом, то массив не обновляется. Это сообщение отредактировал(а) mr_smit - 20.10.2011, 01:27 |
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
Приведите код вашей процедуры OnTimer. Я подскажу как её изменить. Тогда хоть я смогу (если смогу), хоть как-то отработать тот плюсик, который вы мне добавили. :( Это сообщение отредактировал(а) northener - 21.10.2011, 01:04 -------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
mr_smit |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 254 Регистрация: 27.2.2008 Где: Самара Репутация: нет Всего: 4 |
||||
|
||||
Korod |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 24.10.2011 Репутация: нет Всего: нет |
На СОМ-портах персоналки -12в - это лог.1, а +12в - это лог.0.
|
|||
|
||||
northener |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1361 Регистрация: 2.9.2010 Репутация: 12 Всего: 20 |
-------------------- Но только лошади летают вдохновенно. Иначе лошади разбились бы мгновенно! |
|||
|
||||
Darkblue |
|
|||
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 20.1.2012 Репутация: нет Всего: нет |
Уважаемые подскажите пожалуйста procedure TForm1.AfComPort1DataRecived ставится на рабочее поле,или просто прописывается в процедурах. Никак не могу научиться байт ловить ,помогите пожалуйста
|
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
-------------------- Обижено школьников: 8 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |