Добрый день коллеги.
Столкнулся с такой загадкой:
Понадобилось использовать ActiveX компонент MapWinGis http://www.mapwindow.org/ для создания картографической информации в Delphi. Скачал, установил, импортировал, установил, сделал тестовый проект и столкнулся с такой проблемой, компонент не работает в следующем тривиальном коде:
var
Sh : IShapefile;
begin
Sh := CoShapefile.Create;
IF OpenDialog1.Execute then
begin
if not Sh.Open(OpenDialog1.FileName, nil) then
ShowMessage('err!');
try
Map1.AddLayer(sh,true); // выдает ошибку после чего, карта становится черным цветом
Map1.ZoomToMaxExtents;
except
On E:Exception do
ShowMessage(E.Message);
end;
end;
Ну не работает и не работает и бог с ним, но однако дернул меня черт проверить похожий код в C++ Builder-е
void __fastcall TfrmMain::aLoadSHPExecute(TObject *Sender)
{
if (OpenDialog1->Execute())
{
IShapefilePtr shapefile1;
shapefile1.CreateInstance(CLSID_Shapefile);
shapefile1->Open(OpenDialog1->FileName.w_str(), NULL );
Map1->AddLayer(shapefile1,true); // работает
}
}
И там он заработал, пошел дальше проверил в C# и Visual Basic - ТОЖЕ РАБОТАЕТ!
В общем работает везде, но только не в Delphi! Вот и сижу гадаю, вроде ActiveX является универсальным так сказать компонентом и доступен их всех языков поддерживающих данную технологию и ПО ИДЕЕ в DELPHI должен работать. Или что то Delphi делает не так, что вызывает ошибку в данной ActiveX. Такие вот пироги с котятами. У кого какие идеи?
Судя по примеру Sh должно быть типа Shapefile
ОтветитьУдалитьВ том то и дело что Shapefile = IShapefile, то есть в AddLayer передается интерфейс. Но почему то в Delphi выходит ошибка EZeroDivide а в других языках программирования ее и нет. И это для меня увы большая загадка. Ну и разочарование конечно, так как MapWinGis довольно мощный OpenSource компонент для поддержки карт
ОтветитьУдалитьИ все же обратите внимание на то, что в примерах, которые можно скачать на сайте, везде используется подход вроде
ОтветитьУдалитьvar
sf: MapWinGIS_TLB.Shapefile;
begin
sf := CoShapefile.Create();
sf.Open('c:\dev\data\dan.shp', nil);
Map1.AddLayer(sf, true);
Как мне кажется, в вашем варианте после Sh.Open объект Sh будет автоматически уничтожен... Из-за автоматического подсчета ссылок.
Да нет, в таком случае она будет уничтожена при выходе из процедуры, а код до выхода не выполняется.
ОтветитьУдалитьдаже если sh перенести в класс, чтобы гарантировать неудаление, ошибка все равно остается.
type
TForm2 = class(TForm)
Map1: TMap;
OpenDialog1: TOpenDialog;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Sh : IShapefile;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
begin
Sh := CoShapefile.Create;
IF OpenDialog1.Execute then
begin
if not Sh.Open(OpenDialog1.FileName, nil) then
ShowMessage('err!');
try
Map1.AddLayer(sh,true);
Map1.ZoomToMaxExtents;
except
On E:Exception do
ShowMessage(E.Message);
end;
end;
end;
end.
К сожалению на своей XE проверить не могу.
ОтветитьУдалитьПримеры-то проходят? С ShapeFile? Ведь зачем-то они в обоих примерах используют именно ShapeFile...
Поэтому у меня чисто интуитивно складывается ощущение что тут тот самый азбучный принцип "никогда не смешивать модель объекта и модель интерфейса".
Это то понятно, но увы даже демо-примеры не проходят. То есть простейший пример
ОтветитьУдалитьvar
sf: MapWinGIS_TLB.Shapefile;
begin
sf := CoShapefile.Create();
sf.Open('c:\dev\data\dan.shp', nil);
Map1.AddLayer(sf, true);
выдает ошибку в AddLayer. И это только в Delphi, как я и писал в C++ С# и VB такой код выполняется без проблем
Мало того если код переделать так
var
sf: MapWinGIS_TLB.TShapefile;
begin
sf := TShapefile.Create(self); // Испольуется класс. а не интерфейс
sf.Open('c:\dev\data\dan.shp', nil);
то тоже самое, Класс TShapefile это класс созданный Delphi при импортировании ocx.
Спасибо за помощь
Найдено решение проблемы
ОтветитьУдалитьhttp://deeptown12.blogspot.com/2011/01/mapwingis-delphi-activex.html