Integrated Mapping Giriş

Integrated mapping bize MapBasic haricindeki programlama dillerini kullanarak kendi uygulamamızı geliştirmemizi ve MapInfo’yu kontrol etmemizi sağlar. Mesela uygulamamızın kullanıcı arayüzlerini Visual Basic ile istediğimiz gibi tasarlayıp bir yandan da uygulamamız içinde bir MapInfo haritasını kullanıcıya sunabiliriz. Bu tür uygulamalara integrated mapping denmesinin nedeni açıktır: MapInfo’nun bazı elemanlarını (harita penceresi, lejant, diyalog pencereleri vb.) başka bir uygulama ile entegre ediyoruz.

Konuya girmeden önce bazı terminolojiden bahsetmek faydalı olabilir:

DDE (Dynamic Data Exchange): Windows işletim sistemi altında farklı uygulamalar arasında iletişim kurmak için kullanılan bir teknolojidir. DDE’nin temel amacı, Windows programları arasında veriyi paylaştırmaktır. Mesela verileri sıklıkla güncellenen bir finans uygulamasında, Excel hücreleri başka bir uygulamadaki belli değerlere bağlanabilir ve bu değerler değiştikçe Excel sayfasındaki bağlı hücreler otomatik olarak güncellenebilir.

OLE (Object Linking and Embedding): Bir uygulamaya ait nesnelerin veya dokümanların başka uygulamalar tarafından kullanılabilmesini ve yönetilebilmesini sağlayan teknolojidir. İki türlü kullanılabilir:

  • Linking: Bir uygulama ile başka bir uygulamayı yönetmek (Visual Basic ile Excel’i kontrol ederek yeni bir Excel raporu oluşturmak gibi). Integrated mapping de bu kategoriye girer.
  • Embedding: Bileşik dokümanlar oluşturmak veya bir dokümana başka dokümanlar veya nesneler gömmek. (Web sayfalarına video veya Flash gömmek gibi)

OLE Automation: COM tabanlı bir prosesler arası iletişim mekanizmasıdır. Günümüzde kullanılan birçok programlama dilini kullanarak başka uygulamaları programatik olarak kontrol etmemizi sağlar. Tabi burada “her uygulamayı OLE otomasyonu ile kontrol edebilir miyiz?” gibi bir soru akla gelebilir. Bunun cevabı “hayır” dır. Çünkü bir uygulamayı OLE otomasyonu ile kontrol edebilmek için bu uygulamanın bazı nesnelerini export etmiş, diğer deyişle diğer uygulamalar için “paylaşıma açmış” olması gerekir. Bu paylaşım çoğu zaman COM arayüzleri şeklinde yapılır. Bu şekilde diğer “client” uygulamalar bu COM nesnelerine doğrudan erişebilir ve bunların sunduğu servisleri kullanabilir. Otomasyonun iki türü vardır: Lokal otomasyon ve uzak otomasyon. Uzak otomasyon bir ağ üzerinde ve DCOM (Distributed COM) kullanılarak yapılır. Integrated mapping uygulamaları lokal otomasyon kategorisine girer.

COM (Component Object Model): Yazılım bileşenleri için oluşturulmuş binary interface standardıdır. Muhtelif programlama dillerinde kullanılmak üzere,  prosesler arası iletişim kurabilmeyi ve dinamik nesneler oluşturmayı sağlamak için kullanılır. Bu şekilde örneğin C++ ile yazılmış COM nesnelerini (kütüphanesini) Visual Basic, Delphi, C# gibi dillerle kullanabiliriz. Yani COM bize programlama dilinden bağımsız bir arayüz sunar. Bunu şöyle bir örnekle açıklayabiliriz: Malumdur ki bilgisayarımız çok farklı markalara sahip CD sürücüleriyle problemsiz çalışabilir. Bunun nedeni CD sürücünün bilgisayar bağlantısının standart bir arayüze sahip olmasıdır. CD sürücüler bu standarda uygun olarak üretildiği için, farklı markalara sahip olsalar da bilgisayara takıldığında çalışabilmektedirler. COM terimi aslında OLE, OLE Automation, ActiveX, COM+ ve DCOM teknolojilerini içine alan geniş kapsamlı bir tabirdir.

Genel Özellikler

Bir integrated mapping uygulamasında kullanıcının görmekte olduğu harita canlı ve gerçek bir MapInfo haritasıdır. Yani bir imaj, bir export veya herhangi bir snapshot değildir. Uygulamamız açılırken yeni bir MapInfo örneği (yani prosesi) arka planda sessiz olarak başlar ve bu MapInfo prosesine ait harita, uygulamamıza ait bir “child” pencerede gösterilir.

İstediğimiz MapInfo haritasını uygulamamızdaki bir pencerede gösterdikten sonra sıra MapInfo’yu kontrol etmeye, diğer deyişle MapInfo’ya komutlar göndermeye gelir. Bu komut gönderme işini MapBasic komutlarını kullanarak yaparız. Uygulamamızdan MapInfo’ya MapBasic komutları gönderdiğimiz zaman, MapInfo sanki bu komutları MapBasic penceresine yazıp Enter tuşuna basmışız gibi çalıştırır.

Integrated mapping terminolojisinde, kullandığımız programlama dili (mesela Visual Basic) “client”, MapInfo ise “server” olarak tabir edilir. Yani programlama dili ile MapInfo’ya bir nevi bağlanır ve MapInfo’yu ihtiyacımıza göre gerekli komutlar ile kontrol ederiz. Bu kontrolün mümkün olabilmesi için söz konusu programlama dilinin OLE (Object Linking and Embedding) veya DDE (Dynamic Data Exchange) desteğinin olması gerekir. Günümüzde kullandığımız modern dillerin çoğunda zaten bu teknolojiler full olarak destekleniyor. (Java hariç. Bkz. Java ile Integrated Mapping.)

Kullanacağımız dilde olması gereken diğer iki şart ise, kullanıcı arayüzü oluşturabilme ve form bileşenlerinin handle (HWND) değerlerini bize sağlayabilmelidir. Mesela haritamızı göstermek için Visual Basic’te bir picture box kullanacak olursak, haritayı oluşturacağımız bu picture box bileşeninin HWND değerini uygulamamıza bildirmemiz gerekir.

Yukarıda bahsettiğimiz gibi, integrated mapping yapabilmek için OLE Automation ve DDE olmak üzere 2 seçeneğimiz var. Bunlardan OLE seçeneği şiddetle tavsiye ediliyor çünkü OLE daha hızlı ve sağlam ve nispeten yeni bir teknoloji. Ayrıca OLE, runtime hata kodlarını ve mesajlarını sunmak suretiyle geliştiriciler için daha iyi bir hata raporlaması sunuyor. DDE kullandığımızda runtime hata kodlarını alma şansımız yok.

Basit Bir Integrated Mapping Uygulaması: “Hello Map of 🙂 World”

Önce Visual Basic 6.0 ile yeni bir Standart Exe uygulaması oluşturun. Otomatik olarak gelen Form1 adlı formumuzun kod ekranının üst tarafındaki General Declarations kısmında aşağıdaki gibi bir Object değişken tanımlayın:

Dim mi as Object

Daha sonra haritayı göstereceğimiz formun Form_Load prosedürüne şu kodları yazın:

Sub Form_Load()
  Set mi = CreateObject("MapInfo.Application")
  mi.do "Set Application Window " & Form1.hWnd
  mi.do "Set Next Document Parent " & Form1.hWnd & " Style 1"
  mi.do "Open Table """ & App.Path & "\" & "World"" Interactive Map From World"
  mi.RunMenuCommand 1702
End Sub

App.Path özelliği Visual Basic’te o anda çalışmakta olan uygulamanın, diğer deyişle exe dosyasının bulunduğu dizinin yolunu döndürür. Dolayısıyla bu örneği çalıştırabilmek için Visual Basic uygulamamızın exe sinin yanında gerekli MapInfo dosyalarımızın (World.TAB ve diğerleri) olması gerekir.

Projeyi çalıştırdığımızda harita penceresi Visual Basic formunun bir “child” penceresi gibi görülür.

Şimdi yukarıdaki kodları yakından inceleyelim:

MapInfo uygulamasını temsil eden “mi” değişkenimizi form seviyesinde global olarak tanımlamıştık. Şimdi MapInfo’nun yeni bir örneğini (instance) oluşturalım ve bunu “mi” Object değişkenimize atayalım:

Set mi = CreateObject("MapInfo.Application")

CreateObject() metodu bir COM nesnesi oluşturmak ve bunu bir Object değişkene atamak için kullanılır. Makinemize MapInfo kurduğumuz zaman MapInfo kendisini COM veritabanına register eder, yani kaydeder. Diğer deyişle MapInfo, COM arayüzü (interface) sayesinde kendisini bir COM nesnesi olarak diğer programlara sunabilir ve bu şekilde programlanabilme olanağı sağlar. Neyse konuyu biraz dağıttık gibi… Bu şekilde “mi” değişkenimize yeni bir MapInfo örneği (prosesi) atayarak daha sonra Do, Eval, RunMenuCommand vb. metotlarını kullanma şansını elde ederiz.

Eğer MapInfo Professional yerine MapInfo Runtime ürününü kullanırsak yukarıdaki satır şöyle olmalıdır:

Set mi = CreateObject("MapInfo.Runtime")

Bu şekilde yeni bir MapInfo prosesi oluşturmuş ve MapInfo’ya bağlanmış olduk.

Şimdi MapInfo diyalog pencerelerinin ve mesaj kutularının Visual Basic formumuz tarafından sahiplenmesi için “Set Application Window” MapBasic komutunu kullanmamız gerekir:

mi.do "Set Application Window " & Form1.hWnd

Yani uygulamamızda MapInfo diyalog pencerelerini (katman kontrolü gibi) açtığımızda Form1 adlı Visual Basic formu bu diyalog pencerelerinin “parent” formu olacaktır.

Daha sonra MapInfo harita penceresinin Visual Basic uygulamamızda nerede gösterileceğini belirtmemiz gerekir. Bunun içinde “Set Next Document” MapBasic komutunu kullanacağız:

mi.do "Set Next Document Parent " & Form1.hWnd & " Style 1"

Bu şekilde MapInfo haritamız Form1 adlı Visual Basic formumuzda gösterilecektir. “Set Next Document” komutunun yaptığı iş aslında MapInfo’nun map, browser, graph, layout ve legend pencerelerinin sahipliğini MapInfo’dan alıp, belirttiğimiz Visual Basic formuna vermek, diğer deyişle söz konusu MapInfo pencerelerini kendi uygulamamızdaki bir pencerede göstermektir.

Set Next Document komutunun son kısmındaki “Style” parametresi ile, oluşturacağımız pencerenin tipini ayarlayabiliriz:

Style 1: Kenarlığı (border) olmayan bir child pencere

Style 2: Yarım başlık çubuğuna sahip bir popup pencere (MapInfo lejant penceresi gibi)

Style 3: Tam başlık çubuğuna sahip bir popup pencere

Şimdi de örnek uygulamamızdaki bir sonraki satırı inceleyelim. Artık sıra geldi haritada göstereceğimiz MapInfo tablosunu açmaya. Bunun için de “Open Table” ve ardından “Map From” MapBasic komutlarını kullanacağız:

mi.do "Open Table """ & App.Path & "\" & "World"" Interactive Map From World"

Open Table komutu, belirttiğimiz MapInfo tablosunu belleğe yükleyerek kullanıma hazır hale getirir. Burada World tablosunun etrafındaki ikişer çift tırnağın anlamı şudur: Eğer MapBasic içinden World tablosunu açan bir program yazsaydık şöyle olacaktı:

Open Table "World"

Visual Basic dilinde string bir ifade içinde çift tırnak kullanmamız gerektiğinde bunu yan yana iki adet çift tırnak kullanarak yapabiliriz. Bu yüzden

mi.do "Open Table """ & App.Path & "\" & "World"" Interactive"

şeklinde yazdık. Aynı satırda bulunan “Map From World” komutu ise World tablosunu harita penceresinde açmaya yarar. Dikkat edilirse

mi.do "Open Table """ & App.Path & "\" & "World"" Interactive Map From World"

satırında aslında  2 farklı komutu tek seferde çalıştırmış olduk. Bu işlem MapBasic’te tamamen legaldir; yani farklı komutlar arasına boşluk koymak şartıyla birden fazla komutu tek seferde çalıştırabiliriz. MapBasic böyle bir satırın birden fazla komut içerdiğini anlar ve bu komutları yazım sırasına göre çalıştırır. Yukarıdaki satırı aşağıdaki gibi 2 farklı komut satırı olarak da yazabilirdik:

mi.do "Open Table """ & App.Path & "\" & "World"" Interactive"
mi.do "Map From World"

Bu şekilde World tablosunu açmış ve harita penceresi görünümüyle göstermiş olduk. Son olarak, haritayı kaydırabilmek için “pan” aracını aktif edelim:

mi.RunMenuCommand 1702

RunMenuCommand komutu ile standart MapInfo araç çubuğu butonlarının yaptığı işi kendi uygulamamızda oluşturduğumuz butonlarla yapabiliriz. Yani Visual Basic’te bir araç çubuğu butonu oluşturup bu butonun koduna

mi.RunMenuCommand 1702

yazarsak, bu butona tıklandığında, tıpkı MapInfo’nun araç çubuğundaki “pan” (kaydırma) butonuna tıklamış gibi oluruz. RunMenuCommand komutuyla ilgili daha detaylı bilgiyi aşağıdaki MapInfo’nun Araç Çubuğundaki Butonları Entegre Etme kısmında bulabilirsiniz.

Böylece ilk basit integrated mapping uygulamamızı yazıp çalıştırmış olduk. Şimdi de integrated mapping ile ilgili diğer önemli birkaç noktaya değinelim.

MapInfo’dan Bilgi Sorgulama

Integrated mapping uygulamamızda çoğunlukla Do() metodunu kullanırız. Ama bazı durumlarda MapInfo veya MapInfo tabloları ile ilgili bazı bilgileri sorgulama ihtiyacı duyabiliriz. Mesela bir MapInfo tablosunda kaç adet kayıt olduğunu bilmek isteyebiliriz. Bunun için Eval() metodunu kullanmamız gerekir. Eval() metodunu kullandığımız zaman MapInfo yazmış olduğumuz string değerini bir MapBasic ifadesi (expression) olarak yorumlar ve bu ifadenin değerini bize (yani Visual Basic tarafına) string olarak döndürür. Aşağıdaki kod parçası World tablosundaki kayıt sayısını bize verir:

mi.eval("TableInfo(""World"", 8)")

TableInfo açık bir tablo hakkında bilgiler döndüren bir MapBasic fonksiyonudur. Bunu MapInfo’nun Eval() metodu ile birlikte kullanarak bu şekilde World tablosunun kayıt sayısını Visual Basic tarafında almış olduk.

Eval() metodu ile alabileceğimiz başka bir bilgi ise, bir tablodaki belli bir satıra ve sütuna ait bir değer olabilir. Örneğin aşağıdaki kod parçası World tablosundaki ilk ülkenin adını döndürür:

mi.do "fetch first from World" ‘İlk kayda git
Dim firstCountry As String
firstCountry = mi.eval("World.Country") ‘İlk kayıttaki Country kolon değerini al

Not: Eğer Eval() metodunda kullandığımız ifade bir Logical değer içeriyorsa MapInfo bize “T” veya “F” değerlerinden birini döndürür.

MapInfo’nun Araç Çubuğundaki Butonları Entegre Etme

MapInfo’nun araç çubuğundaki standart butonları (seçme, büyütme, küçültme vb.) integrated mapping uygulamamızda doğrudan kullanma şansımız yoktur. Uygulamamızda kullanıcıya bu tür araçlar sunabilmek için kendi araç çubuğu butonlarımızı oluşturmamız gerekir. Bunun için Visual Basic’te yeni bir araç çubuğu butonu oluşturup bu butonun altındaki koda

mi.RunMenuCommand <Buton Kodu>

komutunu yazmamız gerekir.

Şimdi örnek uygulamamızdaki

mi.RunMenuCommand 1702

satırını inceleyelim: Buradaki 1702 değeri MapBasic’in kurulum dizininde bulunan MENU.DEF dosyasında M_TOOLS_RECENTER sabitiyle tanımlanmıştır. MapInfo araç çubuğunda bulunan seçme, büyütme, küçültme, info alma gibi diğer standart işlemlerin kodlarını öğrenmek için bu dosyaya bakmamız gerekir.

Bu değerleri tanımlarken yukarıdaki gibi “ezbere” bir yöntem yerine daha kullanışlı yöntemler kullanabiliriz. Mesela integrated mapping uygulamamızda kullanacağımız bu standart MapBasic araçlarının kodlarını tutan bir sınıf (class) yazabiliriz. Bu sınıfta gerekli araçların kodlarını sabit tamsayılar (constant integer) veya enumeration tipi olarak tanımlayabilir ve bunları daha sonra kodumuzda gerekli yerden daha kullanışlı bir şekilde çağırabiliriz. Bu şekilde kullanacağımız araçların kod numaralarını (yukarıdaki 1702 gibi) hatırlamak zorunda kalmayız.

Not: Bahsettiğimiz sınıf Visual Basic ve C dilleri için zaten mevcuttur. MapBasic kurulum dizinindeki MAPBASIC.BAS header dosyası Visual Basic, MAPBASIC.H ise C dili için zaten verilmiştir. Bu ikisi dışındaki diller için (C#, Delphi gibi) bu sınıfı bizim oluşturmamız gerekir.

MapInfo’nun Kısayol Tuşlarını Kullanma

MapInfo’nun kısayol tuşları integrated mapping uygulamalarında çalışmaz. Mesela Visual Basic ile yazdığımız uygulamamızda, haritadan bir nesne seçip klavyeden Ctrl+C tuşlarına bastığımızda kopyalama işlemi gerçekleşmeyecektir. Bu yüzden tıpkı MapInfo’nun araç çubuğu butonlarını Visual Basic tarafında oluşturduğumuz gibi, MapInfo’nun kısayol tuşlarını yine Visual Basic tarafında halletmemiz gerekir.

Fakat bu durumun istisnaları vardır: Snap ve Cross tuşları. Integrated mapping uygulamamızda klavyeden S veya C tuşlarına basarsak haritanın snap/cross özellikleri açılıp kapanacaktır.

  1. No comments yet.
  1. No trackbacks yet.

Leave a comment