В.: «что делать если грузятся два экземпляра одного прибора и дерутся между собой, вызывая ошибки в работе панели? И что делать если логика прибора не стартует, пока прибор не будет показан на экране»
О.: Отвязать логику (работы прибора/системы) от представления (от того, что в симе называется gauge). Как это сделать? Сначала экскурс в основы.
Многие начинающие прибористы воспроизводят шаблон, предложенный разработчиками сима в SDK. т.е.
GAUGE_TABLE_BEGIN() GAUGE_TABLE_ENTRY(&gaugehdr_attitude) GAUGE_TABLE_ENTRY(&gaugehdr_control_surfaces) GAUGE_TABLE_ENTRY(&gaugehdr_fuel) GAUGE_TABLE_ENTRY(&gaugehdr_fuel_selector) GAUGE_TABLE_ENTRY(&gaugehdr_temperature) GAUGE_TABLE_ENTRY(&gaugehdr_whiskey) GAUGE_TABLE_ENTRY(&gaugehdr_flightmap) GAUGE_TABLE_END()
и не задумываются, что стоит за этими мудрыми словами, до тех пор пока… пока не начинают делать что-то более сложное, и не сталкиваются с проблемами наподобие вышеописанной. Собственно, данный шаблон предназначен для сокрытия программной машинерии, которая обеспечивает загрузку и отображение приборов симом. Пытаясь остатся в пределах использования этого шаблона, начинаются навороты со статическими переменными, отслеживанием многократной загрузки и тд и тп, что не способствует устойчивости модели вообще. Решение же лежит в другом, и решение это более изящно — а именно — развязывание непосредственно представления (gauges) от логики модели той или иной системы ВС. Но для этого — необходимо прекратить использовать вышеприведеннный шаблон, и начать использовать ту самую внутреннюю машинерию приборного модуля. Так что же скрывает вышеприведенный шаблон? А вот что
//GAUGE_TABLE_BEGIN()
extern GAUGEHDR gauge_header;
void FSAPI module_init(void){} //вот оно!!!
void FSAPI module_deinit(void){} //и это!!!!
BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}
GAUGESIMPORT ImportTable =
{
{ 0x0000000F, (PPANELS)NULL },
{ 0x00000000, NULL }
};
/* This is the module's export table. */
GAUGESLINKAGE Linkage =
{
0x00000013,
module_init,
module_deinit,
0,
0,
FS9LINK_VERSION, {
//GAUGE_TABLE_ENTRY(&gaugehdr_attitude)
(&gaugehdr_attitude),
//GAUGE_TABLE_END()
0
}};
Итак, что мы тут видим? А видим, что шаблон скрывает определение трех функций и двух структур. Первую структуру (ImportTable) оставляем без изменений, она обеспечивает доступ к функциям сима наподобие lookup_var(). Вторая структура содержит заголовок приборного модуля, в котором указывается магическое число 0x13 (19 в десятичной системе), обозначающую для сима то, что это приборный модуль, два адреса функций, определенных ранее (module_init, module_deinit), два магических числа, нам не интересных, номер версии сима, для которой предназначен данный приборный модуль, ну а дальше идет список адресов заголовков описаний непосредственно представлений приборов (gauges), завершающееся еще одним магическим числом — 0, поскольку именно его сим ожидает увидить при загрузке списка представлений из приборного модуля, в конце означенного списка представлений.
Более детально нас интересуют именно определенные шаблоном функции. DllMain оставим в стороне, она в приборных модулях дополняется своим кодом в очень редких случаях. Более подробно интересуют две другие функции — module_init и module_deinit. Что они делают? В шаблоне по умолчанию они не делают ничего! Но! функция module_init вызывается один раз при загрузке приборного модуля, и module_deinit вызывается один раз при выгрузке модуля симом. При этом совершенно не важно, был ли отображен прибор на экране, или не был. Т.е. эти две функции выполняются всегда. Вот сюда-то нам и надо поместить инициализацию логики наших систем, загрузку всех требуемых ресурсов, а так же запуск цикла расчетов обновлений логики (в тч и асинхронное, если ваши знания позволяют это реализовать). В представлении же мы оставляем только отображение конкретных значений и прием управляющих воздействий от пользователя (мышеклики). При этом одинаковых представлений может быть любое множество, в каких угодно местах (на 2Д панели, в ВК или на внешнем компьютере). Конкретные способы реализации самой модели я сейчас рассматривать не буду.
Итак, что же надо сделать? конкретно — прекратить использовать шаблон, предложенный SDK, и использовать ту внутреннюю машинерию, которую скрывает этот шаблон. Выполнив это, вы способны внедрить в функции, вызываемые симом при загрузке приборного модуля (не отдельного прибора, события откладываемого до непосредственного отображения прибора, а всего модуля!) и при выгрузке, необходимый вам код инициализации и запуска логики, независимой от представления.
Сообщение отредактировано seric76: 13 July 2012 — 05:17
В исходниках оставлены за кадром некоторые хитрушки для стимуляции головного мозга начинающих писателей
Прикрепленные файлы
gau.ZIP 11.27К
375 Количество загрузок:
Project.ZIP 55.74К
390 Количество загрузок:
А чем рисование через GDI+ решит проблему с рефрешем текстур в вк? Собственно главная проблема в виртуальном кокпите — это несколько более тормознутое обновление текстур — на которых собственно приборы то и рисуются — по сравнению с обновлением подложки 2д панели (ну поставили мы флаг SET_OFF_SCREEN — ну узнал сим что хорошо бы перечитать подложку — ну и когда он по вашему этот сделает? Незамедлительно? Да не факт…). И лечится это вообще-то только одним путем — уменьшением размерности текстур в вк. Чем меньше обновлять — тем быстрее сим это сделает (речь ведем о 2004, фсх вроде в этом плане помягче работает). Ну или рисовать объекты как 3д — но чем больше полигонов в кадре — тем тормознутее собственно работа симулятора.
Ну знаете ли — и из пушки по воробьям (сиречь gdi+ для стрелочников пользовать) — это тоже не вариант 🙂 Ибо рисование через гди — изначально вещь затратная.
Кстати помнится я с подобным сталкивался, уж не помню на каком проекте — так вот, MAKE_NEEDLE имеет какие-то проблемы, а вот спрайт работал плавненько.
А можно задать маленький и глупый вопрос?
Если сделать модель под одну версию FS без использования шаблонов SDK, не приведет ли это к тому, что, при переходе на следующие версии FS придется не просто перекомпилировать исходники с использованием gauges.h из нового SDK, а переписывать куски кода в каждом приборе?
Вряд ли сильно много. Денис просто раскрыл макросы, описывающие «голову» прибора. Если уж прям так напрягает — условную компиляцию никто не отменял.
Спасибо.
У меня два вопроса.
1. В любой гау баблиотеке должен быть хотя бы один прибор с именем, которое, в свою очередь, нужно прописать в Panel.cfg, для того, чтобы сим мог подцепить библиотеку. Сам же прибор требует наличия макроса GAUGE_HEADER_FS700, который в свою очередь, требует обязательного списка элементов. Вот и приходится в прибор логики добавлять такой список, хотя бы с одним элементом, к примеру, MAKE_STATIC, содержащий в качестве параметров нули. В принципе, ничего особо страшного в этом нет, но может есть способ обойтись без таких заглушек?
2. Необходимо написать программный модуль обработки ввода пользователя. Ввод пользователя осуществляется через клавиатуру, джойстик, мышь. С джойстиком понятно — пишем с использованием DirectInput, отключаем в симе джойстик и получаем нечто похожее на ПТ. Мышь. Мышиные события и так обрабатываются в пользовательском коде. Остается клавиатура. И тут мне известны два возможных варианта: DirectInput и SetWindowsHookEx. Собственно клавиатурный хук пока вполне справляется с задачей, то есть клавиатурное событие прехватывается перед симулятором, и в коде определяется что с ним делать: а) обработать самостоятельно и «погасить»; б) обработать самостоятельно и передать симу; в) просто передать симу без обработки.
Собственно вопрос: нужно ли смотреть в сторону DirectInput (с которым я никогда не работал применительно к клавиатуре)?
Можно. Способ для FS9 называется «модуль». Собственно гау есть частный случай обычного модуля, несколько более специфицированный. Для FSX нужно работать через SimConnect.
Как сделать модуль FS9? да точно так же как и gau. С одним отличием — в Linkage первый параметр («магическое число 0x00000013) заменяется либо на 0, либо на любое не занятое симовскими модулями (ага, они имеют такую же структуру, те же ImportTable и Linkage символы) число. Впрочем, отличное от нуля число необходимо только тогда, когда предполагается загрузка вашего модуля другими компонентами сима (ну например — вашими приборами) посредством штатных механизмов ФС. Ну и дальше в Linkage, где у вас идут списки приборов, будет стоять простой сакраментальный 0, обозначающий пустой список функций. Такой модуль надобно будет положить в папочку modules, сим при запуске его загрузит. Что с этим делать дальше и как взаимодействовать с симом? нууу, это большой и сложный вопрос, который уходит в сторону «грязных» хаков и использования штатных, но немножко недокументированных функций
Можно и не смотреть, достаточно клавиатурного хука. Дальше — смотрите сами. там опять начинается грязный хакинг и пошлая недокументарщина. В плане FSX все куда проще — возможность маппить свои события на клавиатуру и перехватывать штатные, с «гашением» любых симовских событий — заложена в SimConnect по дефолту.
можно я добавлю? такие модули будут висеть постоянно в памяти, в отличии от гауги, которая грузится только при загрузки крафта и выгружается при его выгрузки (ну например смене самолёта, который данную гаугу не использует). я не знаю, важно это знать или нет.
С помощью тех самых недокументированных функций можно реализовать и модуль с загрузкой по запросу. В FS9 ессесно. в FSX SimConnect нивелирует все различия.
Ребята, кто подскажет в чем может быть проблема, если после компиляции стандартных файлов из SDK (папка /sample), то файл .gau не создается вообще…?
Компилятор не ругается только с параметром /I. (nmake MVC++2008 EE).
а файл .dll есть? на что ругается без /I?
В том то и проблема, что не создается никаких папок и файлов вообще, а компилер ошибок не выдает.
Без /I пишет «fatal error U1077».
А с указанным параметром «link…» и т.д. — т. е. вроде все Ок.
??? Не понятно.
Прикрепленные изображения
Я прописал нахождение cl и rc …
можно make файл в студию.
и ещё один вопрос — а почему собсно из консоли компиляем? чем живая студия плоха?
и ещё, если работаешь из консоли, vcvars32 запускал?
Сообщение отредактировано icebear: 10 March 2009 — 14:00
# Copyright © 2000 Microsoft Corporation. All rights reserved.
INCDIR = ..inc
DESTDIR = ..inc
INCS = -I$(INCDIR)
LIBS = user32.lib gdi32.lib kernel32.lib
!IFDEF DEBUG
C_FLAGS = /Z7
L_FLAGS = /DEBUG
!ELSE
C_FLAGS =
L_FLAGS =
!ENDIF
goal: SDK.gau
SDK.obj: $(INCDIR)gauges.h
SDK.c
SDK.h
SDK.Attitude.c
SDK.Control_Surfaces.c
SDK.Fuel.c
SDK.Fuel_Selector.c
SDK.Temperature.c
SDK.Wiskey.c
SDK.FlightMap.c
cl $(C_FLAGS) -c $(INCS) SDK.c
SDK.res: SDK.rc
SDK.h
resSDK.Attitude.bg.BMP
resSDK.Attitude.card1.BMP
resSDK.Attitude.mask1.BMP
resSDK.Attitude.card2.BMP
resSDK.Attitude.mask2.BMP
resSDK.Control_Surfaces.bg.bmp
resSDK.Control_Surfaces.Ailerons.bmp
resSDK.Control_Surfaces.Elevator.bmp
resSDK.Control_Surfaces.Rudder.bmp
resSDK.Control_Surfaces.Trim.bmp
resSDK.Fuel.bg.bmp
resSDK.Fuel.needle.bmp
resSDK.Fuel_Selector.Off.BMP
resSDK.Fuel_Selector.Left.BMP
resSDK.Fuel_Selector.Right.BMP
resSDK.Fuel_Selector.Both.BMP
resSDK.Temperature.bg.bmp
resSDK.Temperature.F.bmp
resSDK.Temperature.C.bmp
resSDK.Whiskey.bg.BMP
resSDK.Whiskey.card.BMP
resSDK.Whiskey.mask.BMP
resSDK.FlightMap.BMP
rc -r $(INCS) SDK.rc
SDK.gau: SDK.obj
SDK.res
link $(L_FLAGS) /dll /out:$(DESTDIR)SDK.gau SDK.obj SDK.res $(LIBS)
clean:
del $(DESTDIR)*.exp
del $(DESTDIR)*.gau
del $(DESTDIR)*.lib
del *.obj
del *.res
///////////////////////////////////////////////
В студии я не компилирую потому, что не компилировал никогда при помощи <makefile> — файлов (работал в СиБилдере и Делфи, и всегда использовал встроенный компилер). К тому же руководствовался только SDK.
vcvars32 запускал — все по-прежнему..
goal:SDK.gau
после вызовов cl и перед вызовом link. хотя не думаю, что это что-то даст. cl не переваривает какой-то файл. попробуй сначала от руки компильнуть, без линковки и посмотри, что скажет cl
дык если из студии компилируешь — makefile вообще не нужен, она же сама всё делает. или я что-то не понял?
Написал прибор для кнопки нажигационных огней. Огни переключаются а битмап самой кнопки не появляется и не переключается. Битмап заднего фона виден.
У кого есть идеи?
Код: SDK.h
Код SDK.c
... #include "gauges.h" #include "SDK.h" UINT32 nav_light = 0; ///////////////////////////////////////////////////////////////////////////// // Attitude ///////////////////////////////////////////////////////////////////////////// #define GAUGE_NAME "gear_lock_key" #define GAUGEHDR_VAR_NAME gaugehdr_gear_lock_key #define GAUGE_W 100 // Set up gauge header char gear_lock_key_gauge_name[] = GAUGE_NAME; extern PELEMENT_HEADER gear_lock_key_list; extern MOUSERECT gear_lock_key_mouse_rect[]; GAUGE_HEADER_FS700(GAUGE_W, gear_lock_key_gauge_name, &gear_lock_key_list, gear_lock_key_mouse_rect, 0, 0, 0, 0); ///////////////////////////////////////////////////////////////////////////// FLOAT64 FSAPI gear_lock_key_icon_cb( PELEMENT_ICON pelement ) { return nav_light; } MAKE_ICON ( gear_lock_key_icon, BMP_KEY_DOWN, NULL, NULL, IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY, 0, 0,0, MODULE_VAR_NONE, gear_lock_key_icon_cb, ICON_SWITCH_TYPE_SET_CUR_ICON, 2, 0, 0 ) PELEMENT_HEADER gear_lock_key_icon_list[] = { &gear_lock_key_icon.header, NULL }; ///////////////////////////////////////////////////////////////////////////// MAKE_STATIC ( gear_lock_key_background, BMP_BG, NULL, NULL, IMAGE_USE_TRANSPARENCY, 0, 0,0 ) PELEMENT_HEADER gear_lock_key_list= &gear_lock_key_background.header; ///////////////////////////////////////////////////////////////////////////// MODULE_VAR gear_lock_key_mouse_var = {NAV_LIGHTS}; BOOL FSAPI gear_lock_key_mouse_cb( PPIXPOINT relative_point, FLAGS32 mouse_flags ) { lookup_var( &gear_lock_key_mouse_var); switch (nav_light) { case 0: trigger_key_event( KEY_TOGGLE_NAV_LIGHTS, 0 ); nav_light = 1; break; case 1: trigger_key_event( KEY_TOGGLE_NAV_LIGHTS, 0 ); nav_light = 0; break; //default: // trigger_key_event( KEY_TOGGLE_NAV_LIGHTS, 0 ); // break; } return TRUE; } MOUSE_BEGIN( gear_lock_key_mouse_rect, HELP_NONE, 0, 0 ) MOUSE_CHILD_FUNCT( 100,100,60,60, CURSOR_HAND, MOUSE_LEFTSINGLE, gear_lock_key_mouse_cb ) MOUSE_END ///////////////////////////////////////////////////////////////////////////// #undef GAUGE_NAME #undef GAUGEHDR_VAR_NAME #undef GAUGE_W GAUGE_TABLE_BEGIN() GAUGE_TABLE_ENTRY(&gaugehdr_gear_lock_key) GAUGE_TABLE_END()Сообщение отредактировано anton_il: 11 April 2009 — 16:02
третий параметр NULLевой. Попробуй указать &gear_lock_key_icon_list
ИМХо подобные вопросы лучше задавать в отдельной теме(-ах) — тут всё-таки вроде как Tips & Hints
Сообщение отредактировано Lavrik: 11 April 2009 — 20:21
Спасибо помогло
там еще симпотный баг был,
Ну и за одно открою топик для вопросов по строительству приборов на С
Сообщение отредактировано Drum27: 10 March 2010 — 01:10
В общем, алгоритм
1. заводится L: переменная (просто выбирается для нее имя, сим сам создаст ее при первом упоминании где угодно)
2. в modeldef.xml пишется описание новой кастомной анимации (за описаниями смотри тот же файл) где и прописываются алгоритмы и зависимости
3. объект моделируется в 3Д и ему назначается в качестве анимации тэг этой новой вашей кастомки
4. если надо — пишется поддерживающая часть (на XML или C, не суть) на стороне приборки
5. все это собирается, проверяется, если не работает — возвращаемся на п.2 и делаем итерацию снова
Собсно,подскажите, на что ругается компилятор VS++2008. С расширением файла чёт не то, или настройки?
Сообщение отредактировано Virpil: 02 June 2010 — 09:10
Дима, раскажи что задумал. Широкой аудитории тоже будет интересно 🙂
OFF <Кругозор Миш расширяю>
OFF
================================
Теперь по существу: После переименования и отключения опции «Use precompiled header» стала выдавать два предупреждения и ошибку. ИМХО, похоже ссылается на ресурс. Где ошибка?
------ Построение начато: проект: PKP, Конфигурация: Debug Win32 ------ Компиляция... stdafx.cpp Компиляция... PKP.cpp PKP.Attitude.cc c:documents and settingsадминистраторрабочий столsample_c++pkp.attitude.cc(4) : warning C4627: #include "PKP.Attitude.cpp": пропущен при поиске использования предкомпилированного заголовка Добавление директивы в "stdafx.h" или перестройка предкомпилированного заголовка c:documents and settingsадминистраторрабочий столsample_c++pkp.attitude.cc(48) : warning C4603: PITCH_LIMIT: макрос не определен или определение изменилось после использования предкомпилированного заголовка Добавление макроопределения в предкомпилированный заголовок вместо определения его здесь c:documents and settingsадминистраторрабочий столsample_c++pkp.attitude.cc(110): использование предкомпилированного заголовка Создание кода... Компиляция... dllmain.cpp Компиляция ресурсов... Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1 Copyright (C) Microsoft Corporation. All rights reserved. ......sample_c++PKP.h(30) : fatal error RC1004: unexpected end of file found Журнал построения был сохранен в "file://c:Documents and SettingsАдминистраторРабочий столProject1PKPPKPDebugBuildLog.htm" PKP - ошибок 1, предупреждений 2 ========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========4-я, 48-я строка кода и дерево на скринах. Проект Win32 DLL с экспортом символов.
Прикрепленные изображения
Слушай, Дим. Я конечно не знаю, почему у тебя не клеится. Но кое что замечу.
У меня в сценостроительстве не компилилось пару раз из за того, что всё хозяйство лежало в папке с длинными русскими именами.
В результате компилятор что -то где-то не находил.
Чтобы наверняка, кидай лучше в C:ISH_PRIB например, лучше без пробелов.
MS Platform SDK for Windows Server 2003 SP1 на которую ссылается компиль, установлена отдельной прогой в Program Files, и шла кажись вместе с установкой VS2008++ с сервера MS. (могу ошибаться)
И общий: Где-нить описано как прально собрать DLL именно для использования ее симом?
Сообщение отредактировано Virpil: 03 June 2010 — 14:56
сюда смотрел?
ещё хотел добавить. тут в файлах лежит оверхед тамагочи с исходниками от anton_il, он тоже это всё писал в студии 2К8 насколько я знаю. качни, сделай копию и выкини все его файла оттуда и вставь свои. будешь использовать как образец создания проекта в студии для написания гауг.
а вообще весь код проекта сюда. там много косяков именно в самих файлах по ходу, не только в настройках проекта. по выводу компилятора трудно колдовать.
Сообщение отредактировано icebear: 04 June 2010 — 11:33
Может, Вам из консоли попробовать компилировать? С помощью make-файла?
Я бы все же посоветовал затратить столько времени, сколько нужно для того, что бы въехать в среду Visual C++ и в то, как строятся, а затем компилятся и отлаживаются C/C++ программы.
Я, например, не представляю, как можно что-то делать серьезно хотя бы без отладки.
Так же достаточно явственно помню все неудобства, связанные с неиспользованием раздельной компиляции (Обычно начинающие приборостроители это делают наряду с тем, что для компиляции и сборки пользуются make-файлами, просто потому, что в примере в SDK используется только make-файл).
Т.е. стоит сначала освоить инструмент, хоть как-то, а уж потом пробовать клепать приборы.
Ну и естественно, так же предварительно стоит приобрести, хоть какие-то инженерные знания по изготавливаемым приборам.
А то получится, как часто получается в случае с XML приборами (не во всех случаях), по причине невозможности программирования на этом языке сложной логики.
Просто анимированные картинки, пусть даже и красивые.
Сообщение отредактировано serg_p: 05 June 2010 — 12:01
Некомпилированный шаблон кода проекта студии прицепил в архив ниже. Заранее спасибо за корректировку.
Я новичек в приборостроении. Хотел воспроизвести шаблон SDK FS9, в части касаемой только ихнего авиагоризонта для Цес. Здесь писалось о том, что при комиляции из студии make-file можно «отпустить», а постигнуть на этапе хочется пока именно среду.
Прикрепленные файлы
shablon_a.zip 1.23МБ
68 Количество загрузок:
До gau ей еще далеко.
В свое время я делал пример для Андрея акка icebear.
Не знаю на сколько он помог ему.
Посмотри, может быть поможет в чем-то разобраться.
Прикрепленные файлы
gau_sample.zip 94.52К
112 Количество загрузок:
Сообщение отредактировано serg_p: 05 June 2010 — 12:45
Есть и сама сборка. В ней файлы только того, что предложил MS. Она получилась объемной и авсим ее не подцепил. Я удалил из проекта файл типа VC++ Intellisense Database и сжал максимально. Попробую разобраться в твоем проекте, Серег. Пасиб
Прикрепленные файлы
pkpgau.zip 1.41МБ
72 Количество загрузок:
Файл инклудит сам себя.
Скорее всего там должно было быть
Нужно понять одно правило.
Файлы с расширением c/cpp — тело, собственно реализация, код.
Файлы с расширением h являются в первую очередь интерфейсом, механизмом, предоставляющим возможность вызывать функции, которые реализованы (запрограммированы) в c/cpp файле. Каждый c/cpp файл компилится в отдельный obj файл. Собственно раздельная компиляция. Изменения в одном c/cpp файле не приводят к перекомпиляции других c/cpp файлов. Все obj файлы собираются в процессе компоновки уже конкретно в exe, dll и т.д.
P.S.
Небольшое замечание по раздельной компиляции.
Так как сделано в примере из SDK ни в коем случае не приводит к раздельной компиляции отдельных С-файлов.
Когда один или несколько c/cpp файлов включаются в другой c/cpp файл через #include — для компилятора это выглядит, как один c/cpp файл и компилит он все это в один obj-файл. Т.е. здесь нет никакой раздельной компиляции.
Это ничего, когда файлов наберется штук 5, а когда их за 100 — это просто ужос.
Сообщение отредактировано serg_p: 06 June 2010 — 11:03
Сереж, собрал твой пример, и подправил свой. Компиль стал выдавать одинаковую ошибку для обоих проектов ссылаясь в .cpp-файлах на 4590-ю строку «головного» GAUGE.H. Только для твоего ошибка повторяется 4 раза тк там 4-е .cpp. Приведу нынешний лог своего проекта:
и твоего:
gauges.h — это собственно основной файл API с симом. Писался он еще при царе Горохе. Старые компиляторы (пример изначально я делал в 2003-ей студии), спокойно подменяли пропущенный тип переменной или тип возвращаемого значения функцией, на тип int. Не помню уже, с какой версии VС компилятор перестал подставлять int вместо пропущенного типа и стал считать не указание типа ошибкой. В принципе правильно. Не указывать тип переменной или возвращаемого значения функцией, есть очень нехорошее дело. Вообще, небрежное обращение с типами данных, в определенной ситуации, может сыграть в последствии очень злую шутку.
Хотя, если очень надо, то ошибку эту можно отключить.
Интересно, что у меня то все сейчас скомпилилось и студия у меня такая же, 2008-ая. Не пойму, наверное, после какого-то обновления экспресс VC, у меня компилятор стал лояльным к этой ошибке.
Замени 4590-ую строку в gauges.h
на вот эту строку.
Здесь объявляется функциональный тип данных, т.е. тип — указатель на функцию с таким-то списком параметров и таким-то возвращаемым значением. В исходном варианте пропущен тип возвращаемого значения функции.
Сообщение отредактировано serg_p: 05 June 2010 — 22:01
Сообщение отредактировано Virpil: 06 June 2010 — 16:45
Но опыта и знаний для этого слишком мало.
Форум не поможет тебе их приобрести.
Только книги и твоя задница.
И движение от простого к сложному.
Забудь пока про приборы.
(Если хочешь писать приборы на С)
Пройди для начала по какой-нибудь «мурзилке», которая учит писать проги на VC с полной проработкой примеров.
Поверь, на освоение C/C++ уходят годы.
проблема снова в файле ресурсов (.rc), который мы ещё не видели
кинь прямо сюда его код, он небольшой.
и ещё, добавлю от себя по поводу с/сpp и h файлов: файлы h по сути можно опускать, они для удобства (что бы не бегать по километровому исходнику в поисках декларации той или иной функции) или для работы с библиотеками, где реализация просто скрыта.
и ещё, может последние посты с проблемами ide переместить вот сюда http://www.avsim.su/…priborov-na-si/ ?
Сообщение отредактировано icebear: 07 June 2010 — 11:17
Мне надо взять картинку с гаги (всё, что в текущий момент там нарисовано) и продублировать в файл, например.
Я вот нашел в «case PANEL_SERVICE_POST_DRAW»:
Структура интересная, имеет поля типа:
, но они практически все равны NULL.
hdc = pelement->hdc;
но это ты доступишься до нижнего элемента в дереве, а вот будет-ли он полной картинкой — вопрос двадцать пятый. ещё одно замечание: hdc вроде можно достать только у тех, кто декларирован с флагом IMAGE_CREATE_DIBSECTION. возможно после декларации твои нули исчезнуть и появится буфер.
Сообщение отредактировано icebear: 28 November 2011 — 12:17
HINSTANCE hDLL;
hDLL = LoadLibrary(«pnk_154m_3_024.gau»);
pAdr = (GAUGESLINKAGE *)GetProcAddress(hDLL, «Linkage»);
HBITMAP hb = LoadBitmap(hDLL,MAKEINTRESOURCE(4976));
DeleteObject(hb);
FreeLibrary(hDLL);
Но это когда мы точно знали что номер битмапа 4976. А как узнать этот номер? Наиболее быстрый способ это подсмотреть в отладчике в таком коде (перебирает все элементы)
GAUGESLINKAGE * pAdr;
HINSTANCE hDLL;
hDLL = LoadLibrary(«pnk_154m_3_024.gau»);
pAdr = (GAUGESLINKAGE *)GetProcAddress(hDLL, «Linkage»);
PELEMENT_HEADER el_list;
int i=0;
while (pAdr->gauge_header_ptr[i]!=NULL)
{
el_list = *pAdr->gauge_header_ptr[i]->elements_list;
while (el_list!=NULL)
{
if (el_list->next_element!=NULL)
el_list = *el_list->next_element;
else
el_list = NULL;
}
i++;
}
Именно так!
Спасибо за подсказку про IMAGE_CREATE_DIBSECTION! Получил «pelement->hdc;» и прочие указатели, щас пытаюсь вытащить оттуда картинку.
Проблема:
Если прописать прибор и в ВК и в 2D кабине, то после того, как побывали хоть раз в ВК и хоть раз открыли 2D окно, в котором он прописан в 2D кабине — CallBack прибора с service_id == PANEL_SERVICE_PRE_UPDATE будет вызываться дважды. Это очень плохо. Собственно то, что некоторые программисты могут не учитывать этот факт, приводит к тому, что прибор нельзя прописать и в 2D кабине и в ВК, когда в PRE_UPDATE, например, что-нибудь инкрементируется (т.е. когда в вычислениях есть рекурсия по данным). Понятно, что в таком случае, инкрементироваться все будет дважды.
Если я ничего не упустил, то выйти из того положения можно таким вот образом:
MODULE_VAR main_module_tick18 = { TICK18 }; FLOAT64 get_tick18() { return main_module_tick18.var_value.n; } FLOAT64 main_module_tick18_prev = 0; ... // Update уровня логики void FSAPI logic_level_update(PGAUGEHDR pgauge, SINT32 service_id, UINT32 extra_data) { // Используем только PANEL_SERVICE_PRE_UPDATE // (инициализация и деинициализация в module_init и module_deinit) if (service_id != PANEL_SERVICE_PRE_UPDATE) return; // Выполняем код уровня логики один раз каждый тик. // Вне зависимости от того прописан ли прибор уровня логики и в ВК и в 2D кабине. lookup_var(&main_module_tick18); if (main_module_tick18.var_value.n == main_module_tick18_prev) return; // to do // ... // Обязательно запоминаем номер текущего тика main_module_tick18_prev = main_module_tick18.var_value.n; }Собственно в
// to do
// …
и крутим всю логику. Запускаться будет она один раз каждую 1/18 секунды, так как, если TICK18 у нас не изменился, то значит мы сейчас сидим в CallBack-е второго экземпляра прибора, а в этом случае мы CallBack-функцию прибора покидаем.
Это могут быть просто некоторые короткие вычисления, необходимые для данного прибора.
Или это может быть вызов из невидимого прибора (который прописываем и в ВК и в 2D кабине) основной функции (метода) всей страшно сложной логики, страшно сложных систем, какого-нибудь приборного комплекса.
…
(В ВК, если не ошибаюсь, нет никакой разницы, куда прописать невидимый прибор логики ([VcockpitXX]), CallBack всегда будет вызываться симом. В 2D, прибор, который будет крутить весь уровень логики необходимо прописать в окно, которое обязательно открывается автоматом при входе в 2D кабину. Как правило это окно с ident=MAIN_PANEL)
Сообщение отредактировано serg_p: 11 January 2012 — 15:47
Во вторых.
Как я понял, для FSX, ты имеешь в виду случай, когда dll прописывается в DLL.xml, что бы она загружалась вместе с симом. Но здесь мне приходит на ум только один вариант. С помощью функции SimConnect-а — SimConnect_SubscribeToSystemEvent, подписаться на системное событие «6Hz». Но! Хоть, как говорит MS, джой читается именно с этой частотой (This is the same rate that joystick movement events are transmitted) и тут для отработки ввода от джоя вроде бы больше и не надо, этой частоты обновления скорее всего не хватит для реализации собственных ПИД регуляторов, фильтров, следящих систем и т.д. 18 герц уже может и нормально, но 6 герц для своей навороченной логики — это маловато.
Ну и вообще, мне кажется, что лепить свою dll, которая будет висеть в памяти, пока сим загружен — как-то не ахти. Причем тут ведь не важно, используешь ли ты модель в данный момент, для которой ты прилепил к симу дополнительную dll или не используешь, dll будет висеть в памяти. Тут конечно можно, наверное, определить загружен ли самолет или нет, и в зависимости от этого уже создавать/убивать необходимые для работы структуры данных, но, по моему мнению все это гемор.
По моему мнению гораздо проще и надежней все реализовывать в виде приборов. Тут и обновление логики четко синхронизировано с отображением и частота обновления (18Гц) вполне приемлема для реализации всяких своих фишек и dll, в которой реализуются приборы, загружается и выгружается вместе с самолетом.
Сообщение отредактировано serg_p: 11 January 2012 — 15:48
Сообщение отредактировано icebear: 11 January 2012 — 12:52
Цикл один.
В каждой итерации пробегаются по очереди все приборы, прописанные в Panel.cfg, начиная с [Window00] и заканчивая последней [VcockpitXX]. Соответственно, если, например, у тебя прибор прописан в двух 2D окнах, плюс еще в какой-нибудь [VcockpitXX] — его CallBack будет вызываться три раза, если ты зашел в ВК и плюс к этому хоть по одному разу отобразил оба 2D окна. Т.е. сим начинает крутить CallBack прибора только, если он его должен визуализировать. Причем, после того, как сим визуализировал экземпляр прибора, его Callback будет всегда вызываться симом, вплоть до окончания полета, вне зависимости от того будет ли еще отображаться этот экземпляр или нет.
CallBack-и приборов с одним STATIC, с флагом HIDDEN, тоже крутятся, несмотря на то, что битмап прибора не отрисовывается.
Все это можно легко проверить в отладчике.
Сообщение отредактировано serg_p: 11 January 2012 — 13:33