Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.116.44.205] |
|
Сообщ.
#1
,
|
|
|
Как правильно найти объект на карте в С++ Builder 6?
CMapXFindFeature *FoundFeature; OleVariant unusedParam; unusedParam.operator =(48); //номер нужного слоя FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Edit1->Text)); //в Edit1->Text храниться название улицы находящейся на слое №48 Проверка в if говорит о том, что улицу не находит, хотя она есть на карте. if (FoundFeature->get_FindRC() % 10 == 1) { ShowMessage("Есть"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundFeature->get_CenterX(); Form1->Map1->CenterY = FoundFeature->get_CenterY(); } else { ShowMessage("Нет улицы"); } Вывод: в строке ниже что-то неправильно: FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Edit1->Text)); Что? |
Сообщ.
#2
,
|
|
|
Цитата Лена @ Вывод: в строке ниже что-то неправильно: FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Edit1->Text)); Что? Не факт... Малость смущает цепочка ->get_Find()->Search() == ->найти->исследовать - это первое. Второе - проверь, что возвращает сам FoundFeature->get_FindRC(). Третье - FoundFeature->get_FindRC() % 10 - может быть так - FoundFeature->get_FindRC() % 0x10 и вообще как-то странно - по значению остатка определять ДА или НЕТ тоже немножко странно OleVariant unusedParam; unusedParam.operator =(48); //номер нужного слоя хотя присваивание unusedParam = 48 делает то же самое... |
Сообщ.
#3
,
|
|
|
Свой пример я основывала на примере из help. Для Builder help-a нет.
Вот он: void CSampleProjectView::SimpleFind() { try { CMapXFindFeature FoundObject = m_Map.GetLayers(). Item("US Major Cities").GetFind().Search("Columbia","SC"); if(FoundObject.GetFindRC() %10 == 1) { m_Map.SetZoom(100); m_Map.SetCenterX(FoundObject.GetCenterX()); m_Map.SetCenterY(FoundObject.GetCenterY()); } else AfxMessageBox("No exact match found."); } catch (COleDispatchException *e) { e->ReportError(); e->Delete(); } catch (COleException *e) { e->ReportError(); e->Delete(); } } Однако в Builder нет Item, а например есть _Item принимающий не имя а индекс типа OleVariant. Соответственно метод Search в Builder принимает параметр wchat_t * address. Исходя из этого и пробовала перевести выше приведенный код на C++ Builder 6. |
Сообщ.
#4
,
|
|
|
Цитата Лена @ Однако в Builder нет Item, а например есть _Item ... Лена, ты где-то здорово запуталась...Речь идет не о Билдере, у него действительно нет Item В хелпе УЖЕ приведен сишный код с использованием компонентов MapX и их причиндалов (свойств, методов, интерфейсов etc...) Я так понял, что тебе надо вести поиск по номеру слоя, а не по названию - это тебя и смутило - |
Сообщ.
#5
,
|
|
|
Цитата Coala @ Цитата Лена @ Однако в Builder нет Item, а например есть _Item ... Лена, ты где-то здорово запуталась...Речь идет не о Билдере, у него действительно нет Item В хелпе УЖЕ приведен сишный код с использованием компонентов MapX и их причиндалов (свойств, методов, интерфейсов etc...) Я так понял, что тебе надо вести поиск по номеру слоя, а не по названию - это тебя и смутило - _Item это метод MapX но в среде C++ Builder. Пишу Form1->Map1->Layers-> в выпадающем списке подскази ищу соответствующий метод, нахожу похожий из примера, это _Item его и использую в своей цепочке. В Делфи в выпадающем списке будет метод Item. MapX после интеграции в различные среды подставляет различные методы для каждой среды. Для Делфи будет Item принимающий имя слоя, для Builder будет _Item принимающий индекс слоя. Метод Search в Делфи принимает имя, а метод Search для Builder принимает wchat_t * address. Вот я и пытаюсь найти по индексу слоя, используя методы MapX, в среде Builder, потому что поиска по имени слоя в MapX в Builder нет. |
Сообщ.
#6
,
|
|
|
Дело в том что когда я делал поиск то для того что бы вытянуть название улицы и номер дома, все зависит от того как сделанна карат, нужно смотреть как это сделали разработчики, дело в том что в таблице с улицами может и не быть названий улиц, она может иметь указатели на другую таблицу... тебе нудно знать какую и в каком поле оно находиться и уже по соответствующей колонке делать выборку...
|
Сообщ.
#7
,
|
|
|
Цитата Лена @ MapX после интеграции в различные среды подставляет различные методы для каждой среды Лена, ты на 100% уверена? ActiveX для того и придумали, чтобы и на Билдере, и на Дельфях, и на всем остальном юзеры (программисты) не ломали голову! Цитата Лена @ Для Делфи будет Item принимающий имя слоя, для Builder будет _Item принимающий индекс слоя Если это действительно так - то таких программеров (утопить/дать Нобелевку - выбрать по желанию) Еще раз: Цитата Coala @ В хелпе УЖЕ приведен сишный код с использованием компонентов MapX не бывает в Дельфи void и if (такого как в хелпе) без begin и end. |
Сообщ.
#8
,
|
|
|
Coala, в хэлпе приведен код для VC, он может значительно отличаться от кода для билдера. Например, в коде Лены, Form1->Map1 - почти наверняка - компонент, брошенный на форму, т.е. указатель, а хэлпе явно используется или ссылочная переменная, или объект, и методы его возвращают ссылки или объекты, а не указатели.
|
Сообщ.
#9
,
|
|
|
Цитата Adil @ он может значительно отличаться от кода для билдера Я имею ввиду разницу в параметрах для одного и того же метода Цитата Adil @ Например, в коде Лены, Form1->Map1 - почти наверняка - компонент, брошенный на форму, т.е. указатель, а хэлпе явно используется или ссылочная переменная, или объект, и методы его возвращают ссылки или объекты, а не указатели ИМХО такое просто не пропустит компилятор - или не обязательно? |
Сообщ.
#10
,
|
|
|
Фрагмент help который я привела выше для VC. MapX компонент на форме. Примера на Делфи у меня нет, но там Item и практически тоже самое, я раньше видела пример в Интернете. Вот как ищет объект Visual Basik практически одно и тоже.
'The code for a find command button Private Sub cmdFind_Click() 'Create a MapXLib for the feature found Dim FindCityObject As MapXLib.FindFeature 'Sets the find feature object to the city the user types in Set FindCityObject = Map1.Layers("US Top 20 _ Cities").Find.Search(txtCityName.Text, txtStateName.Text) 'Use result codes to determine if a city is found If (FindCityObject.FindRC Mod 10 = 1) Then 'Recenter the map to the city location Map1.ZoomTo 200, FindCityObject.CenterX, _ FindCityObject.CenterY Else 'Print out message box indicating city was not found MsgBox ("City not found") End If End Sub Все однотипно и похоже и для VC и для Делфи и для VBA. Только у MapX в Builder свои прибамбасы To MAX2002 Да, мне кажется, что решение где-то рядом и возможно, мой код правильный. Вот несколько строчек кода начала поиска из рабочей программы из ранней версии Buildet, который ищет улицу. В ранней версии применялась технология OLE и MapX версии 3: //Variant l_A, ds_A, find; объявлены в классе формы l_A.OlePropertyGet("Find").OlePropertySet("FindDataset", ds_A); l_A.OlePropertyGet("Find").OlePropertySet("FindField", ds_A.OlePropertyGet("Fields","ID")); l_A.OlePropertyGet("Find").OlePropertySet("ClosestAddr", true); Table2->First(); find = l_A.OlePropertyGet("Find").OleFunction("Search", Table2->FieldValues["ID"], "" );//вот оно! Значит, человек в конечно итоге ищет по id (таблица приложена ниже), значит, мой код для 6 версии должен выглядеть так: CMapXFindFeature *FoundFeature = Form1->Map1->Layers->get_Item(unusedParam)->get_Find()->Search(WideString(Table2->FieldValues["ID"])); unusedParam - номер слоя Слой с улицами загружен в MapX я его вижу, знаю его номер, есть таблица (*.dbf) откуда этот слой получил данные об улицах (прилагаю). Однако не находит. Что-то я упускаю. Прикреплённая картинка
|
Сообщ.
#11
,
|
|
|
Цитата Лена @ CMapXFindFeature FoundObject = m_Map.GetLayers().Item("US Major Cities").GetFind().Search("Columbia","SC"); Цитата Лена @ Set FindCityObject = Map1.Layers("US Top 20 _Cities").Find.Search(txtCityName.Text, txtStateName.Text) в обоих примерах Search имеет 2 параметра - в данных случаях, название города и название штата. Цитата Лена @ FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Edit1->Text)); Второй параметр допустимо не указывать (NULL по умолчанию для wchar_t) или как? |
Сообщ.
#12
,
|
|
|
Из той справки что я имею вот его описание OBJECT.Search (Address, [ Boundary ] )
N1 первый параметр №2 - второй. 1. A string, which is the name of the object or street address that you want to find. For example, "Rensselaer, 6 Georgian Ct,", "London", or "3 Elm Street". 2. A string, which is the name of the refining boundary object. Used when a refining layer is specified. For example, "NY", "21135". If a refine layer has been set, this argument is required; otherwise it is optional. Я так понимаю, что параметр не обязатлен и самое главное я перевожу код из раней версии Builder и там у человека пусто и все работает. Поэтому я опустила этот параметр. find = l_A.OlePropertyGet("Find").OleFunction("Search", Table2->FieldValues["ID"], "" );//из ранеей версии, видно что пусто. Еще если у MAX2002 есть код на Делфи для поиска объекта, выложите его пожалуйста, А то у меня на VC и VBA под рукой. |
Сообщ.
#13
,
|
|
|
Цитата Лена @ FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Edit1->Text)); Цитата Лена @ find = l_A.OlePropertyGet("Find").OleFunction("Search", Table2->FieldValues["ID"], "" ); Аленушка, разницу видишь? У предшественника - 2 параметра - Table2->FieldValues["ID"] и "" . |
Сообщ.
#14
,
|
|
|
Пробывала передать пустые кавычки, тоже не находит:
CMapXFindFeature *FoundFeature; OleVariant unusedParam, unusedParam1; unusedParam.operator =(48); AnsiString id2 = ""; unusedParam1.operator =(id2); FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString),unusedParam1); |
Сообщ.
#15
,
|
|
|
Лена, попробуй так
FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString), WideString("")); |
Сообщ.
#16
,
|
|
|
Цитата Coala @ Лена, попробуй так FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString), WideString("")); Вот тут и начинаются проблемы с тем, что нет толковой документации именно для Builder. Дело в том, что например, метод Search в Builder требует первым параметром тип wchar_t * address, а вторым tagVariant, что отличается от классического примера. Вывод только один - пока MapInfo не выпустить нормальный help к MapX он не победим в среде C++ Builder 6. Правда мне удалось многое сделать: динамичиская загрузка слоев, масштабирование, замер расстояний, печать выделенной области, а вот важную операцию -поиск объекта не удалось. Я даже задала вопрос на форуме MapInfo, а в ответ на свой код получила: What value are you passing in Find.Search? I don't see the value that you're trying to find in your code? Cindy MapInfo Technical Support Я им пишу "так покажите фрагмент кода как правильно!", а они молчат как партизаны! |
Сообщ.
#17
,
|
|
|
Лена, отправь им то, что я тебе предложил...
Вполне возможно, что tagVariant - это 0 [по умолчанию]? Цитата Coala @ таких программеров (утопить/дать Нобелевку - выбрать по желанию) оставить только утопить и начать с этой самой Cindy c ее I don't see the value that you're trying to find in your code? К сожалению, в таких случаях приходится пробовать методом тыка P.S. Есть дилер MapInfo (в том числе) фирма Резидент, если память не изменяет - www.resident.ru (можно поискать в яндексе). Эти ребята пишут и сами - может быть, они смогут помочь... |
Сообщ.
#18
,
|
|
|
ну вообщето это я делал, только наоборот, поиск к точке ближайших объектов, и все работало, только осталось найти старые исходники...
|
Сообщ.
#19
,
|
|
|
Цитата MAX2002 @ ну вообщето это я делал, только наоборот, поиск к точке ближайших объектов, и все работало, только осталось найти старые исходники... MAX2002, буду очень признательна, если найдутся ЛЮБЫЕ фрагменты вашего кода, и вы их мне вышлите! Даже если вы их найдете через месяц, все равно они будут актуальны. Мне надо обязательно доделать свой проект! Я от этого MapX, скоро стану похожа на этот смайлик: |
Сообщ.
#20
,
|
|
|
Лена, Вы бы выложили здесь TLB от MapX ActiveX или сгенерированный на его основе Builder'ом заголовочный файл. Возможно, что уже давно бы получили ответ.
|
Сообщ.
#21
,
|
|
|
Цитата Лена @ сгенерированный на его основе Builder'ом заголовочный файл Как всегда - в лузу!!! Мог бы и сам давно сообразить... ---- Намудрил с цитатами, trainer, sorry |
Сообщ.
#22
,
|
|
|
Цитата trainer @ Лена, Вы бы выложили здесь TLB от MapX ActiveX или сгенерированный на его основе Builder'ом заголовочный файл. Возможно, что уже давно бы получили ответ. Вот h, cpp, tlb: Прикреплённый файлMapX.zip (94.65 Кбайт, скачиваний: 119) |
Сообщ.
#23
,
|
|
|
Ага, есть - в MapXLib_TLB.h
Mapxlib_tlb::CMapXFeatures* __fastcall Search(BSTR strWhere, VARIANT Variables/*[opt]*/= TNoParam()); Народ, кто пограмотней в ActiveX - подскажите! |
Сообщ.
#24
,
|
|
|
Вот еще папка с файлами примеров для Делфи, которая идет в стандартной поставке MapX. Сейчас пытаюсь адаптировать фрагменты кода для Builder, но пока особого успеха нет из-за разных параметров в функциях.
Прикреплённый файлSamples.zip (98.72 Кбайт, скачиваний: 124) |
Сообщ.
#25
,
|
|
|
А какое значение возвращает FindRC?
|
Сообщ.
#26
,
|
|
|
После выполнения строки:
FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString)); FoundFeature становиться равным :04670C0 А строка FoundFeature->get_FindRC() равной :0040D270 Что конкретно делает метод get_FindRC() я не знаю, но во всех примерах он фигурирует, как метод проверки, что объект найден. Ниже переделанный мной из Делфийского примера, который я выложила выше. MapX не ругается везде предлагает после -> свои функции. Однако во время выполнения проблема. Я не понимаю, например, что такое VT_DISPATCH и зачем оно? Обидно, что мое приложение практически готово и многое умеет делать. Вот только с поиском проблема. OleVariant unusedParam, unusedParam1; AnsiString id = ""; unusedParam.operator =(48);//номер слоя, а в Делфи по имени unusedParam1.operator =(id); CMapXLayer * lyr; CMapXDataset *ds; CMapXFindFeature *FoundObj; Variant nothing; nothing.VType = VT_DISPATCH; lyr = Form1->Map1->Layers->_Item(unusedParam); ds = Form1->Map1->DataSets->_Item(unusedParam); lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(unusedParam); lyr->Find->FindField = ds->Fields->_Item(unusedParam); //MapX выдает ошибку на этой строке ниже, если убрать три строки с VarAsType ошибка будет на строке с ф-цией Search lyr->Find->RefineLayer = VarAsType(nothing, VT_DISPATCH); lyr->Find->RefineDataset = VarAsType(nothing, VT_DISPATCH); lyr->Find->RefineField = VarAsType(nothing, VT_DISPATCH); FoundObj = lyr->Find->Search(WideString(Table2->FieldValues["ID"]),unusedParam1); if (FoundObj->get_FindRC() % 10 == 1) { ShowMessage("Yes"); Form1->Map1->Zoom = 30; //если объект найден карта увеличивается и помещает его в центре Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } Родной код на Делфи в архиве выше в папке FIND |
Сообщ.
#27
,
|
|
|
Лена, я спрашивал не адреса объектов и функций - они мне неинтересны, а значение, возвращаемое функцией get_FindRC(или, что тоже самое - значение свойства FindRC). Или есть проблемы с сохранением значения в переменную?
Добавлено Цитата Лена @ Возвращает код результата поиска - успешно/неуспешно, почему неуспешно и т.д. Что конкретно делает метод get_FindRC() я не знаю |
Сообщ.
#28
,
|
|
|
Цитата Лена @ Обидно, что мое приложение практически готово и многое умеет делать Обидно то, что ты не понимаешь - как оно работает. trainer Цитата Coala @ Mapxlib_tlb::CMapXFeatures* __fastcall Search(BSTR strWhere, VARIANT Variables/*[opt]*/= TNoParam()); первый параметр - это WideString, а что за бред во втором параметре , не силен я в OLE-заморочках... Лена Цитата Лена @ //MapX выдает ошибку на этой строке ниже, если убрать три строки с VarAsType ошибка будет на строке с ф-цией Search lyr->Find->RefineLayer = VarAsType(nothing, VT_DISPATCH); lyr->Find->RefineDataset = VarAsType(nothing, VT_DISPATCH); lyr->Find->RefineField = VarAsType(nothing, VT_DISPATCH); FoundObj = lyr->Find->Search(WideString(Table2->FieldValues["ID"]),unusedParam1); что за ошибки-то - либо своими словами, либо скриншотики... |
Сообщ.
#29
,
|
|
|
>Обидно то, что ты не понимаешь - как оно работает.
То, что я уже сделала в своем приложении, я понимаю, как работает: динамическая загрузка слоев, различные инструменты для карты, замеры расстояний, печати областей и т.п. Там понятна каждая строчка. А вот поиск объекта В случае использования метода if (FoundFeature->get_FindRC() % 10 == 1) и в случае свойства if (FoundFeature->FindRC % 10 == 1) Возвращает в i цифру минус 3 short i = FoundFeature->FindRC; Очевидно это строка содержит ошибку: FoundFeature = Form1->Map1->Layers->_Item(unusedParam)->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString)); Со вторым параметром функции не совсем все понятно. Пробую так: OleVariant unusedParam1; AnsiString id = ""; unusedParam1.operator =(id); и использовать unusedParam1, но тоже ошибка. Все таки код из Делфи мне кажется более правильный, более подробно с моими предположительными комментариями: OleVariant unusedParam, unusedParam1; AnsiString id = ""; unusedParam.operator =(48);//номер слоя unusedParam1.operator =(id); CMapXLayer * lyr; CMapXDataset *ds; CMapXFindFeature *FoundObj; //cюда найденную улицу Variant nothing; nothing.VType = VT_DISPATCH; //готовиться какой-то дополнительный параметр lyr = Form1->Map1->Layers->_Item(unusedParam); //слою присваивается слой улицы по номеру (в делфи по имени) ds = Form1->Map1->DataSets->_Item(unusedParam); //очевидна инициализация ds данными из слоя улиц lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(unusedParam);//очевидно привязка данных к слою lyr->Find->FindField = ds->Fields->_Item(unusedParam); //привязка полей? //три строки ниже явно готовить второй параметр для ф-ции Search, чтобы он был пустым //MapX выдает ошибку если не закоментрировать эти строки с VarAsType lyr->Find->RefineLayer = VarAsType(nothing, VT_DISPATCH); // ошибка см. рисунок lyr->Find->RefineDataset = VarAsType(nothing, VT_DISPATCH);//VarAsType требует const Variant &V и unsignet short AVarType lyr->Find->RefineField = VarAsType(nothing, VT_DISPATCH); //если три строки выше закомментированы, то ошибка в строке ниже //тут явная ошибка я передаю unusedParam1, а надо что-то другое. В делфи передается '', если убрать unusedParam1 ошибка остается //подготовительные мероприятия закончены далее строка поиска FoundObj = lyr->Find->Search(WideString(Table2->FieldValues["ID"]),unusedParam1); if (FoundObj->FindRC % 10 == 1) //здесь минус три { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } При написании FoundObj = lyr->Find->Search( получаю в скобках первый параметр wchar_t * address, второй tagVariant RefineBoundary который каким-то образом надо подготовить и указать что он пустой. Описание вторго параметра ф-ции Search но для Делфи: A string, which is the name of the refining boundary object. Used when a refining layer is specified. For example, "NY", "21135". If a refine layer has been set, this argument is required; otherwise it is optional. Очевидно что мы не определяем refine layer поэтому он должен быть optional т.е. пустой, как в коде приложения который работает, но в ранней версии Builder Напомню строки того, как это реализовывалась в ранней версии Builder Variant l_A, ds_A; Variant find; l_A.OlePropertyGet("Find").OlePropertySet("FindDataset", ds_A); l_A.OlePropertyGet("Find").OlePropertySet("FindField", ds_A.OlePropertyGet("Fields","ID")); Table2->First(); find = l_A.OlePropertyGet("Find").OleFunction("Search", Table2->FieldValues["ID"], "" ); Прикреплённая картинка
|
Сообщ.
#30
,
|
|
|
С кодом Делфи, может понятнее:
OleVariant unusedParam; unusedParam.operator =(48);//number of layer CMapXLayer * lyr; CMapXDataset *ds; CMapXFindFeature *FoundObj; Table2->First(); Variant nothing; //TVarData(nothing).VType := varDispatch; from Delhi TVarData(nothing).VType = varDispatch; //lyr := currentMap.Layers.Item[findLayer.text]; from Delhi lyr = Form1->Map1->Layers->_Item(unusedParam);//number of layer, no Layer name function in C++Builder /* from Delhi ds := currentMap.Datasets.Item[findDataset.text]; lyr.Find.FindDataset := currentMap.Datasets.Item[findDataset.text]; lyr.Find.FindField := ds.Fields.Item[findField.text]; */ ds = Form1->Map1->DataSets->_Item(unusedParam); lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(unusedParam);// lyr->Find->FindField = ds->Fields->_Item(unusedParam); /* from Delhi lyr.Find.RefineLayer := VarAsType(nothing, varDispatch); lyr.Find.RefineDataSet := VarAsType(nothing, varDispatch); lyr.Find.RefineField := VarAsType(nothing, varDispatch); */ lyr->Find->RefineLayer = VarAsType(nothing, varDispatch); //problem??? lyr->Find->RefineDataset = VarAsType(nothing, varDispatch); lyr->Find->RefineField = VarAsType(nothing, varDispatch); FoundObj = lyr->Find->Search(WideString(Table2->FieldValues["ID"]),what second parameter here?); if (FoundObj->FindRC % 10 == 1) { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } |
Сообщ.
#31
,
|
|
|
А откуда уверенность, что это именно 48-й слой? Чем не нравится обращение к слою по имени?
|
Сообщ.
#32
,
|
|
|
Я через свойство lyr->Name в операторе if предварительно убедилась, что имя этого слоя равно "_ROAD" именно это улицы. Мало того я могу во время выполнения, используя MapX просмотреть в специальном окне расположение слоев после их динамической загрузки. Слой "_ROAD" на последнем 48 месте.
Я бы с удовольствием хотела обратиться по имени слоя в методе _Item в Builder, но он принимает параметр tadVariant index, раз index значит по номеру, поэтому я не знаю, как передать по имени "_ROAD" как если бы это было в Делфи. Вот в Делфи метод Item принимает имя слоя. |
Сообщ.
#33
,
|
|
|
Цитата Лена @ Раз VARIANT, значит принимает значения разных типов. Это ActiveX - значит интерфейс определяется компонентом, а не языком. Не может быть такого, чтобы один и тот же компонент принимал текст из программы на одном языке и не принимал на другом.tadVariant index, раз index значит по номеру Цитата Лена @ Так и передать. поэтому я не знаю, как передать по имени "_ROAD" |
Сообщ.
#34
,
|
|
|
Спасибо, в понедельник попробую. Проект на работе в офисе, мысль понятна. Просто слово index мною однозначно интенпритировалось в данном контексте как номер!
Добавлено Правда, пока не понимаю как передать пустой второй параметр в функции Search. |
Сообщ.
#35
,
|
|
|
Цитата Лена @ Правда, пока не понимаю как передать пустой второй параметр в функции Search. В этом - весь идиотизм ActiveX, написанных шибко продвинутыми программерами Особливо для переменной типа Variant...Попробуй методом тыка - 0, NULL, "", EmptyParam (как в Ворде)... |
Сообщ.
#36
,
|
|
|
void __fastcall TFStr_Search::Button3Click(TObject *Sender) { Table2->First(); OleVariant unusedParam; unusedParam.operator =(48);//номер слоя CMapXLayer * lyr = Form1->Map1->Layers->_Item(unusedParam); AnsiString id = "_ROAD"; //имя слоя WideString wsid = WideString(id); //---- начало проверки ------------------- if(WideString(lyr->Name) == wsid) { Form1->Label5->Caption = (WideString(lyr->Name)); Application->MessageBox("Cëîé_ROAD","Проверка",MB_ICONEXCLAMATION); } //----- конец проверки. Успешно --------- OleVariant unusedParam1; //готовлю параметр для _Item в цепочке поиска unusedParam1.operator =(id); OleVariant unusedParam2; //готовлю пустой параметр для Search unusedParam2.IsEmpty(); CMapXFindFeature *FoundObj; FoundObj = Form1->Map1->Layers->_Item(unusedParam1)->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString),unusedParam2); if (FoundObj->FindRC % 10 == 1) { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } } Все время попадаю в секцию else. Если написать в Search первым параметром WideString(Table2->FieldValues["ID"]) вместо WideString(Table2->FieldByName("ID")->AsString возникает исключение (см.рисунок). Прикреплённая картинка
|
Сообщ.
#37
,
|
|
|
Цитата Лена @ Вообще его не указывать. На то и существуют в C++ параметры со значениями по умолчанию, что бы в данном случае вызов без указания второго параметра был бы эквивалентен пустому параметру. Правда, пока не понимаю как передать пустой второй параметр в функции Search. |
Сообщ.
#38
,
|
|
|
Цитата Лена @ Слой "_ROAD" на последнем 48 месте А индексация начинается с 0, или с 1? |
Сообщ.
#39
,
|
|
|
Индексация в MapX начинается с 1, это относиться к слоям и фичам на слое...
|
Сообщ.
#40
,
|
|
|
Цитата Coala @ Mapxlib_tlb::CMapXFeatures* __fastcall Search(BSTR strWhere, VARIANT Variables/*[opt]*/= TNoParam()); Если следовать букве...то первый параметр типа BSTR должен создаваться примерно так: WideString layName; ...Search(layName.BSTR(),...); Что касается второго параметра - Лена, что за метод TNoParam(), что там про это дело в хелпе сказано? |
Сообщ.
#41
,
|
|
|
Цитата Coala @ Цитата Coala @ Mapxlib_tlb::CMapXFeatures* __fastcall Search(BSTR strWhere, VARIANT Variables/*[opt]*/= TNoParam()); Если следовать букве...то первый параметр типа BSTR должен создаваться примерно так: WideString layName; ...Search(layName.BSTR(),...); Что касается второго параметра - Лена, что за метод TNoParam(), что там про это дело в хелпе сказано? Cпасибо буду пробывать. Мысль layName.BSTR(),...); интересная. По поводу вторго параметра, есть тольк информация в файле TLB и описание его для Делфи (ниже). Описание методов и примеров для Builder нет. A string, which is the name of the refining boundary object. Used when a refining layer is specified. For example, "NY", "21135". If a refine layer has been set, this argument is required; otherwise it is optional. В Builder этот параметр не тип string, а Variant и судя по коду переделываемого мной приложения он не нужен. Речь идет о каком-то refining boundary object, котрый мы не определяем и поэтому в первом приложении было так find = l_A.OlePropertyGet("Find").OleFunction("Search", Table2->FieldValues["ID"], "" ); второй параметр пустой. |
Сообщ.
#42
,
|
|
|
Цитата Лена @ второй параметр пустой Он не пустой, он - пустая строка. Меня больше всего смущает его описание в хидере - тип VARIANT. Это в Дельфи - Variant и VARIANT - одно и то же... |
Сообщ.
#43
,
|
|
|
IsEmpty не делает объект пустым, а проверяет объект на пустоту
|
Сообщ.
#44
,
|
|
|
Цитата trainer @ IsEmpty не делает объект пустым, а проверяет объект на пустоту Тогда что выглядит более правильным: OleVariant unusedParam2; unusedParam2.IsNull(); //для второго параметра Search или OleVariant unusedParam2; AnsiString Second =""; unusedParam2.operator =(Second); |
Сообщ.
#45
,
|
|
|
Лена, Variant и OleVarint - разные типы! Может тут...
|
Сообщ.
#46
,
|
|
|
Coala, кончай нести чушь и запутывать Лену.
Лена, слой "_ROAD" индексирован? И это точно он содержит улицы? На всякий случай: road по-английски - дорога, улица - street. Хотя, конечно, при создании слоя его могли назвать как угодно. Добавлено Цитата Лена @ Ни то, ни другое. Объект, инкапсулирующий VARIANT, изначально создается пустым. В первом случае IsNull() не делает никаких осмысленных действий, во втором - объект получает значение "пустая строка". Unassigned и пустая строка, строго говоря - разные значения(хотя конкретный компонент может интерпретировать их одинаково).Тогда что выглядит более правильным Добавлено И почему все время параметры называются "Неиспользуемый параметр"(unusedParam)? Чтобы врагов запутать? Добавлено Если FindRC действительно возвращает -3, то это какая-то недокументированная ошибка(или случайное значение), ибо это не соответствует ни одному из кодов результата операции поиска или коду ошибки. |
Сообщ.
#47
,
|
|
|
Цитата trainer @ Coala, кончай нести чушь и запутывать Лену. Look at yourself Оба на кофейной гуще гадаем... |
Сообщ.
#48
,
|
|
|
Всем мои извинения...малость погавкались...
Цитата trainer @ Если FindRC действительно возвращает -3, то это какая-то недокументированная ошибка(или случайное значение), ибо это не соответствует ни одному из кодов результата операции поиска или коду ошибки. Тут trainer прав. Поэтому (может быть, я уже всех достал), но возникает два вопроса - что возвращает строка Цитата Лена @ FoundObj = Form1->Map1->Layers->_Item(unusedParam1)->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString),unusedParam2); т.е. что именно сидит в FoundObj - есть ли что-нибудь в хелпах по поводу кодов ошибок ----------------------------- Второй параметр Search - TNoParam() определен в utilcls.h Можно попробовать следующее // в хидере TNoParam * prm; // в FormCreate prm = new TNoParam(); ..... ...->Search(wide_string.bstr(), prm); |
Сообщ.
#49
,
|
|
|
Мне кажется, что я сейчас выкладываю код самый близкий к правильному. В нем ошибка. Если есть мысли, подскажите как ее обойти.
void __fastcall TFStr_Search::Button2Click(TObject *Sender) { OleVariant Param1; Param1.operator =(48); //номер слоя CMapXLayer * lyr; CMapXDataset *ds; Table2->First(); lyr = Form1->Map1->Layers->_Item(Param1); lyr->Name; //просто проверка в точке отстановки, все нормально /* from Delhi lyr, ds: variant; ds := Map1.Datasets.Item[findDataset.text]; lyr.Find.FindDataset := Map1.Datasets.Item[findDataset.text]; lyr.Find.FindField := ds.Fields.Item[findField.text]; Где findDataset, findDataset, findField, FindItem это тексты из ComboBox примера. я не могу объявить lyr, ds как Variant, потому что не смогу строить цепочку lyr-> */ //подготовка lyr для последующего вызова Search по аналогии c Делфи ds = Form1->Map1->DataSets->_Item(Param1); //здесь в точке останова ds = NULL?! lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Param1); lyr->Find->FindField = ds->Fields->_Item(Param1); //ds = NULL поэтому исключение. Ошибка только во время выполнения. //код ниже, по моему мнению, правильный CMapXFindFeature* feature; CMapXLayerFind* lfind = lyr->get_Find(); if(lfind!=NULL) { feature = lfind->Search(WideString(Table2->FieldByName("ID")->AsString).c_bstr()); } if(feature!=NULL) { WideString Name = feature ->get_Name(); Form1->Label5->Caption = Name; } if (feature ->FindRC % 10 == 1) { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = feature ->get_CenterX(); Form1->Map1->CenterY = feature ->get_CenterY(); } else { ShowMessage("No"); } }// конец обработчика Как правильно реализовать эту строчку: ds = Form1->Map1->DataSets->_Item(Param1);? Даже если жестко прописывать значение из базы данных, все равно ds = NULL. Строка явно не правильно мною сформирована. Самая главная просьба - не сортесь, пожалуйста, из-за этого не победимого MapX! |
Сообщ.
#50
,
|
|
|
Цитата Лена @ Самая главная просьба - не сортесь, пожалуйста, из-за этого не победимого MapX! Мы постараемся, главная проблема в том, что мы не можем смоделировать твою ситуацию - поэтому и (мягко говоря) гадаем... Все-таки попробуй ввести в Search 2 параметра - как я написал в посте № 48... |
Сообщ.
#51
,
|
|
|
Думаю в ds = Form1->Map1->DataSets->_Item(Param1); надо передать не Param1, а значение из базы данных, но пока не соображу как.
-юсртыхэю Цитата Coala @ Цитата Лена @ Самая главная просьба - не сортесь, пожалуйста, из-за этого не победимого MapX! Мы постараемся, главная проблема в том, что мы не можем смоделировать твою ситуацию - поэтому и (мягко говоря) гадаем... Все-таки попробуй ввести в Search 2 параметра - как я написал в посте № 48... Я уже пробывала и два и один. Мне кажется lyr не готов к вызову Seach. lyr-у надо предварительно указать поле из базы данных, чего раньше я не делала. И затем Seach по текущей записи в этом поле найдет, то что нужно. В коде выше я пытаюсь подготовить слой lyr. |
Сообщ.
#52
,
|
|
|
Цитата Лена @ Я уже пробывала и два я имел ввиду второй параметр класса TNoParam() - как в вызове метода, описанном в MapXLib_TLB.h |
Сообщ.
#53
,
|
|
|
Посмотрите как основательно готовиться в ранней версии Builder вызов метода Seach
Variant l_A, ds_A, find; l_A.OlePropertyGet("Find").OlePropertySet("FindDataset", ds_A); l_A.OlePropertyGet("Find").OlePropertySet("FindField", ds_A.OlePropertyGet("Fields","ID")); find = l_A.OlePropertyGet("Find").OleFunction("Search", Table2->FieldValues["ID"], "" ); инициализируется Dataset у слоя (в данном случае роль слоя это l_A) и приписывается поле ID через Fields и только после этого вызывается "Search" для текущей записи. Все мои Search раньше ничего не находили и не найдут потому что поиск мною был не поготовлен для lyr. Я попробую // в хидере TNoParam * prm; // в FormCreate prm = new TNoParam(); ..... ...->Search(wide_string.bstr(), prm); но не найдет. lyr не готов. |
Сообщ.
#54
,
|
|
|
Цитата Лена @ ds = Form1->Map1->DataSets->_Item(Param1); //здесь в точке останова ds = NULL?! По идее, у Map->DataSets должно быть свойство Count (в общем, количество этих самых доступных ДатаСетов), посмотри в отладчике чему оно равно... |
Сообщ.
#55
,
|
|
|
Цитата Лена @ Насколько я понимаю, 48-й набор данных не обязан быть источником данных для 48-го слоя. Точно также, как и слой "_ROAD" может иметь набор данных с другим именем. Слой может вообще не иметь набора данных или иметь несколько наборов данных.ds = Form1->Map1->DataSets->_Item(Param1); //здесь в точке останова ds = NULL?! Проверять надо через Form1->Map1->Layers->_Item(OleVariant(L"_ROAD"))->DataSets; |
Сообщ.
#56
,
|
|
|
Да все правильно, очевидно слой не содержит данных раз ds=NULL.
Но я не соображу, что поменять в коде ниже исходя из вашего совета? void __fastcall TFStr_Search::Button2Click(TObject *Sender) { OleVariant Param1, Param2; AnsiString NAME = "_ROAD"; AnsiString Field = "ID"; Param1.operator =(NAME);//имя слоя Param2.operator =(Field); //имя колонки в таблице CMapXLayer * lyr; CMapXDataset *ds; Table1->First(); lyr = Form1->Map1->Layers->_Item(Param1); //lyr->Name; //для проверки ОК ds = Form1->Map1->DataSets->_Item(Param1);//что тут написать? как привизать данные к lyr? lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Param1); lyr->Find->FindField = ds->Fields->_Item(Param2); CMapXFindFeature* feature; CMapXLayerFind* lfind = lyr->get_Find(); if(lfind!=NULL) { feature = lfind->Search(WideString(Table1->FieldByName("ID")->AsString).c_bstr()); } if (feature ->FindRC % 10 == 1) { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = feature ->get_CenterX(); Form1->Map1->CenterY = feature ->get_CenterY(); } else { ShowMessage("No"); } } |
Сообщ.
#57
,
|
|
|
Цитата Лена @ Я не знаю деталей реализации. Например, что из себя представляет источник данных? DAO? ADO? ODBC? RDO? Lotus Notes? OLE? Что-то еще?Но я не соображу, что поменять в коде ниже исходя из вашего совета? Для начала: void __fastcall TFStr_Search::Button2Click(TObject *Sender) CMapXDatasets * layer_datasets = Form1->Map1->Layers->_Item(OleVariant(L"_ROAD"))->DataSets; if( layer_datasets ) { if( layer_datasets->Count > 0 ) { char buffer[256]; sprintf(buffer,"Слой имеет %d источников данных",layer_datasets->Count); MessageBox(Handle,buffer,"Информация",MB_ICONINFORMATION|MB_OK); } else { MessageBox(Handle,"Слой не имеет источников данных","Ошибка",MB_ICONSTOP|MB_OK); } } else { MessageBox(Handle,"Ошибка при получении набора источников данных слоя","Ошибка",MB_ICONSTOP|MB_OK); } } |
Сообщ.
#58
,
|
|
|
Это - начало заголовка WOR-файла MapInfo:
!Workspace !Version 600 !Charset WindowsCyrillic Open Table "гидрография_L" As гидрография_L Open Table "растительность_A" As растительность_A Open Table "дорожная_сеть_L" As дорожная_сеть_L и т.д.... при этом все данные слоя/таблицы хранятся в файлах tab_name.DAT, .ID, .MAP, .TAB. Для этого набора данных MapInfo в диалоге Карта->Управление слоями дает такую последовательность: косметический слой дорожная_сеть_L гидрография_L растительность_A Вывод - не факт, что слой с номером N из диалога связан с таблицей под таким же номером... Далее - наличие косметического слоя (в AutoCAD это системный, неудаляемый и т.д.). Не надо ли учитывать его наличие при индексировании слоев? Цитата trainer @ Например, что из себя представляет источник данных? DAO? ADO? ODBC? RDO? Lotus Notes? OLE? Что-то еще? trainer, очевидно, что-то еще...Самодельное от разработчиков MapX... Лена, запусти тест trainer из предыдущего поста, возможно, появится ясность... ............ Вот тут действительно малость отморозил - если это данные объектов (семантика) из самой карты, то они в DAT-файлах (метрика соответственно в MAP)и доступ к ним идет средствами MapInfo (MapBasic, MapX, etc), а вот если это данные из внешней базы, то trainer задал справедливый вопрос |
Сообщ.
#59
,
|
|
|
trainer и Coala спасибо за помощь!
По-моему мы все в шаге от Нобелевской премии за попытку разобраться как работает MapX в среде C++ Builder Мне кажется, что в данный момент на просторах CНГ только я одна работаю с MapX в Builder Источник данных BDE таблицы dbf. trainer объясните, что зачем буква L перед кавычками в строке _Item(OleVariant(L"_ROAD"))? Прежде чем тестировать, хочу понять сам код. Наш с вами топик внимательно читал еще один человек. Я получила от него письмо. У него не установлен MapX но на основании его рекомендаций у меня получился новый код. Мне кажется я в шаге от решения: void __fastcall TFStr_Search::Button2Click(TObject *Sender) { Table2->First(); OleVariant Param1; AnsiString NAME = "_ROAD"; Param1.operator =(NAME); //имя слоя CMapXLayer * lyr; lyr = Form1->Map1->Layers->_Item(Param1); //ЕСЛИ НЕТ БАЗЫ ДАННЫХ, ПОИСК БЕСПОЛЕЗЕН, НИЧЕГО НЕ НАЙДЕТ //ПОЭТОМУ СОЗДАЕТСЯ БАЗА ДАННЫХ ДЛЯ ТОГО СЛОЯ В КОТОРОМ БУДЕТ ПОИСК Form1->Map1->DataSets->Add(miDataSetLayer, lyr, Param1); //здесь у меня ошибка, надо не CMapXLayer а вариант для второго параметра lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Param1);//заносим в lyr CMapXDataset *ds = Form1->Map1->DataSets->_Item(Param1); //цикл для теста for(int i = 1; i <= ds->Fields->Count; i++) { ShowMessage(ds->Fields->_Item(Param1)->Name); // Чтобы удостовериться в наличии поля ID } lyr->Find->FindField = ds->Fields->_Item(исходя из цикла);//ID CMapXFindFeature *FoundObj; FoundObj = lyr->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString)); if (FoundObj->FindRC % 10 == 1) //константа -3 ищ справки будет означаеть, что ничего не найдено. { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } } Form1->Map1->DataSets->Add(miDataSetLayer, lyr, Param1); Как я понимаю, должно быть похоже на это: Map1->DataSets->Add(miDataSetLayer, lyr, lyr->Name); Первый параметр предопределенная константа, два других варианты. Добавлено Раньше я выложила код на форуме MapInfo, там не было еще метода Add: вот сегодня ответ I don't see anywhere in this code where you issue a Datasets.Add. Is that somewhere else in your code? If you issue Map1.Datasets.Count, does it return a number greater than 0? Cindy MapInfo Technical Support Значит мы движемся в ПРАВЕЛЬНОМ направлении метод ADD!!!! |
Сообщ.
#60
,
|
|
|
Цитата Лена @ По-моему мы все в шаге от Нобелевской премии за попытку разобраться как работает MapX в среде C++ Builder Скорее - от белой рубахи до пола с очччччень длинными рукавами Лена, мне действительно такая рубаха скоро понадобится! Цитата Лена @ Источник данных BDE таблицы dbf. BDE - не источник данных, а механизм доступа к ним. Рубаху мне, рубаху Если я правильно понимаю вопрос, то MapX создан для работы с внутренним форматом MapInfo (DAT, ID, MAP, TAB - файлами или цифровой картой), если MapX позволяет пристегнуть и внешние базы - то причем тут BDE, а если не позволяет, то как MapX можно с ним скрестить? Слои карты и таблицы базы связаны между собой или как? |
Сообщ.
#61
,
|
|
|
Цитата Coala @ >Слои карты и таблицы базы связаны между собой или как? В одной таблице dbf, например в одной из колонок данными могут быть пути на эти самые файлы TAB. В момент старта приложения я указываю MapX брать для загрузки слоев из этой колонки эти самые пути. MapX в цикле бежит по колонке в которой например такая запись С:/MYmap/road.map берет и загружает этот самый road.map затем переходит к другой записи. 48 записей 48 слоев получаю в MapX. Соответственно на форме обыкновенные Table1, Table2, … и их DataSourse. Соответственно есть и алиас в Builder для доступа к таблицам. Ниже код загрузки всех слоев: void __fastcall TForm1::Button3Click(TObject *Sender) { DataModule1->Table5->First(); AnsiString S; S = DataModule1->Table5->FieldValues["FILE"]; OleVariant unusedParam,unusedParam1; unusedParam1.operator =(0); int i = 0; for(Cnt_Lyr=1; Cnt_Lyr<=DataModule1->Table5->RecordCount; Cnt_Lyr++) { unusedParam.operator =(S); Map1->Layers->Add(unusedParam, unusedParam1); Map1->DataSets->Add(miDataSetLayer,unusedParam); void __fastcall TForm1::Button3Click(TObject *Sender) { DataModule1->Table5->First(); AnsiString S; S = DataModule1->Table5->FieldValues["FILE"]; OleVariant unusedParam,unusedParam1, nusedParam2; unusedParam1.operator =(0); int i = 0; for(Cnt_Lyr=1; Cnt_Lyr<=DataModule1->Table5->RecordCount; Cnt_Lyr++) { unusedParam.operator =(S); Map1->Layers->Add(unusedParam, unusedParam1); Map1->DataSets->Add(miDataSetLayer,unusedParam); unusedParam2.operator =(Cnt_Lyr); //для проверки Layer[i] = Map1->Layers->_Item(unusedParam2); if(!Layer[i])// { Label1->Caption = S; Application->MessageBox("Не загрузил...","Ошибка",MB_ICONEXCLAMATION); //return; } DataModule1->Table5->Next(); S = DataModule1->Table5->FieldValues["FILE"]; i++; } } //для проверки Layer[i] = Map1->Layers->_Item(unusedParam2); if(!Layer[i])// { Label1->Caption = S; Application->MessageBox("Не загрузил...","Ошибка",MB_ICONEXCLAMATION); //return; } DataModule1->Table5->Next(); S = DataModule1->Table5->FieldValues["FILE"]; i++; } } Добавлено Лишнее скопировла в код, но общий смысл должен быть понятен. Добавлено без лишнего void __fastcall TForm1::Button3Click(TObject *Sender) { DataModule1->Table5->First(); AnsiString S; S = DataModule1->Table5->FieldValues["FILE"]; OleVariant unusedParam,unusedParam1, unusedParam2; unusedParam1.operator =(0); int i = 0; for(Cnt_Lyr=1; Cnt_Lyr<=DataModule1->Table5->RecordCount; Cnt_Lyr++) { unusedParam.operator =(S); Map1->Layers->Add(unusedParam, unusedParam1); Map1->DataSets->Add(miDataSetLayer,unusedParam); unusedParam2.operator =(Cnt_Lyr); //для проверки Layer[i] = Map1->Layers->_Item(unusedParam2); if(!Layer[i])// { Label1->Caption = S; Application->MessageBox("Не загрузил...","Ошибка",MB_ICONEXCLAMATION); //return; } DataModule1->Table5->Next(); S = DataModule1->Table5->FieldValues["FILE"]; i++; } } |
Сообщ.
#62
,
|
|
|
Если я правильно понял, то DBF по большому счету ни при чем.
Ты считываешь имена файлов (MAP или TAB, у тебя в посте нестыковочка) и подставляешь их в MapX (добавляешь слои в карту). Вопрос: Цитата Лена @ Map1->DataSets->Add(miDataSetLayer,unusedParam); - кто такой miDataSetLayer |
Сообщ.
#63
,
|
|
|
>- кто такой miDataSetLayer
Type of Dataset being added takes a DatasetTypeConstants value. typedef enum DatasetTypeConstants { miDataSetDAO = 1, miDataSetODBC = 2, miDataSetUnbound = 3, miDataSetGlobalHandle = 4, miDataSetOLEData = 5, miDataSetLayer = 6, miDataSetNotesView = 7, miDataSetNotesQuery = 8, miDataSetSafeArray = 9, miDataSetDelphi = 1010, miDataSetDelphi4 = 1011, miDataSetDelphi5 = 1012, miDataSetDelphi6 = 1013, miDataSetADO = 12, miDataSetRDO = 13, miDatasetXML = 14, miDataSetOCI = 15 } DatasetTypeConstants; больше в справке ничего нет. Добавлено Может мне выложить help файл для MapX5.0 на ftp сервере? Он 2.6 Мг. |
Сообщ.
#64
,
|
|
|
Цитата Лена @ Map1->DataSets->Add(miDataSetLayer,unusedParam); Ага, ты добавляешь в коллекцию наборов данных именно слой с именем файла из DBF в unusedParam - кстати, все-таки MAP-файл, DAT-файл или TAB-файл? |
Сообщ.
#65
,
|
|
|
S = DataModule1->Table5->FieldValues["FILE"];
unusedParam.operator =(S); Map1->Layers->Add(unusedParam, unusedParam1); В поле FILE строки типа С:/MYmap/road.map, С:/MYmap/building.map... соотвествнно MapX добовляет road.map, building.map и т.д. |
Сообщ.
#66
,
|
|
|
Цитата Лена @ соотвествнно MapX добовляет road.map, building.map и т.д. Yes, mam!!! А кто добавляет саму семантику из DAT-файлов??? Лена, если ты после такой загрузки видишь в среде MapInfo карту, то выдает ли MapInfo информацию по ее объектам? |
Сообщ.
#67
,
|
|
|
Цитата Coala @ MapInfo карту, то выдает ли MapInfo информацию по ее объектам? Да. MapX все показывает. Вижу все 48 карт. Код ниже позволяет посмотреть что находиться в MapX void __fastcall TForm1::Button1Click(TObject *Sender) { OleVariant unusedParam; Map1->Layers->LayersDlg(unusedParam,unusedParam); int kol = Map1->Layers->Count; Label1->Caption = "Всего слоев: " + IntToStr(kol); } Добавлено В моем примере осталось правильно сформировать метод Add. |
Сообщ.
#68
,
|
|
|
Цитата Лена @ Да. MapX все показывает. Вижу все 48 карт. Я не это спрашиваю... В MapInfo в тулбаре Операции нажми на кнопочку i и ткни мышой в любой объект карты... |
Сообщ.
#69
,
|
|
|
Да, конечно показывает. Открыла карту _ROAD. При шелчке получаю окно с информацией какое ID. Карты все рабочие, из раннего приложения.
|
Сообщ.
#70
,
|
|
|
Сообщ.
#71
,
|
|
|
Цитата Coala @ Ну если действительно есть вся информация по ОБЪЕКТУ (как на рисунке), то ты где-то рядом... Да. У меня примерно так. Только еще пункт ID присуствует. |
Сообщ.
#72
,
|
|
|
Все подводные камни проверили, остался последний - Search
|
Сообщ.
#73
,
|
|
|
C Seach у нас тоже порядок. Осталось прицепить к слою DataSets. Ведь не даром мне раньше написали о моем коде, когда не было в нем метода ADD:
I don't see anywhere in this code where you issue a Datasets.Add. Is that somewhere else in your code? If you issue Map1.Datasets.Count, does it return a number greater than 0? Cindy MapInfo Technical Support Теперь у меня так: void __fastcall TFStr_Search::Button2Click(TObject *Sender) { Table2->First(); OleVariant Param1, Param2; AnsiString NAME = "_ROAD"; AnsiString Field = "ID"; Param1.operator =(NAME); Param2.operator =(Field); CMapXLayer * lyr; lyr = Form1->Map1->Layers->_Item(Param1); Form1->Map1->DataSets->Add(miDataSetLayer,Param1); //проблема! Должно быть что-то типа Form1->Map1->DataSets->Add(miDataSetLayer,lyr,lyr->name);? lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Param1); CMapXDataset *ds = Form1->Map1->DataSets->_Item(Param1); //цикл для теста в коде он не нужен for(int i = 1; i <= ds->Fields->Count; i++) { Param1.operator = (i); ShowMessage(ds->Fields->_Item(Param1)->Name); } lyr->Find->FindField = ds->Fields->_Item(Param2); CMapXFindFeature *FoundObj; FoundObj = lyr->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString)); if (FoundObj->FindRC % 10 == 1) { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } } |
Сообщ.
#74
,
|
|
|
Цитата Лена @ У меня он не только не установлен, я вообще никогда не работал с картографической информацией и в живую MapX и подобные не видел. У него не установлен MapX но на основании его рекомендаций у меня получился новый код. Цитата Лена @ L"_ROAD" - это строка в кодировке Unicode - каждый символ имеет тип не char, а wchar_t. Можно также писать OLETEXT("_ROAD")trainer объясните, что зачем буква L перед кавычками в строке _Item(OleVariant(L"_ROAD"))? Так что показал мой код? Поле FILE таблицы DataModule1->Table5 содержит путь к MAP- или DBF-файлу? Добавлено Цитата Лена @ Это практически то же самое, что и должен делать приведенный мною код в Поиск объекта (сообщение #848560), только для конкретного слоя. Я так понимаю, что я зря все это пишу. If you issue Map1.Datasets.Count, does it return a number greater than 0? |
Сообщ.
#75
,
|
|
|
Код с буквой L не работал, а так работает, но пишет, что слой не имеет источника данных.
void __fastcall TForm1::Button5Click(TObject *Sender) { OleVariant Param1; AnsiString NAME = "_ROAD"; Param1.operator =(NAME); CMapXDatasets * layer_datasets = Form1->Map1->Layers->_Item(Param1)->DataSets; if( layer_datasets ) { if( layer_datasets->Count > 0 ) { char buffer[256]; sprintf(buffer,Слой имеет %d источников данных,layer_datasets->Count); MessageBox(Handle,buffer,"Информация",MB_ICONINFORMATION|MB_OK); } else { MessageBox(Handle,"Слой не имеет источников данных","Ошибка",MB_ICONSTOP|MB_OK); } } else { MessageBox(Handle,"Ошибка при получении источников данных слоя","Ошибка",MB_ICONSTOP|MB_OK); } } Строка: long x = Form1->Map1->DataSets->Count; возвращает 0 Поле FILE таблицы DataModule1->Table5->FieldValues["FILE"]; содержит путь к TAB файлам карт. Так организовала всю загрузку карт: void __fastcall TForm1::Button3Click(TObject *Sender) { DataModule1->Table5->First(); AnsiString S; S = DataModule1->Table5->FieldValues["FILE"]; OleVariant unusedParam,unusedParam1,unusedParam2; unusedParam1.operator =(0); int i = 0; for(Cnt_Lyr=1; Cnt_Lyr<=DataModule1->Table5->RecordCount; Cnt_Lyr++) { unusedParam.operator =(S); Map1->Layers->Add(unusedParam, unusedParam1); Map1->DataSets->Add(miDataSetLayer,unusedParam);// значит тут тоже проблема unusedParam2.operator =(Cnt_Lyr); //тест Layer[i] = Map1->Layers->_Item(unusedParam2); if(!Layer[i]) { Label1->Caption = S; Application->MessageBox("Не загрузил...","Ошибка",MB_ICONEXCLAMATION); } AnsiString id = "_ROAD"; String sid = String(id); WideString wsid = WideString(sid); if(WideString(Layer[i]->Name) == wsid) { Label5->Caption = IntToStr(i); Application->MessageBox("Слой _ROAD","Проверка",MB_ICONEXCLAMATION); } DataModule1->Table5->Next(); S = DataModule1->Table5->FieldValues["FILE"]; i++; } } Буду разбираться с Map1->DataSets->Add(miDataSetLayer,unusedParam); этого кода чтобы увидеть осмысленное число в long x = Form1->Map1->DataSets->Count; Добавлено Похоже надо так организовать подгрузку данных: CMapXLayer * LYR[100]; LYR[0] = Map1->Layers->Add(unusedParam, unusedParam1); Map1->DataSets->Add(miDataSetLayer,Variant(LYR[0])); Сейчас все проверю. Сообщу. Добавлено YES!!! Код выше показал, что x стал 48. Иду дальше! |
Сообщ.
#76
,
|
|
|
Опытным путем пришла к такому коду, естественно он с моей ошибкой
void __fastcall TFStr_Search::Button2Click(TObject *Sender) { Table2->First(); OleVariant Param1, Param2; AnsiString NAME = "_ROAD"; AnsiString Field = "ID"; Param1.operator =(NAME); Param2.operator =(Field); CMapXLayer * lyr; lyr = Form1->Map1->Layers->_Item(Param1); //long x = Form1->Map1->DataSets->Count; //тут вижу 48 все правильно! Form1->Map1->DataSets->Add(miDataSetLayer,OleVariant(lyr),OleVariant(lyr->Name));//так ли? lyr->Find->FindDataset = Form1->Map1->DataSets->get_Item(Param1); CMapXDataset *ds = Form1->Map1->DataSets->get_Item(Param1); //цикл для теста for(int i = 1; i <= ds->Fields->Count; i++) { Param1.operator = (i); ShowMessage(ds->Fields->_Item(Param1)->Name); //здесь конкретно вижу имя каждого поля из базы данных. Все точно! Поле ID идет вторым. } lyr->Find->FindField = ds->Fields->_Item(Param1); CMapXFindFeature *FoundObj; FoundObj = lyr->get_Find()->Search(WideString(Table2->FieldByName("ID")->AsString)); if (FoundObj->FindRC % 10 == 1)// ОШИБКА!!! Получить возвращаемое значение никак не удается! Метод get_FindRC не помогает. { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } } Или не правильно оформила ADD (см.рисунок) или вступает в силу второй параметр Seach. Добавлено lyr->Find->FindField = ds->Fields->_Item(Param1); надо Param1 но тоже не помогает. Добавлено lyr->Find->FindField = ds->Fields->_Item(Param1); надо Param2 но тоже не помогает. Прикреплённая картинка
|
Сообщ.
#77
,
|
|
|
Цитата Лена @ И не поможет. Т.к. FindRC и get_FindRC - фактически одно и то же.ОШИБКА!!! Получить возвращаемое значение никак не удается! Метод get_FindRC не помогает. Очевидно, что должно быть примерно так. Загрузка слоев: void __fastcall TForm1::Button3Click(TObject *Sender) { int i; TTable * table = DataModule1->Table5; CMapXLayer * layer; CMapXDataset * dataset; table->First(); for( i = table->RecordCount ; i >= 0 ; --i ) { layer = Map1->Layers->Add(table->FielbByName("FILE")->AsVariant); dataset = Map1->Datasets->Add(miDataSetLayer,layer,OleVariant(layer->Name)); table->Next(); } } Поиск: void __fastcall TFStr_Search::Button2Click(TObject *Sender) { CMapXLayer * layer = Form1->Map1->Layers->_Item(OleVariant("_ROAD")); CMapXDataset * dataset = layer->Datasets->_Item(OleVariant("_ROAD")); CMapXField * field = dataset->Fields->_Item(OleVariant("ID")); CMapXLayerFind * find = layer->Find; find->FindDataset = dataset; find->FindField = field; CMapXFoundFeature * find_result = find->Search(OleVariant(Edit1->Text)); if( (find_result->FindRC%10) == 1 ) { Form1->Map1->Zoom = 30; Form1->Map1->CenterX = find_result->get_CenterX(); Form1->Map1->CenterY = find_result->get_CenterY(); } else { char buffer[1024]; sprintf("Не смог найти объект\nКод результата поиска: %d",find_result->FindRC); MessageBox(Handle,buffer,"Ошибка",MB_ICONSTOP|MB_OK); } } Как выглядит файл TAB? P.S. 1) Возможно, что я ошибаюсь; 2) Возможно, что некоторые действия можно не повторять каждый раз, а вынести из поиска в загрузку. |
Сообщ.
#78
,
|
|
|
CMapXDataset * dataset = layer->Datasets->_Item(OleVariant("_ROAD"));
layer DataSet пуст. Нужно CMapXDataSet *dataset = Form1->Map1->DataSets->_Item(OleVariant("_ROAD")); |
Сообщ.
#79
,
|
|
|
Цитата trainer @ Как выглядит файл TAB? Это описание полей конкретной таблицы, например: !table !version 300 !charset WindowsCyrillic Definition Table Type NATIVE Charset "WindowsCyrillic" Fields 13 obj_COD Integer ; obj_NUM Integer ; obj_NAM Char (32) ; atr_003 Char (32) ; atr_005 Char (32) ; atr_009 Char (254) ; atr_015 Char (32) ; atr_028 Float ; atr_032 Char (32) ; atr_033 Char (32) ; atr_036 Char (32) ; atr_040 Char (32) ; atr_247 Char (254) ; Лена, вышли для trainer свой реальный road.tab (или _road.tab) ЗЫ. Сама карта - это 4 файла: - TAB - MAP - собственно метрика объектов карты (слоя карты, в принципе в MapInfo всю карту можно вбухать в 1 слой) - DAT - атрибуты объектов (семантика, характеристики). Каждой записи в MAP соответствует запись в DAT (даже если она пустая) - ID - честно говоря, не совсем понял, что в нем идентифицируется. Три последних файла - двоичные. ... Похоже - в предыдущем посте Guest говорит дело! В первом случае получаем Датасет из коллекции Датасетов некоторого слоя, а во втором - из коллекции Датасетов карты! |
Сообщ.
#80
,
|
|
|
Адаптировала код от trainer не работает:
CMapXLayer * lyr = Form1->Map1->Layers->_Item(OleVariant("_ROAD")); CMapXDataset * dataset = lyr->DataSets->_Item(OleVariant("_ROAD"));//при переходе на следующую строку исключение компонента CMapXField * field = dataset->Fields->_Item(OleVariant("ID")); CMapXLayerFind * find = lyr->Find; find->FindDataset = dataset; find->FindField = field; CMapXFindFeature *FoundObj; FoundObj = lyr->Find->Search(WideString(Table2->FieldByName("ID")->AsString)); if(FoundObj->FindRC % 10 == 1) { Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { .... } Мой новый код тоже на работает, хотя выглядит все правильно: void __fastcall TFStr_Search::Button2Click(TObject *Sender) { Table2->First(); OleVariant Param1, Param2; AnsiString NAME = "_ROAD"; AnsiString Field = "ID"; Param1.operator =(NAME); Param2.operator =(Field); int x = Form1->Map1->DataSets->Count;//вижу цифру 48 CMapXLayer * lyr = Form1->Map1->Layers->_Item(Param1); CMapXDataset * ds = lyr->DataSets->_Item(OleVariant(lyr)); //ds = NULL ds = Form1->Map1->DataSets->Add(miDataSetLayer,OleVariant(lyr)); //теперь ds != NULL lyr->Find->FindDataset = ds; /* //цикл для теста for(int i = 1; i <= ds->Fields->Count; i++) { Param1.operator = (i); ShowMessage(ds->Fields->_Item(Param1)->Name); //здесь вижу все заголовки колонок таблицы } */ //ShowMessage(ds->Fields->_Item(Param2)->Name); //вижу поле ID lyr->Find->FindField = ds->Fields->_Item(Param2); CMapXFindFeature *FoundObj; FoundObj = lyr->Find->Search(WideString(Table2->FieldByName("ID")->AsString));//тут что-то не так? if (FoundObj->FindRC % 10 == 1)//Ошибка компонента!!! Стандартное окно ошибки MapX. { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } } Добавлено Если напиписать так if(FoundObj!=NULL && FoundObj->FindRC % 10 == 1) то удается увидеть, что FoundObj=NULL Прикреплённая картинка
|
Сообщ.
#81
,
|
|
|
Цитата Лена @ CMapXLayer * lyr = Form1->Map1->Layers->_Item(Param1); CMapXDataset * ds = lyr->DataSets->_Item(OleVariant(lyr)); //ds = NULL ds = Form1->Map1->DataSets->Add(miDataSetLayer,OleVariant(lyr)); //теперь ds != NULL lyr->Find->FindDataset = ds; Лена, об этом тебе уже писал Guest - пост № 78. Во второй строке ты пытаешься получить Датасет от слоя... В третьей строке - все вроде ОК, добавляешь Датасет именно в карту. А в четвертой - ИМХО явная лажа (ты методу присваиваешь свойство), тем более, что Цитата Лена @ //цикл для теста for(int i = 1; i <= ds->Fields->Count; i++) { Param1.operator = (i); ShowMessage(ds->Fields->_Item(Param1)->Name); //здесь вижу все заголовки колонок таблицы } тестируешь ты именно ds - и все ОК. Так и попробуй Search для ds...а не для lyr |
Сообщ.
#82
,
|
|
|
void __fastcall TFStr_Search::Button2Click(TObject *Sender) { Table2->First(); OleVariant Param1, Param2; AnsiString NAME = "_ROAD"; AnsiString Field = "ID"; Param1.operator =(NAME); Param2.operator =(Field); //int x = Form1->Map1->DataSets->Count; CMapXLayer * lyr = Form1->Map1->Layers->_Item(Param1); CMapXDataset * ds = Form1->Map1->DataSets->_Item(Param1); ds = Form1->Map1->DataSets->Add(miDataSetLayer,OleVariant(lyr)); lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Param1); lyr->Find->FindField = ds->Fields->_Item(Param2); CMapXFindFeature *FoundObj; FoundObj = lyr->Find->Search(WideString(Table2->FieldByName("ID")->AsString)); if (FoundObj->FindRC % 10 == 1)//тут все время минус три { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); //оказываюсь здесь } } |
Сообщ.
#83
,
|
|
|
Что содержит этот самый road.tab?
|
Сообщ.
#84
,
|
|
|
> ds = Form1->Map1->DataSets->Add(miDataSetLayer,OleVariant(lyr));
> lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Param1); > lyr->Find->FindField = ds->Fields->_Item(Param2); ds и Form1->Map1->DataSets->_Item(Param1) могут не совпасть lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Param1); lyr->Find->FindField = Form1->Map1->DataSets->_Item(Param1)->Fields->_Item(Param2); или (наверно это лучше, если откомпилится) lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Param1); lyr->Find->FindField = lyr->Find->FindDataset->Fields->_Item(Param2); |
Сообщ.
#85
,
|
|
|
>Что содержит этот самый road.tab?
Road.tab это карта c дорогами созданная в MapInfo. К карте привязаны индификаторы. Щелчок по карте показывает этот индификатор. Индификаторы которые привязаны к карте храняться в таблице dbf. В этой же таблице и названия улицы в другой колонке. В первом Builder было так l_A.OlePropertyGet("Find").OlePropertySet("FindDataset", ds_A); l_A.OlePropertyGet("Find").OlePropertySet("FindField", ds_A.OlePropertyGet("Fields","ID")); find = l_A.OlePropertyGet("Find").OleFunction("Search", Table2->FieldValues["ID"], "" ); >ds и Form1->Map1->DataSets->_Item(Param1) могут не совпасть Да. Похоже. Буду пробывать. Ну вот, только дошла до самого интересного, как руководство поручили срочно схемы рисовать в CorelDRAW для выставки! |
Сообщ.
#86
,
|
|
|
Лена, вопрос на засыпку: зачем я указал третий параметр для функции Add?
Добавлено Цитата Лена @ Я знаю, что это такое, я умею читать документацию. Что конкретно он содержит? Road.tab это карта c дорогами созданная в MapInfo |
Сообщ.
#87
,
|
|
|
Цитата trainer @ Лена, вопрос на засыпку: зачем я указал третий параметр для функции Add? Я пробовала разные кол-во параметров и два и три. |
Сообщ.
#88
,
|
|
|
Цитата Лена @ не надо адаптировать, надо переписать как есть, обе функции.Адаптировала код от trainer не работает И посмотрев, работает или не работает - уже адаптировать. Добавлено Цитата Лена @ С двумы параметрами тот фрагмент не будет работать гарантированно. Я пробовала разные кол-во параметров и два и три. |
Сообщ.
#89
,
|
|
|
Под словом адаптировала я имела в виду правку синтаксиса для MapX т.е. вместо Datasets писала DataSets (регистр).
Я еще раз все попробую. |
Сообщ.
#90
,
|
|
|
Цитата Лена @ Road.tab это карта c дорогами созданная в MapInfo. К карте привязаны индификаторы. Щелчок по карте показывает этот индификатор. Индификаторы которые привязаны к карте храняться в таблице dbf. В этой же таблице и названия улицы в другой колонке. road.tab - это не карта, карта - это все 4 файла road.XXX ИМХО названия улиц хранятся в файле road.dat.А если нет, то что вообще хранится в DAT-файле? Если MapInfo выводит всю информацию об объекте карты, то взять ее она может только из DAT-файла. |
Сообщ.
#91
,
|
|
|
Набор карт, их индексация, таблицы dbf их алиас, это все из раннего рабочего приложения. Я переделываю только синтаксис для шестого Builder.
Названия улиц храняться в файле dbf, там же и их ID. Насколько я знаю, рисуется карта, затем геокодированием с ней связываются данные из dbf. Все это уже сделано в MapInfo. Вот уже второй день не могу приступить к проекту и выполнить все рекомендации, потому что из-за предстоящей выставки завалили другой работой. |
Сообщ.
#92
,
|
|
|
Лена, если не жалко - вышли пачку road-файлов (все 4).
Цитата Лена @ Насколько я знаю, рисуется карта, затем геокодированием с ней связываются данные из dbf. Все это уже сделано в MapInfo. Именно поэтому MapInfo показывет данные объектов, dbf тут ни при чем... |
Сообщ.
#93
,
|
|
|
Как не причем dbf? Вот же поиск из работающего приложения:
l_A.OlePropertyGet("Find").OlePropertySet("FindDataset", ds_A); l_A.OlePropertyGet("Find").OlePropertySet("FindField", ds_A.OlePropertyGet("Fields","ID")); find = l_A.OlePropertyGet("Find").OleFunction("Search", Table2->FieldValues["ID"], "" ); MapX ищет на своей карте значения совподающее со значением из dbf. Значения на карте добавлены геокодированием. Теперь используем dbf для поиска. |
Сообщ.
#94
,
|
|
|
ds_A - это что такое? Как созается? Информацию надо вытягивать клещами. Чувствуешь себя святой инквизицией.
Цитата Лена @ Сдается мне, что нет такого понятия "геокодирование". Значения на карте добавлены геокодированием |
Сообщ.
#95
,
|
|
|
Цитата trainer @ ds_A - это что такое? Как созается? Информацию надо вытягивать клещами. Чувствуешь себя святой инквизицией. Цитата Лена @ Сдается мне, что нет такого понятия "геокодирование". Значения на карте добавлены геокодированием В первом Buildere и первом MapX не было типов CMapXDataseta, СMapXLayer только варианты в данном случае ds_A это тоже массив вариантов подрузумевающий в данно контексте CMapXDataset. Геокадирование в MapInfo это привязка данных к карте. Т.е. привязка данных к рисунку. Данные храняться в таблицах. Это все уже сделано в первом проекте и все работает. Меня не много загрузили другой работой и я не успеваю проверить еще раз код от trainer. Я сейчас на компьюторе где вообще Builder не установлен. |
Сообщ.
#96
,
|
|
|
Цитата trainer @ Сдается мне, что нет такого понятия "геокодирование". Это терминология кандидатов в доктора от геоинформатики... Цитата Лена @ привязка данных к рисунку. Данные храняться в таблицах trainer - графика объектов (метрика) в MAP-файле, данные (семантика) - в DAT-файле, внешних баз с данными объектов (ИМХО) - нет. ЗЫ. Метрика, семантика - из той же терминологии. |
Сообщ.
#97
,
|
|
|
Я сейчас сижу на другом компьюторе, а мой проект на другом компьюторе и на другом этаже. Делаю другую работы, а мысли только о MapX!
Как только пройдет аврал со срочной работой, снова вступлю в бой с MapX! Решение уже совсем рядом. |
Сообщ.
#98
,
|
|
|
2:Лена
ситуация с MapX, при работе так CMapXFeature *TempMapXFeature=Map1->FeatureFactory->CreateRegion(OleVariant((IDispatch *)pItem),unusedParam); TempMapXFeature->KeyValue=(WideString("mnogougolnik")); CarLayer->AddFeature(OleVariant((IDispatch *)TempMapXFeature),unusedParam); Промсходит утечка памяти, если ты работаешь с MapX через EXEC то утечки не происходт, проверенно экспериментальным путем(скорее всего BC криво импортирует MapX). Из-за этого пришлось весь сервис переписать на Delphi. |
Сообщ.
#99
,
|
|
|
>если ты работаешь с MapX через EXEC то утечки не происходт
Прошу прощения, но я не поняла, что такое EXEC? |
Сообщ.
#100
,
|
|
|
Это примерно так
Variant CarLayer=Map->Layers->CreateLayer(WideString("Cars"),EmptyParam,Variant(1),EmptyParam,EmptyParam); Map->Layers->AnimationLayer=(CMapXLayerPtr)(IDispatch *)CarLayer; //------------------------------------------------------------------------- TFont *CarFont=new TFont(); OleFontToFont(Map->DefaultStyle->SymbolFont,CarFont); CarFont->Size=44; CarFont->Name="MapInfo Transportation"; delete CarFont; Map->DefaultStyle->SymbolCharacter=66; //------------------------------------------------------------------------- Variant NewPoint=OleVariant::CreateObject("MapX.Point.5"); NewPoint.Exec(Procedure("Set")<<37.663579517<<55.64860384); //------------------------------------------------------------------------- Variant NewSymbol=Map->FeatureFactory->CreateSymbol(NewPoint,Variant(Map->DefaultStyle)); NewFeature=CarLayer.Exec(Function("AddFeature")<<NewSymbol); NewFeature.Exec(PropertySet("KeyValue")<<"CAR"); //------------------------------------------------------------------------- NewSymbol=Unassigned; NewPoint=Unassigned; |
Сообщ.
#101
,
|
|
|
Создала новое приложение. В MapX теперь загружен всего один нужный мне слой. Все загружено в режиме конструктора. Однако не находит:
Table1->First(); CMapXLayer * lyr = Form1->Map1->Layers->_Item(Variant(1)); if(lyr==NULL) { ShowMessage("Слой пуст"); return; } CMapXDataset * ds = Form1->Map1->DataSets->_Item(Variant(1)); ds = Form1->Map1->DataSets->Add(miDataSetLayer,Variant(lyr),Variant(lyr->Name)); if(ds==NULL) { ShowMessage("Проблема с dataset"); return; } Variant Param1; for(int i = 1; i <= ds->Fields->Count; i++) { Param1.operator = (i); ShowMessage(ds->Fields->_Item(Param1)->Name); //Вижу все имена колонок из Table1. ID идет вторым. } int x = Form1->Map1->DataSets->Count; //здесь цифра 1 lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Variant(1)); if(lyr->Find->FindDataset==NULL)//всегда true { ShowMessage("lyr->Find->FindDataset не найден");//попадаю сюда - плохо return; } lyr->Find->FindField = ds->Fields->_Item(Variant(2));// ID идет вторым. CMapXFindFeature *FoundObj; FoundObj = lyr->Find->Search(WideString(Table1->FieldByName("ID")->AsString)); if (FoundObj->FindRC % 10 == 1) { ShowMessage("Yes"); Form1->Map1->Zoom = 30; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("No"); } Можно и так написать: lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Variant(lyr)); или так: lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Variant(lyr->Name)); все равно: lyr->Find->FindDataset=NULL если написать так lyr->Find->FindDataset = ds; то исключение. Наверное, надо поиск реализовывать через ф-цию Exec как говорил MAX2002, но как не знаю. |
Сообщ.
#102
,
|
|
|
Цитата Лена @ Table1->First(); Что в этой таблице, кроме имен файлов, которые ты грузишь в Map1? ... Сколько в ней записей - 48 (по числу слоев) или??? |
Сообщ.
#103
,
|
|
|
Я ведь написала;
Цитата В MapX теперь загружен всего один нужный мне слой. Все загружено в режиме конструктора. Карта с дорогами, к которым привязано ID из Table1, загружена в режиме конструктора в MapX. Все, никакой динамической загрузки. Никаких 48 слоев. В MapX находиться один слой дорог. Эти дороги имеют свои ID. Эти ID можно посмотреть в MapInfo. Соответственно в Table1 находиться улицы - их названия и их ID во второй колонке. Соответственно записей много, потому что улиц много. Карта – таблица – все рабочее, потому что работает в другом приложении без проблем. Похоже что-то с самим компонентом в среде Builder 6. |
Сообщ.
#104
,
|
|
|
Цитата Лена @ CMapXLayer * lyr = Form1->Map1->Layers->_Item(Variant(1)); if(lyr==NULL) { ShowMessage("Слой пуст"); return; } из деревенской логики следует, что слой отсутствует, а не пуст. Это к слову... Цитата Лена @ for(int i = 1; i <= ds->Fields->Count; i++) { Param1.operator = (i); ShowMessage(ds->Fields->_Item(Param1)->Name); //Вижу все имена колонок из Table1. ID идет вторым. } из твоего фрагмента кода (пост № 101) непонятно, как пристегнута сама таблица Table1? |
Сообщ.
#105
,
|
|
|
>из твоего фрагмента кода (пост № 101) непонятно, как пристегнута сама таблица Table1
К слою TAB геокодированием пристегнуты ID из DBF таблицы с улицами. Это сделано в МapInfo разработчиками карт. Теперь на форме к Table1 пристегнута эта же DBF таблица в режиме конструктора. Теперь используя ID этой таблицы для сопостовления с ID на слое ищем фрагмент катры и увеличиваем его. |
Сообщ.
#106
,
|
|
|
Цитата Лена @ К слою TAB геокодированием пристегнуты ID из DBF таблицы с улицами. иды наверное сидят в DAT-файле...опять к слову... Цитата Лена @ CMapXDataset * ds = Form1->Map1->DataSets->_Item(Variant(1)); ds = Form1->Map1->DataSets->Add(miDataSetLayer,Variant(lyr),Variant(lyr->Name)); не совсем понятно, что делает вторая строчка, тем не менее ds - из карты, а не из внешней базы (dbf) Цитата Лена @ for(int i = 1; i <= ds->Fields->Count; i++) { Param1.operator = (i); ShowMessage(ds->Fields->_Item(Param1)->Name); //Вижу все имена колонок из Table1. ID идет вторым. } следовательно - видишь ты поля из DAT-файла, Table1 тут ни при чем... Цитата Лена @ lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Variant(1)); по той же деревенской логике lyr->Find->FindDataset не может быть свойством на запись!!! сравни это с тем, что ты делала на полстраницы выше, где все было ОК: Цитата Лена @ CMapXDataset * ds = Form1->Map1->DataSets->_Item(Variant(1)); |
Сообщ.
#107
,
|
|
|
Цитата Лена @ А эта Table1 открыта не в монопольном режиме?Теперь на форме к Table1 пристегнута эта же DBF таблица в режиме конструктора. И зачем эта Table1 вообще нужна? |
Сообщ.
#108
,
|
|
|
Цитата следовательно - видишь ты поля из DAT-файла, Table1 тут ни при чем... Это понятно. Просто комментарий написала не корректный. Цитата CMapXDataset * ds = Form1->Map1->DataSets->_Item(Variant(1)); ds = Form1->Map1->DataSets->Add(miDataSetLayer,Variant(lyr),Variant(lyr->Name)); не совсем понятно, что делает вторая строчка, тем не менее ds - из карты, а не из внешней базы (dbf) Слой имеет свой dataset, ведь данные в него были добавлены геокодированием на этапе разрабоки в MapInfo. Первая строка создает укзатель на данные этого слоя. Вторая строка инициализация. Цитата по той же деревенской логике lyr->Find->FindDataset не может быть свойством на запись!!! FindDataset это свойство. А что же записать в это свойство? Я по аналогии с Делфи писала. -юсртыхэю Цитата trainer @ Цитата Лена @ А эта Table1 открыта не в монопольном режиме?Теперь на форме к Table1 пристегнута эта же DBF таблица в режиме конструктора. И зачем эта Table1 вообще нужна? В дальнейшем Table1 буду использовать так: пользователю буде предоставлен столбец с названием улиц. Щелок по этой улице подставит в метод Seach ID из таблицы для поиска такого же ID на карте. И соотвественно пользователь увидет на карте, то что нужно. Что касается монопольного режима, то речь идет о свойстве Exlusive? Оно false. В коде который я привела дело не доходит до применения не посредственно Table1. Cпотыкаюсь на lyr->Find->FindDataset. |
Сообщ.
#109
,
|
|
|
Цитата Лена @ В дальнейшем Table1 буду использовать так: пользователю буде предоставлен столбец с названием улиц. Щелок по этой улице подставит в метод Seach ID из таблицы для поиска такого же ID на карте. И соотвественно пользователь увидет на карте, то что нужно. Приплылиииии! Лена, есть понятие целостности данных в базах данных, коей в частности является МапИнфо. Представь ситуацию, что некто удалил (добавил) часть записей в DBF и забыл перелопатить карту (или действовал со злым умыслом)? Ты можешь средствами MapX получить из DAT-файла реальную (из карты) таблицу в удобном для юзера виде? Если да, то забудь ты про DBF. |
Сообщ.
#110
,
|
|
|
CMapXLayer * lyr = Form1->Map1->Layers->_Item(Variant(1)); if(lyr==NULL) { ShowMessage("Нет слоя"); return; } CMapXDataset * ds = Form1->Map1->DataSets->_Item(Variant(1)); ds = Form1->Map1->DataSets->Add(miDataSetLayer,Variant(lyr),Variant(lyr->Name)); if(ds==NULL) { ShowMessage("Проблема с dataset"); return; } Variant Param1; for(int i = 1; i <= ds->Fields->Count; i++) { Param1.operator = (i); ShowMessage(ds->Fields->_Item(Param1)->Name); //Вижу все имена из DAT файла ID идет вторым. } int x = Form1->Map1->DataSets->Count; //здесь цифра 1 lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Variant(1)); if(lyr->Find->FindDataset==NULL)//всегда true Где в моем коде выше используется Table1? Нигде. MapX получает все из своих ресуров для поиска. Table1 будет использовать ниже в методе Seash, а до него я не дохожу. |
Сообщ.
#111
,
|
|
|
Цитата Лена @ Где в моем коде выше используется Table1? НИГДЕ!!! Я не про код, а про сам подход к целостности данных!!! А что касается кода, то вот это явно не то: Цитата Лена @ lyr->Find->FindDataset = Form1->Map1->DataSets->_Item(Variant(1)); у тебя уже есть ds, ранее добавленный в коллекцию наборов данных для этого слоя, ты из него можешь читать данные. Т.е. у твоего lyr в коллекции наборов данных уже есть набор, пристегнутый тобой, что-то типа lyr->DataSets[i]... |
Сообщ.
#112
,
|
|
|
Сообщ.
#113
,
|
|
|
Я бы попробовал так
FoundObj = ds->Search(.......); причем Search и с одним параметром, и с двумя, и посмотрел бы, что в этом самом обже получится |
Сообщ.
#114
,
|
|
|
Цитата Coala @ Я бы попробовал так FoundObj = ds->Search(.......); причем Search и с одним параметром, и с двумя, и посмотрел бы, что в этом самом обже получится В прилагаемом мною рисунке (см.выше) метода Seach нет у ds. Попытка написать FoundObj = ds-> сразу [C++ Error] Unit1.cpp(1): Unable to invoke Code Completion due to errors in source code |
Сообщ.
#115
,
|
|
|
Ага, там есть CMapXDataSet::get_Layer() и CMapXDataSet::Layer, возвращающие CMapXLayer - слой, связанный с этим ds
и что дальше |
Сообщ.
#116
,
|
|
|
Сообщ.
#117
,
|
|
|
ЗАРАБОТАЛО!
Как выяснилось для Builder необходимым условием, в отличии от VBA, Делфи, VC, должно быть чтобы поле по которому искалась информация было ТОЛЬКО первым в файле DAT. В VBA, Делфи, VC можно вести поиск по любому полю в таблице (по первому, второму, третьему и т.д.) Код ниже ищет нужную улицу. Поле, по которому идет поиск, перемещено в таблице на первое место: Цитата void __fastcall TForm1::Button1Click(TObject *Sender) { CMapXFindFeature *FoundObj = Form1->Map1->Layers->_Item(OleVariant(1))->Find->Search(WideString("576090")); if(FoundObj->FindRC % 10 == 1) { Form1->Map1->Zoom = 0.5; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage(IntToStr(FoundObj->FindRC)); } } Этот же пример работает, например, в Делфи не взирая на то под каким номером идет поле. Cпасибо всем за помощь и терпение! |
Сообщ.
#118
,
|
|
|
Цитата Лена @ Быть такого не может. Ну не знает MapInfo, на чем написан код, который его вызывает.Как выяснилось для Builder необходимым условием, в отличии от VBA, Делфи, VC, должно быть чтобы поле по которому искалась информация было ТОЛЬКО первым в файле DAT. Лена, я со 101%-ной уверенностью заявляю, что этого быть не может. Проблема в чем-то другом. Например, в индексировании. |
Сообщ.
#119
,
|
|
|
MapX 5.0
Делаю поиск в Делфи. Поле ID первоначально находиться в третей колонке. Все работает. Пробую в Builder 6 не работает. В Builder 1.0 и MapX 3.0 работает. Открываю слой с дорогами в MapInfo. Средствами MapInfo перемещаю ID на первое место, меняю тип с float на integer (хотя в Builder 1.0 и MapX 3.0 был float) и о чудо - поиск работает! Следовательно, Builder может искать ТОЛЬКО по KeyField которое находиться на первом месте в таблице. Думаю, что это можно назвать глюком Builder. Может, поэтому официально MapInfo не декларирует работу MapX в Builder 6 из-за наличия этих подводных камней. Добавлено Поиск средствами FindField и FindDataSet по-прежнему не работает. Явно проблема с адаптацией Builder для MapX. |
Сообщ.
#120
,
|
|
|
Цитата Лена @ Builder ничего не ищет и не может искать. Он всего лишь среда разработки. Ищет код, написанный программистом, в данных, созданных пользователем.Следовательно, Builder может искать ТОЛЬКО по KeyField которое находиться на первом месте в таблице. Не стоит одушевлять программу. |
Сообщ.
#121
,
|
|
|
У меня еще такой вопрос:
В декабре выходит новый компилятор от Borland. В нем будет возможность создавать приложения и на Паскале и на С++ и на С#. Визуальные компоненты также сохраняются. Если MapX успешно используется в Делфи, то какова вероятность того, что в новом компиляторе он будет хорошо работать сразу и в Паскале и в С++. Ведь это будет уже единая среда. Может ли быть ситуация, что в проекте на Паскале все будет работать, а в этом же компиляторе на C++ все будет глючить? О новом компиляторе http://www.borland.com/us/products/cbuilder/index.html |
Сообщ.
#122
,
|
|
|
Лена, я уже устал объяснять, что функциональность ActiveX-компонентов не зависит от того, из какого языка вызывать его функции.
Объясняю на пальцах. Есть стержень в шариковой авторучке. Если я пишу правой рукой и на бумаге, то все получается отлично, если пишу левой рукой - получается коряво. Если пишу правой рукой, но на стекле - ничего не получается. Вопрос: это глюк авторучки? Функции MapX(в том числ и поиск) уже реализованы программистами MapInfo в самом компоненте. Имеет ли для MS Word значение, будет он запущен из меню "Пуск", с рабочего стола или из проводника? P.S. Хотя зачем я это объясняю? Каждый волен упорно заблуждаться и ждать у моря погоды. |
Сообщ.
#123
,
|
|
|
Т.е. вы хотите сказать, что MapX также корректно работает и в Делфи и в Builder? Все проблемы в программисте, который пишет? Тогда почему техническая поддержка MapInfo четко написала мне, что компонент MapX не поддерживается MapInfo в Builder.
MapX распространяет документацию и для VBA и для Делфи и для VC. Для Builder ничего нет. Очевидно, выявлены проблемы работы компонента в среде Builder из-за особенностей этого компилятора. Для MapInfo важно чтобы их ActiveX работал в любом компиляторе. Для Builder ничего нет от MapInfo. Это подозрительно. Примеры на Делфи работают в Builder нет, разве это вина программиста т.е. меня ? |
Сообщ.
#124
,
|
|
|
Цитата Лена @ Если этот программист сваливает причины ошибок на инструмент, а не пытается разобраться - да.Все проблемы в программисте, который пишет? Цитата Лена @ Потому, что в технической поддержке сидят не программисты. Они знают только то, что им скажут, а остальное додумывают по мере своих способностей. Тогда почему техническая поддержка MapInfo четко написала мне, что компонент MapX не поддерживается MapInfo в Builder. Добавлено Цитата Лена @ Для Builder нет потому, что он близкий родственник Delphi. Или потому, что маркетинг не сказал, что это надо.Для Builder ничего нет. Очевидно, выявлены проблемы работы компонента в среде Builder из-за особенностей этого компилятора Да, и о каких особенностях компилятора идет речь? |
Сообщ.
#125
,
|
|
|
Trainer> Если этот программист сваливает причины ошибок на инструмент, а не пытается разобраться - да.
Первый мессинг этого топика имеет дату 30го августа. Топик набрал 9 страниц. Если это не попытка разобраться, тогда что таковым является? Потом, что ты написал звучит очень неубедительно. Было бы более убедительно, если б ты написал, что-то типа: "Если этот программист сваливает причины ошибок на инструмент, а не пытается разобраться - да. Вот я(Trainer) уже 5 лет разрабатываю программы с использованием MapX и Builder, и все нормально работает. Нет никаких проблем с поиском" Trainer> Потому, что в технической поддержке сидят не программисты. Они знают только то, что им скажут, а остальное додумывают по мере своих способностей. В тех поддержке сидят программисты (возможно не асы), которые отлично знают этот продукт. И вопрос, тестировался ли MapX на совместимость с СBuilder, не может являться фирменной тайной. MapX поставляется с примерами написанными на Visual C++, Delphi, Visual Basic. Значит, или не тестировался c CBuilder или проекты тест не прошли. Потом напр. Oracle, свои продукты, к примеру Pro*C++, тестирует только на совместимость с Visual C. Trainer> Для Builder нет потому, что он близкий родственник Delphi. Builder это С++, Delphi это Pascal. Может и мизерная, но всеж таки какая то разница имеется. Trainer> Да, и о каких особенностях компилятора идет речь? Например http://info.borland.com/devsupport/borlandcpp/patches.html imho ты неправ. Но, если у тебя есть на компе Delphi6/CBuilder6/MapX5, тогда могу написать в выходные маленькую программку на Delphi, для поиска в стандартной карте c использованием FindDataSet/FindField. И аналогичную программу на Builder-е. Программа на Delphi будет работать. А Builder-овская будет давать сбой. И отправить тебе оба проекта. Если вернешь мне работающую Builder-овскую, то respect, и ты прав и можешь устраиваться в mapInfo в отдел технической поддержки. |
Сообщ.
#126
,
|
|
|
Цитата Rosty @ У меня нет MapX вообще, о чем я ранее уже писал.если у тебя есть на компе Delphi6/CBuilder6/MapX5, Я знаю, что такое ActiveX, я вижу исходники компонента для Builder'а. Если ты мне покажешь в этом исходнике место, где компонент определяет, что он вызывается из программы, написаной в Builder'е, а не, например, в Delphi, и поэтому отказывается работать, то я скажу, что я не прав. Добавлено Цитата Rosty @ И что из этого влияет на работу MapX? А то ведь я могу привести ссылку на, например, Microsoft Platform SDK или Visual Studio. Будет ли это означать, что MapX не может работать с Visual Studio и вообще под Windows? Например http://info.borland.com/devsupport/borlandcpp/patches.html Добавлено Цитата Rosty @ Выкладывай, посмотрю. Но без MapX оттрассировать не смогу. DFM-ы должны быть в текстовом формате.И аналогичную программу на Builder-е. Программа на Delphi будет работать. А Builder-овская будет давать сбой. Цитата Rosty @ Хотелось бы в это верить. Практика обычно прозаичнее, имел возможность в этом убедиться, правда, не в программировании. Точнее - в программировании не под PC. Например, с Philips.В тех поддержке сидят программисты (возможно не асы), которые отлично знают этот продукт. Цитата Rosty @ Или это в MapInfo просто никому не надо. Значит, или не тестировался c CBuilder или проекты тест не прошли. |
Сообщ.
#127
,
|
|
|
Ребята, только не сортесь, я Вас очень прошу!
trainerу отдельное спасибо, что указал мне во время дискуссии правильную загрузку датасетов. |
Сообщ.
#128
,
|
|
|
Это не ссора. Это выявление истины.
|
Сообщ.
#129
,
|
|
|
С сылкой я имел ввиду, что каждый компилятор (+текущие его системные файлы) имеют свои баги.
По всей видимости поддержка ActiveX реализована более удачно в Delphi, чем в Buildere. Напр. http://info.borland.com/devsupport/bcppbuilder/patches/bcpp5/BCB5FIXES.HTML в 5м buildere исправляются такие баги связанные с ActiveX. When importing a type library which contains a user-defined record, the _TLB.h file contains a declaration of the GUID for the user-defined record, but the _TLB.cpp file contains no definition thereof. The override flag for CAN_CREATE (-Yu) doesn't work. GUIDs in a type library which are associated with records are not output in the generated .cpp file but ARE output in the generated .h file The supplied BUILD_.h is incorrect. utilcls.h uses __uuidof(DISPINTF), where DISPINTF is a template parameter defaulted to IDispatch. This *fails* at runtime where __uuidof(IID_IDispatch) succeeds Including MSVBVM60.DLL containing TLB fails on generating the pascal for a COM interface, with Error: 'GhostMethod_76' already exists. TAutoDriver copy constructor (LCID) does not clear out m_ExcepInfo, but TAutoDriver copy constructor (TAutoDriver) does. TVariant& operator= (Const TBaseVariantT& rhs) does not compile. When importing a type library which contains a user-defined record, the _TLB.h file contains a declaration of the GUID for the user-defined record, but the _TLB.cpp file contains no definition thereof. Can not use an activeX control created by Visual Basic V6.0 that does not have 'CAN CREATE' flag set in its type info. VB6 controls will not allow methods to be called via the OCX wrapper. The Dispatch wrapper works but cannot be made visible. Сам пример. Используется Mapinfo-ская карта Wordlcap.map. Delphi проект находит по втрому полю(Country) "FALKLAND ISLANDS" и позиционирует карту на Stanley. Builder-овская программа при команде CMapXFindFeature *FoundObj = lyr->Find->Search(WideString("FALKLAND ISLANDS"), v); дает сбой IsBound() возвращает false на 4270 строке utlcls.h. //********************* Delphi *******************************// procedure TFindForm.Button1Click(Sender: TObject); var FoundObj, ds: variant; lyr : CMapXLayer; unusedParam: OleVariant; begin TVarData(unusedParam).vType := varError; TVarData(unusedParam).vError := 2147614724; // DISP_E_PARAMNOTFOUND; lyr := currentMap.Layers.Item[1]; ds := currentMap.Datasets.Add(miDataSetLayer, lyr, lyr.Name, unusedParam, unusedParam, unusedParam, unusedParam, unusedParam); lyr.Find.FindDataset := ds; lyr.Find.FindField := ds.Fields.Item[2]; FoundObj := lyr.Find.Search('FALKLAND ISLANDS', ''); if (foundObj.findrc Mod 10 = 1) then currentMap.ZoomTo(2, FoundObj.CenterX, FoundObj.CenterY) else showmessage('Exact Match Not found'); end; // **************** BUILDER ****************************************** void __fastcall TForm1::Button5Click(TObject *Sender) { Variant v; v.VType = varError; v.VError = 2147614724; CMapXLayer *lyr = Form1->Map1->Layers->_Item(OleVariant(1)); CMapXDataset *ds = Form1->Map1->DataSets->Add(miDataSetLayer,OleVariant(lyr), OleVariant(lyr->Name),v,v,v,v,v); lyr->Find->FindDataset = ds; lyr->Find->FindField = ds->Fields->_Item(OleVariant(2)); v.VType = varString; v.VString = ""; CMapXFindFeature *FoundObj = lyr->Find->Search(WideString("FALKLAND ISLANDS"), v); if(FoundObj->FindRC % 10 == 1) { Form1->Map1->Zoom = 2; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); } else { ShowMessage("Exact Match Not found"); } } DFM файл: object Form1: TForm1 Left = 192 Top = 107 Width = 761 Height = 548 Caption = 'Form1' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object Map1: TMap Left = 0 Top = 4 Width = 601 Height = 513 ParentColor = False TabOrder = 0 ControlData = { 2CA107001D3E000005350000010000000F000080FFFEFF3B45006D0070007400 ... удалил строки. Это объект MapX 3F0D64FC8998EA593F00000000000000000100000000000000} end object Button5: TButton Left = 605 Top = 2 Width = 137 Height = 23 Caption = 'Find Falkland' TabOrder = 1 OnClick = Button5Click end end |
Сообщ.
#130
,
|
|
|
Цитата Rosty @ В имеющихся у меня Borland C++Builder5 UP1 и Borland C++Builder6 UP4 в строке 4270 нет вызовов функции IsBound. В BCB6 эта строка вообще не содержит кода, в BCB5 содержит часть объявления одной из функций. дает сбой IsBound() возвращает false на 4270 строке utlcls.h. Добавлено Цитата Rosty @ Зачем давать ссылку на исправленные ошибки? Я по-прежнему жду информацию о том, что принципиально препятствует работоспособности ActiveX в BCB. Для любой версии Builder'а Напр. http://info.borland.com/devsupport/bcppbui.../BCB5FIXES.HTML |
Сообщ.
#131
,
|
|
|
>сбой IsBound()
Да, именно эта ошибка измучила меня до полного душевного истощения. Если бы наш форум не читал еще одни человек, который мне подсказал о поиске, то я так бы и не решила этот вопрос. В тех.суппорт сидит некая Синди и выдает примеры только на VBA. На Builder получить ничего не возможно. Правда, судя по их форуму, периодически возникают вопросы о том, как работает MapX в Builder 6, но ответ Синди всегда одни – MapInfo не тестировала MapX в среде Builder, поэтому поддержки нет. Тем не мене эта Синди согласилась принять мой слой дорог для поиска улицы. В итоге я получила важную информацию о том, что поле должно быть integer, а не float. Однако приложение по-прежнему не работало. Потом я получила еще одну подсказку от читателя форума, он нашел в help: “Для Find.FindDataSet Dataset of field to match against. If not specified, a layer's KeyField is used. А для Layer.KeyField-a This string property identifies the column (field) name in the layer's MapInfo table that will be set or retrieved by the KeyValue property of a feature object. It currently defaults TO THE FIRST COLUMN in the layer's table. This property does not apply to raster or userdraw layers. An error is raised if you try to set the KeyField to an invalid field name.” После переноса поля на первое место поиск заработал, но через FindDataSet/FindField не работает. Rosty ели у вас есть хоть какие-то фрагменты кода на C++ Builder для MapX вышлите мне please! Л. |
Сообщ.
#132
,
|
|
|
..\Borland\CBuilder6\include\vcl\utilcls.h
4267: template <class DISPINTF> HRESULT 4268: TAutoDriver<DISPINTF>::Invoke(DispatchFlag ............... 4269: { 4270: _ASSERTE(IsBound() /* Must be bound to perform Invoke() */); На счет ссылки. Ты спрашывал какие могут быть особенности у компилятора. Например такие, что программа откомпилированная на CBuilder5 может работать и может не рвботать в зависимости от того, установлен ли последний SP. Это раз. Во вторых, ты бы сколько ставил на то, что тот SP исправляет все баги BCB5? А на счет приведенного кода по существу ничего сказать не можешь? |
Сообщ.
#133
,
|
|
|
Lena >Rosty если у вас есть хоть какие-то фрагменты кода на C++ Builder для MapX вышлите мне please!
Еще раз??? |
Сообщ.
#134
,
|
|
|
Rosty судя по вашей компетентности в вопросе о MapX, я предположила, что у вас могут быть фрагменты любого работающего кода. Вот и попросила.
В старом приложении, найденная улица не только увеличивалась зумом на карте, но и становилась жирной и красилась в красный цвет. Займусь этим в понедельник. О результатах сообщу участникам этой дискуссии. |
Сообщ.
#135
,
|
|
|
Цитата Guest @ Я не спрашивал, какие могут быть особенности у компиляторов. У меня достаточно большой опыт работы с разнообразными компиляторами. Я спрашивал, какие особенности компилятора Borland C++ 5.5.x или 5.6.x препятствуют правильной работе MapX.Ты спрашывал какие могут быть особенности у компилятора. Цитата Цитата о каких особенностях компилятора идет речь?Очевидно, выявлены проблемы работы компонента в среде Builder из-за особенностей этого компилятора Касаемо строки 4270. У меня Borland C++ 6 Update Pack 4. Строка под номером 4270 содержит только пустой комментарий. Update Pack 4 помимо много еще чего как раз заменяет и utilcls.h Теперь относительно самой функции IsBound. Она проверяет, связан ли компонент с сервером. Цитата Guest @ Я ни на что ставить не намерен. Есть доказательства - это одно, нет доказательств - другое. Вот пример недавно обнаруженного "глюка компилятора": Странный глюк . Я такого видел уже достаточно много и крайне скептически отношусь к очередным "открывателям". Во вторых, ты бы сколько ставил на то, что тот SP исправляет все баги BCB5? |
Сообщ.
#136
,
|
|
|
У меня C++ Builder 6 SP4
Прилагаю в архиве файл ..\Borland\CBuilder6\include\vcl\utilcls.h и постоянную ошибку возникающую в Builder: При вводе 4274получаю: _ASSERTE(IsBound() /* Must be bound to perform Invoke() */); Прикреплённый файлutilcls.zip (29.15 Кбайт, скачиваний: 127) |
Сообщ.
#137
,
|
|
|
Отдельно взятый кусок программы в отрыве от остального может вести себя как угодно. Надо сравнивать полностью проекты, делающие одно и то же.
Анализ не производится по принципу "Вырежем произвольный кусок и посмотрим, что получится" |
Сообщ.
#138
,
|
|
|
Чтобы выявить ошибку, я создала новый проект: кнопка, один слой, с одним и тем же кодом. Один в Делфи, другой в Builder. Код выше приводился пользователем Rosty. В Делфи код работает в Builder нет
Пользователь MAX2002, который работал с MapX, тоже во время дискуссии говорил, что это у Builder-а проблема... Все таки надеюсь на хорошую декабрьскую версию |
Сообщ.
#139
,
|
|
|
Trailer >
Отдельно взятый кусок программы в отрыве от остального может вести себя как угодно. Надо сравнивать полностью проекты, делающие одно и то же. Анализ не производится по принципу "Вырежем произвольный кусок и посмотрим, что получится" Могу выставить полный проект, но мне непонятно, как можно проверить работу программы, которая в основном состоит из одного ActiveX, если этот ActiveX не установлен на компьютере? Ты просил исходный код и DFM в текстовом виде. И я выложил ВЕСЬ код. Я бы выложил и весь проект, но нет кнопки подключения файла. Видимо для этого, нужно бы зарегистрироваться. Trailer > Я не спрашивал, какие могут быть особенности у компиляторов. У меня достаточно большой опыт работы с разнообразными компиляторами. Я спрашивал, какие особенности компилятора Borland C++ 5.5.x или 5.6.x препятствуют правильной работе MapX. Попробую объяснить третий раз. Каждый компилятор, точнее ее lib файлы содержат баги. Не является исключением и CBuilder. Ссылки на такие найденные баги я приводил. Из за какого-то Builder-овского бага не работает Find с установленными значениями FindDataSet, FindField. Ты утверждаешь, что MapX должен работать на все 100 с Builder. Но ты только слышал об этом компоненте. Его можно скачать с сайта mapinfo.com. Хочешь продолжить спор, скачай, посмотри что это. Я знаю mapX и не хочу спорить с человеком, который только слышал о нем. И который в свою правоту может только привести, что хорошо знает ActiveX и имеет большой опыт работы с компиляторами Builder. |
Сообщ.
#140
,
|
|
|
Lena >
В старом приложении, найденная улица не только увеличивалась зумом на карте, но и становилась жирной и красилась в красный цвет Один из способов это сделать: if(FoundObj->FindRC % 10 == 1) { Form1->Map1->Zoom = 2; Form1->Map1->CenterX = FoundObj->get_CenterX(); Form1->Map1->CenterY = FoundObj->get_CenterY(); double x = FoundObj->LabelPoint->get_X(); double y = FoundObj->LabelPoint->get_Y(); int n = lyr->Labels->Count; for(int i = 1; i<=n; i++) { CMapXLabel *lbl = lyr->Labels->_Item(OleVariant(i)); if(lbl->AnchorX==x&&lbl->AnchorY==y) { lbl->Style->TextFontColor = RGB(128,0,0); UINT nArgErr = (UINT)-1; DISPPARAMS dispparams; VARIANTARG va; dispparams.rgvarg = &va; dispparams.rgvarg[0].vt = VT_BOOL; dispparams.rgvarg[0].boolVal = TRUE; dispparams.cArgs = 1; dispparams.cNamedArgs = 0; lbl->Style->TextFont->Invoke(DISPID_FONT_BOLD, IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, &nArgErr); break; } } Но есть один минус, перебираются все метки, а таких меток на карте может быть несколько сот. Я не вижу такого свойства у CMapXFindFeature, с помощью которой можно бы от нее за один шаг, перейти к соответствующей метке. Но есть идея. В понедельник проверю, и если работает, тогда спроектирую класс и отправлю. |
Сообщ.
#141
,
|
|
|
Цитата Rosty @ Мне за решение проблем некоего Rosty не платят. Чтобы я еще что-то для этого качал. Хочешь продолжить спор, скачай, посмотри что это |
Сообщ.
#142
,
|
|
|
Trainer > Мне за решение проблем некоего Rosty не платят.
Чтобы я еще что-то для этого качал. Уважаемый, нет у меня таких проблем, которых ты мог бы решить. Прочитал твой ответ на вопрос заданный "ТЕМ КТО РАБОТАЛ С МapX5", типа: Search метод должен работать в Buildere при установленных значениях FindDataSet/FindField. И если он не работает то только потому, что у кодера руки кривые. Я подумал, мало того, что кадер трындит о том, что не знает, да еще поучивает человека, который в MapX разбирается несравненно лучше чем он. И решил вывести это кадра на чистую воду. imho мне это получилось. Вместо конкретного ответа, сперва у тебя туфли были маленькие(нет MapX), потом штаны давили (на той строке ничего нет), потом пол был кривой(нельзя вырывать куски кода из проекта). Теперь ....(тебе не платят). P.S. Что, приведенный мной анекдот о мостах Будапешта, тебе не понравился, что ты его дважды удалил? |
Сообщ.
#143
,
|
|
|
Rosty
Заканчивай, ты себя не очень корректно ведешь. К тому же trainer прав, если нужно, то можно заставить работать MapX и с Builder'ом. На вскидку, можно написать dll-ку на Delphi и ее юзать из Builder'а. Есть и более сложные способы, но при желании все возможно. В конце концов, можно все вообще руками сделать (я имею в виду работу с ActiveX). Так что хватит наездов и несмешных анекдотов, я не думаю, что кому-нибудь это интересно читать. |
Сообщ.
#144
,
|
|
|
Artalex, я вел себя довольно корректно. Обещал код. Код выложил так,
как просили. Даже не ждал выходных. И даже указал один из возможных способов решения проблемы. (IsBound() дает false, но есть еще ф-ия Bound()) Ожидал ответа типа 1: "Смотри ламер, это делается так и так". Моим ответом, был бы, "Спасибо, ты монстр (в положительном смысле) и я действительно ламер, но буду стараться" Тип 2: "Да, код не работает. Borland здесь что-то явно нахимичил". Мой ответ: "Бывает". И ответ, которого я бы дал в данном случае, будучи на месте Trainer. "Смотри, хоть я с тобой не согласен, но у меня нет времени разобраться в этом вопросе, по-этому, пусть будет так, как ты говоришь, и я был неправ на счет того, что XY не разобрался(ась) в MapX." Все. Это альфа и омега, когда общаются два спеца. Вместо этого: и то не то и то не так, и договорились до "у меня нет дел до проблем некого Rosty". И лично мне не нравится, если мои ответы удаляют. Типа барин(moder) делает что хочет. Потом, вопрос не в том, что работает ли MapX с Builder-ом. Он работает и довольно неплохо. Но метод Search, при установленных значениях FindDataset/FindField дает сбой. Trainer утверждает, что если разобраться, тогда можно заставить Search работать. Я попросил его показать, как это делать. Если б он это сделал, я был бы ему благодарен. Теперь Ты утверждаешь, что MapX и Builder лучшие друзя. Судя по Твоему ответу, делаю вывод, что, конечно и на твоем компе этот компонент не установлен. И этого компонента Ты тоже в глаза не видел. Для того, чтоб находить любой объект не нужна dll-ка, это через голову. Есть другой способ. Более элегантный и более эффективный. На счет несмешного анекдота, Ты не прав. То что я привел, описывает одну из основных свойств или сторон программирования. Если программа правильно написана, тогда она будет работать на компе, даже если эту программу писал пастух. Но если она не правильна, тогда она не будет работать, даже если солнышко по вечерам стучит в окно автора программы и спрашивает: Trainer, а завтра во сколько? И с востока или с запада. |
Сообщ.
#145
,
|
|
|
Лена, это снова я.
Не факт, что MapX будет совместим с очередной версией Билдера. Судя по твоей переписке с Синди, их это мало волнует. Пишут они свои примочки на VBA, у дяди Билли к ним претензий нет, остальное побоку. Поэтому не жди до декабря. Проблему можно можно решить радикально (не падай в обморок, у меня два раза был выбор - либо я делаю работу, либо пишу заявление) - установи Дельфи и к декабрю (а скорее всего - намного раньше) у тебя все получится. Сорри за лирику, но мне пришлось в пожарном порядке переходить с AutoLISP на Watcom C\C++ 10, а еще через три года - с Ваткома на Билдер. Не думаю, что переход Дельфи-Билдер окажется сложнее. Всем остальным - ребята, давайте жить дружно! Эмоции есть у всех, иногда прорывает - и не надо воспринимать это, как оскорбление. Честно говоря, trainer мог бы давно плюнуть на этот топик - но тем не менее пытается если не дать решение, то хотя бы приблизиться к истине (я не подлизываюсь, это мое мнение о нем и не только по этому топику). ЗЫ. if (FoundObj->FindRC % 10 == 1) { // ... } Всегда считал, что всякие Фаунды должны возвращать либо true/false, либо 1/0, либо addr/NULL. Но чтоб вот так |
Сообщ.
#146
,
|
|
|
Rosty
Цитата Теперь Ты утверждаешь, что MapX и Builder лучшие друзя. Ткни пальцем где я говорил это. Цитата Судя по Твоему ответу, делаю вывод, что, конечно и на твоем компе этот компонент не установлен. Не установлен, и я не считаю себя из-за этого ущербным. Цитата Для того, чтоб находить любой объект не нужна dll-ка, это через голову. Есть другой способ. Более элегантный и более эффективный. Я же написал, что это "на вскидку". Я, как и trainer, просто не хочу себе забивать голову этой проблемой. Но то, что решение этой проблемы существует - это 100%. Можешь считать меня самоуверенным, если честно, то мне пофиг. Цитата Если программа правильно написана, тогда она будет работать на компе, даже если эту программу писал пастух. trainer об этом же и говорил. Может хватит, а ? Я бы предложил тебе в приват перейти, но ты же не зарегистрирован. Эту тему я больше засорять не буду. Если есть желание, то можем по e-mail продолжить обсуждение этого вопроса. |
Сообщ.
#147
,
|
|
|
Rosty, открой личико!
|
Сообщ.
#148
,
|
|
|
По порядку:
Цитата Rosty @ Как мне кажется, программирование - точная наука и в привлечении для объяснения чьих-то проблем магии и прочих потусторонних сил не нуждается. Есть два варианта:Тип 2: "Да, код не работает. Borland здесь что-то явно нахимичил". 1) Источник проблем обнаружен и объяснен(здесь возникает ошибка потому, что...); 2) Источник проблем не обнаружен(магия, чертовщина, "здесь что-то явно нахимичил" и т.д. и т.п.). ASSERTE - это следствие, а не причина. Цитата Rosty @ Именно так. Если у меня возникнет подобная проблема - я ее решу. Решать проблемы других я не обязан.и договорились до "у меня нет дел до проблем некого Rosty". Цитата Rosty @ Для анекдотов есть раздел "Юмор". И лично мне не нравится, если мои ответы удаляют. |