Borland Delphi/C++Builder OTA Hakkında Bilgi
OTA Nedir ?
Delphi IDE’ni kullandığı ve IDE içinde kullanılan servislere kısaca OTA (Open Tools API) denir. Diğer bir deyişle Delphi IDE için yazılan Plug-in’ler olarak da bilinirler. OTA açıklamaları ve class tanımları ToolsAPI.pas içindedir. Delphi help içerisinde OTA konusunda herhangi bir dokumana rastlanmamaktadır. Daha fazla bilgi için ToolsAPI.pas incelenebilir. Bulunduğu yer, Delphi’yi kurduğunuz klasörün altında BDS\4.0\Source\ToolsAPI\ToolsAPI.pas. (Delphi 2005 için 3.0)
ToolsAPI.pas bakıldığında bazı global değişkenler göze çarpacaktır.
Bunlar:
BorlandIDEServices: IBorlandIDEServices;
SplashScreenServices: IOTASplashScreenServices;
SplashScreenServices: Delphi açılırken global olarak bu değişkeni tanımlar. Bu değişken Delphi açıldığında ilk geçerli olan değişkendir.
BorlandIDEServices: Delphi açıldığı zaman global olarak bu değişken geçerli hale gelir. Bu değişken SplashScreenServices değişkeninden sonra geçerli hale gelir. Çeşitli servislere ulaşmak için bu global değişkenden faydalanılır. Bütün IxxxServices ile başlayan servislere ulaşmak için BorlandIDEServices değişkeni temel olarak alınır.
Örneklemek gerekirse, IOTAModuleServices servisini kullanmak için kısaca QueryInterface metodunu çağırarak mu metodun var olup olmadığını kontrol ederiz. Çünkü bazı servisler bazı Delphi modellerinde tanımı olmayabilirler. Örneğin, IOTAToDoServices servisi yalnızca Delphi Professional ve Delphi Enterprise versiyonlarında tanımlıdır.
Kullanımı şöyle kontrol edilir.
var
ms : IOTAToDoServices;
begin
...
...
if BorlandIDEServices.QueryInterface(IOTAToDoServices, ms) = S_OK then
//ya da if Supports(BorlandIDEServices, IOTAToDoServices, ms) then
begin
//Delphi IDE bu servisi destekler, bu durumda dönen değer
//ms ile bu servis özellikleri kullanılabilir,
ms.UpdateList;
...
...
end;
...
end;
Bir Delphi IDE servisini Delphi’ye tanımlamak için Register adlı procedur kullanılır.
Delphi bunu otomatik olarak arar ve çalıştırır.
Örnek programlar
SplashScreen servisi:
Şimdi basit bir SplashScreen IDE servisi yazalım.
Not: Delphi 2006 kullanıyorum, diğer Delphi versiyonlarında da hemen hemen benzer menüler vardır.
1.Delphi Win32 package yaratalım. (File->New->Package)
2.Bu bir DesignTime package olduğu için Project Manager’da Requires üzerinde Sağ tıklayarak designide.dcp ekleyelim.

3.Yeni bir Unit ekleyiniz (File->New->Unit)
4.MainUnit olarak save ediniz.
5.MainUnit.pas dosyasını aşağıdaki biçimde değiştiriniz.
unit MainUnit;
interface
uses
ToolsAPI;
procedure Register;
implementation
uses
Graphics;
{$R IMAJ_DEPOSU.RES}
const
BMP = 'BMP_SCREEN';
procedure InstallSplash;
var
lBitmap: TBitmap;
begin
if SplashScreenServices = nil then
Exit;
lBitmap := TBitmap.Create;
try
lBitmap.LoadFromResourceName(hInstance, BMP);
SplashScreenServices.AddPluginBitmap('Yükleniyor...', lBitmap.Handle, False, 'Version 0.0.1', 'Klavye servisi'); //Buradaki False True yapılırsa, yazı kırmızı renkte çıkar
finally
lBitmap.Free;
end;
end;
procedure Register;
begin
InstallSplash;
end;
end.
6.Compile (Ctrl-F9) ettiğimiz zaman “File not found: IMAJ_DEPOSU.RES” mesajı verecektir.
7.IMAJ_DEPOSU.RES dosyasını hazarlamamız gerekir, bunun için
a. Bir tane 48x48 idel boyutlarda olmak üzere (16x16 da olabilir) bir tane bitmap dosyası bulalım. BK3.BMP olsun.
b.Notepad de ya da herhanig bir test editörde IMAJ_DEPOSU.RC (Resource File) adlı bir dosya yaratalım.
c. IMAJ_DEPOSU.RC dosyası içine BMP_SCREEN Bitmap "BK3.bmp" satırını aşağıdaki gibi ekleyelim.

d.IMAJ_DEPOSU.RES dosyasını yaratmak için projeyi save ettiğiniz klasörde command prompt satırında aşağıdaki komutu kullanınız. (brc32 –r IMAJ_DEPOSU.RC)
8.IMAJ_DEPOSU.RES dosyamız hazır olduğu için artık compile (Ctrl-F9) edebiliriz.
9.Bu package design time package olduğu için bunu tanımlamamız gerekir. Bunu yapmak için package üzerinde sağ tıklayarak Options seçiniz. Aşağıdaki gibi değişiklik yapınız.
10.OK ile onaylayınız, artık bu package install edebilir.
11.Install etmek için Project Manager'de package üzerinde sağ tıklayarak Install seçeneğini seçiniz.
12.Package’in install edildiğine dair ekrana bir mesaj çıkacaktır.
13.Ayrıca Install edildiğiniz Delphi menüsünden de görebiliriz. “Component->Install Packages...” ile ekran aşağıdaki gibi olmalıdır.

14.Delphi’yi kapatıp açtığınızda package’niz ile ilgili mesaj, ekranda aşağıdaki gibi çıkacaktır.
Delphi IDE’nizin sizden başka kimsenin açmasını istemiyorsanız.
1.Daha önce hazırladığımız unit MainUnit dosyası üzerinde bazı değişiklikler yapalım.
2.unit MainUnit dosyamızı aşağıdaki gibi değiştirelim.
unit MainUnit;
interface
uses
ToolsAPI;
procedure Register;
implementation
uses
Graphics, Dialogs;
{$R IMAJ_DEPOSU.RES}
const
BMP_SCREEN = 'BMP_SCREEN';
procedure InstallSplash;
var
lBitmap: TBitmap;
str:string;
rc : Boolean;
begin
if SplashScreenServices = nil then
Exit;
lBitmap := TBitmap.Create;
try
lBitmap.LoadFromResourceName(hInstance, BMP_SCREEN);
//Buradaki False True yapılırsa, yazı kırmızı renkte çıkar
SplashScreenServices.AddPluginBitmap('Loading...',
lBitmap.Handle, True, 'Version 0.0.1', 'Testing');
str := '';
rc := InputQuery('Şifre', 'Kod:', str);
if not rc then Halt(1); {Programdan çıkınız, yani
IDE'nin çalışmasına izin vermeyiniz.}
if str <> 'GizliSifre' then Halt; //Aynı şekilde byee.
finally
lBitmap.Free;
end;
end;
procedure Register;
begin
InstallSplash;
end;
end.
3.Herşeyimizi tekrar Save edelim. (Şifre sorduğunda yanlışlıkla ESC basarsak Delpi kapanır!)
4.Compile (Ctrl-F9) edelim, package daha önce install edildiği için ayrıca tekrar Install etmemize gerek yoktur.
5.Delphi’den çıkıp tekrar çalıştırdığımızda, bir süre sonra sizden şifre isteyecektir.
6.'GizliSifre' dışında ya da ESC tuşuna ya da Cancel butonuna basarsak Delphi KAPANIR!!.
7.Böylece install ettiğiniz package’yi koruma altına aldıktan sonra Delphi’nizi sizden başka kimse kullanamayacaktır.
Not1: InputQuery yerine sizin kullandığınız herhangi bir Form da kullanabilirsiniz.
Not2: Bu servisi değiştirip Compile ettiğimizde her durumda Register çalışacaktır.
Klavye servisi:
Daha önce yaptığımız örneği geliştirerek Ctrl+Shift+D tuş kombinasyonları yardımı ile Delphi içinde çalıştığımız bir dosyada bir kelimeyi işaretleyip hafızaya kopyalayalım. Normal olarak bir kelineyi kopyalamak için kelimeyi işaretyelip Ctrl-C tuşuna basarız. Bu servisde ise kelime üzerindeyken (Kelimeyi işaretlemeye gerek yok) Ctrl+Shift+D tuş yardımı ile işaretleyip hafızaya kopyalarız. Kısaca nasıl yapıldığına bakalım.
Bu özelliği kullanmak için IOTAKeyboardBinding servisinden yararlanılır.
ToolsAPI.pas dosyasına baktığımızda, IOTAKeyboardBinding elemanları kısaca şöyledir:
IOTAKeyboardBinding = interface(IOTANotifier)
['{F8CAF8D7-D263-11D2-ABD8-00C04FB16FB3}']
function GetBindingType: TBindingType;
function GetDisplayName: string;
function GetName: string;
procedure BindKeyboard(const BindingServices: IOTAKeyBindingServices);
property BindingType: TBindingType read GetBindingType;
property DisplayName: string read GetDisplayName;
property Name: string read GetName;
end;
Metodları kısaca açıklamak gerekirse:
function GetBindingType: Burada Delphi’ye kullanılacak tuş setinin tipini tanıtıyoruz, yeni bir set mi (btComplete) yoksa sadece var olan bir setini mi genişletiyoruz (btPartial) ?
function GetDisplayName: Editor options da Key Mapping kısmında görülecek isim.
function GetName: Servis için kullanılan Unique bir isim. Format olarak, genellikle adiniz.servisadi. Türkçe karakterler kullanılmamalıdır.
procedure BindKeyboard(const BindingServices: IOTAKeyBindingServices): Servisi Delphi sistemine tanıtıyoruz. Bunun için IOTAKeyBindingServices servisinin AddKeyBinding metodunu çağırırız.
Daha önce yaptığımız kod üzerinde aşağıdaki değişikliği yapalım.
Şimdilik şifre sorma kısmını iptal edelim gerektiğinde tekrar ekleriz.
unit MainUnit;
interface
uses
ToolsAPI, Menus, Classes;
type
TycKeyboardBinding = class(TNotifierObject, IOTAKeyboardBinding)
private
{ IOTAKeyboardBinding }
procedure BindKeyboard(const BindingServices: IOTAKeyBindingServices);
function GetBindingType: TBindingType;
function GetDisplayName: string;
function GetName: string;
procedure TusExecute(const Context: IOTAKeyContext;
KeyCode: TShortcut;
var BindingResult: TKeyBindingResult);
end;
procedure Register;
implementation
uses
Graphics, Dialogs, SysUtils;
{$R IMAJ_DEPOSU.RES}
const
BMP_SCREEN = 'BMP_SCREEN';
procedure InstallSplash;
var
lBitmap: TBitmap;
// str:string;
// rc : Boolean;
begin
if SplashScreenServices = nil then
Exit;
lBitmap := TBitmap.Create;
try
lBitmap.LoadFromResourceName(hInstance, BMP_SCREEN);
SplashScreenServices.AddPluginBitmap('Loading...',
lBitmap.Handle, True, 'Version 0.0.1',
'Klavye servisi'); {Buradaki False değeri True
yapılırsa, yazı kırmızı renkte çıkar}
{!!Şimdilik iptal edelim
str := '';
rc := InputQuery('Şifre', 'Kod:', str);
if not rc then Halt(1); //Programdan çıkınız, yani IDE'nin çalışmasına
//izin vermeyiniz.
if str <> 'GizliSifre' then Halt;
}
finally
lBitmap.Free;
end;
end;
var
TusTakimiIndex : Integer;
procedure Register;
var
KeyboardServices: IOTAKeyboardServices;
begin
TusTakimiIndex := -1;
InstallSplash;
if Supports(BorlandIDEServices, IOTAKeyboardServices,
KeyboardServices) then
TusTakimiIndex := KeyboardServices.AddKeyboardBinding
(TycKeyboardBinding.Create);
end;
{ TycKeyboardBinding }
procedure TycKeyboardBinding.BindKeyboard(
const BindingServices: IOTAKeyBindingServices);
begin
BindingServices.AddKeyBinding([ShortCut(Ord('D'),
[ssCtrl, ssShift])], TusExecute, nil);
end;
function TycKeyboardBinding.GetBindingType: TBindingType;
begin
//Sadece var olan bir tuş setini genişletiyoruz (btPartial)
Result := btPartial;
end;
function TycKeyboardBinding.GetDisplayName: string;
begin
//Editor options da görülecektir
Result := 'Test servisim'
end;
function TycKeyboardBinding.GetName: string;
begin
//Unique bir isim
Result := 'YusufCELIK.KlavyeTest'
end;
//Ctrl+Shift+D tuş kombinasyonuna basıldığında çalışacak rutin.
procedure TycKeyboardBinding.TusExecute(const Context: IOTAKeyContext;
KeyCode: TShortcut; var BindingResult: TKeyBindingResult);
const
CharSet = [' ', ';', '(', ')', '=', ':', ',', '.', '-', '+', '''',
'[', ']', '>', '<', '*', '/', '\'];
var
Row : Integer;
ColStart : Integer;
ilkCol : Integer;
Col : Integer;
ColEnd : Integer;
i : Integer;
str : string;
begin
{BindingResult değerine göre Delphi karar verir:
krUnhandled : Tuş kombinasyonu bu procedur içinde işlem görmedi,
bu tuş kombinasyonun kullanan bir sonraki
procedur de kullanılabilir.
Yani Delphi IDE'sinde bu tuş kombinasyonunu
kullanan bir menu var ise işlem görür.
krHandled : Tuş kombinasyonu bu procedur içinde işlem gördü,
bu tuş kombinasyonu ile ilgili başka işlem
yapılmayacaktır.
krNextProc : Bu tuşu kullanan bir sonraki procedur bu tuşu
kullanabilir, ancak hiç bir menu işlem
görmez.
Yani Delphi IDE'sinde bu tuş kombinasyonunu
kullanan bir menu var ise işlem görmez.
}
BindingResult := krHandled;
//Context.EditBuffer.EditPosition editorle ilgili
//bilgilere ulaşabilirsiniz
Row := Context.EditBuffer.EditPosition.Row; //Cursor satırını al
Col := Context.EditBuffer.EditPosition.Column; //Cursor sütununu al
Context.EditBuffer.EditPosition.MoveEOL;
//satırdaki karakter sayısını bulalım
i := Context.EditBuffer.EditPosition.Column;
Context.EditBuffer.EditPosition.MoveBOL;
str := Context.EditBuffer.EditPosition.Read(i); //satırı kopyalayalım
ColEnd := Length(str)+1;
ColStart := Col;
while ColStart > 0 do
begin
if not (str[ColStart] in CharSet) then
Break;
Dec(ColStart)
end;
ilkCol := ColStart;
for i := ColStart to Length(str) do
begin
if str[i] in CharSet then
begin
ColEnd := i;
Break;
end;
end;
ColStart := 0;
for i := ilkCol downto 1 do
begin
if str[i] in CharSet then
begin
ColStart := i+1;
Break;
end;
end;
if (ColStart <> 0) and (ColEnd <> 0) then
begin
//Cursor’u Row satır ColStar sütuna götür
Context.EditBuffer.EditPosition.Move(Row, ColStart);
//Bu satır ve kolondan işaretlemeye başla
Context.EditBuffer.EditBlock.BeginBlock;
// Cursor’u Row satır ColEnd sütuna götür
Context.EditBuffer.EditPosition.Move(Row, ColEnd);
//Bu satır ve kolondan işaretlemeye bitir
Context.EditBuffer.EditBlock.EndBlock;
//İşaretlenen kelimeyi ClipBoarda kopyala
//Buradaki False, ClipBoard’daki değer ezilsin demektir
Context.EditBuffer.EditBlock.Copy(False);
//Aşağıdaki satır neyi kopyaladığımızı görmek içindir.
//Çalıştığından emin olduktan sonra silebiliriz.
str := Copy(str, ColStart, ColEnd-ColStart);
ShowMessage('Kopyalandı...'+#13#10+
'Kopyalanan değer:['+str+']');
end
else
begin
Context.EditBuffer.EditPosition.Move(Row, Col); //eski satır/kolona gidelim
end;
end;
finalization
//Regiter procedurunda yapılanın tam tersi, yani servisi uninstall eder.
if TusTakimiIndex <> -1 then
(BorlandIDEServices as IOTAKeyboardServices).RemoveKeyboardBinding(
TusTakimiIndex);
end.
Yapılan son değişikliklerden sonra Compile edersek ekrana bir mesaj çıkarak servisi yükler.
Editor Options’a bakıldığında daha önce belirttiğimiz gibi aşağıdaki isimle kayıt edildiğini görürüz.
function TycKeyboardBinding.GetDisplayName: string;
begin
//Editor options da görülecektir
Result := 'Test servisim'
end;
Bir sonraki konumuza geçmeden önce yukarıdaki örnekte sıkça kullandığımız interface IOTAEditPosition hakkında bilgi verelim. Önce yapısına bakalım.
IOTAEditPosition = interface(IUnknown)
['{9C510464-C7BC-11D2-9AEB-00A02457621F}']
procedure
function BackspaceDelete(HowMany: Integer): Boolean;
function Delete(HowMany: Integer): Boolean;
function DistanceToTab(Direction: TSearchDirection): Integer;
...
...
function GotoLine(LineNumber: Integer): Boolean;
procedure InsertBlock(const Block: IOTAEditBlock);
procedure InsertCharacter(Character: Char);
procedure InsertFile(const FileName: string);
procedure InsertText(const Text: string);
function Move(Row, Col: Integer): Boolean;
function MoveBOL: Boolean;
function MoveCursor(MoveMask: TMoveCursorMasks): Boolean;
function MoveEOF: Boolean;
function MoveEOL: Boolean;
function MoveReal(Row, Col: Integer): Boolean;
function MoveRelative(Row, Col: Integer): Boolean;
procedure Paste;
function Read(NumberOfCharacters: Integer): string;
function RepeatLastSearchOrReplace: Boolean;
function Replace(const Pattern, ReplaceText: string;
CaseSensitive, RegularExpression,
WholeFile: Boolean; Direction: TSearchDirection;
var ErrorCode: Integer): Integer; overload;
function Replace: Integer; overload;
function ReplaceAgain: Integer;
procedure Restore;
function RipText(const ValidChars: TSysCharSet;
RipFlags: Integer): string; overload;
function RipText(const ValidChars: string;
RipFlags: Integer): string; overload;
procedure Save;
function Search(const Pattern: string; CaseSensitive,
RegularExpression,
WholeFile: Boolean; Direction: TSearchDirection;
var ErrorCode: Integer): Boolean; overload;
function Search: Boolean; overload;
function SearchAgain: Boolean;
procedure Tab(Magnitude: Integer);
property Character: Char read GetCharacter;
property Column: Integer read GetColumn;
property IsSpecialCharacter: Boolean read GetIsSpecialCharacter;
property IsWhiteSpace: Boolean read GetIsWhiteSpace;
property IsWordCharacter: Boolean read GetIsWordCharacter;
property LastRow: Integer read GetLastRow;
property ReplaceOptions: IOTAReplaceOptions read GetReplaceOptions;
property Row: Integer read GetRow;
property SearchOptions: IOTASearchOptions read GetSearchOptions;
end;
Interface IOTAEditPosition kısaca, Delphi içinde iken, o anda kod ya da başka bişey yazdığınız yazı üzerinde bulunan cursor ile ilgili bilgileri içerir. Bu bilgiler şöyle özetlenebilir.
Cursorun üzerinde bulunduğu, karakter nedir (Context.EditBuffer.EditPosition.Character) ?
Cursor kaçıncı satırda, kaçıncı sütündadır
(Context.EditBuffer.EditPosition.Column ya da Row ) ?
Bir kelime mi (Context.EditBuffer.EditPosition.IsWordCharacter) ?
Üzerinde çalışılan dosyanın son satır sayısı (Context.EditBuffer.EditPosition. LastRow) ?
Editör’de hangi satıra gitmek istiyorsunuz (Context.EditBuffer.EditPosition. GotoLine) ?
Editör’de hangi satır/sütün gitmek istiyorsunuz (Context.EditBuffer.EditPosition. Move) ?
Bulunduğumuz satırın sonuna gitmek (Context.EditBuffer.EditPosition.MoveEOL) ?
Bulunduğumuz satırın başına gitmek (Context.EditBuffer.EditPosition.MoveBOL) ?
Dosyanın sonuna gitmek (Context.EditBuffer.EditPosition.MoveEOF) ?
Clipbordakini yapıştırmak (Context.EditBuffer.EditPosition.Paste) ?
Karakter dizisi insert etmek için (Context.EditBuffer.EditPosition.InsertText) ?
İstenilen kadar karakter okumak (Context.EditBuffer.EditPosition.Read) ?
Cursor pozisyonun saklayıp daha sonra geri dönmek
(Context.EditBuffer.EditPosition.Save / Restore) ?
Görüldüğü gibi üzerinde çalıştığımız dosyaya hemen hemen herşeyi yaptırmak mümkündür.
Delphi IDE’sine menu ekleme, menü servisi:
Daha önce yaptığımız örnek üzerinde devam edelim. Bu sefer Delphi IDE’sine kendi menümüzü ekleyelim. Bu özelliği kullanmak için IOTAWizard interface’inden yaralanırız.
ToolsAPI.pas dosyasına baktığımızda, IOTAWizard elemanları kısaca şöyledir:
IOTAWizard = interface(IOTANotifier)
['{B75C0CE0-EEA6-11D1-9504-00608CCBF153}']
{ Expert UI strings }
function GetIDString: string;
function GetName: string;
function GetState: TWizardState;
{ Launch the AddIn }
procedure Execute;
end;
Metodları kısaca açıklamak gerekirse:
function GetIDString: string: Burada unique bir isim veriyoruz, Delphi tarafından internal olarak kullanılıyor. Format olarak, genellikle adiniz.servisadi.
function GetName: string: Delphi tarafından internal olarak kullanılıyor. Türkçe karakterler kullanılmamalıdır
function GetState: TWizardState: Delphi IDE de kullanılacak menunun durumunu gösterir.
TWizardState = set of (wsEnabled, wsChecked); Olarak tanımlanmıştır.
procedure Execute: Yararacağımız menu Help içinde ise, bu procedur çağrılır, IDE menusüne kendi menümüzü ekleyecek isek bu procedure bir işe yaramaz.
Daha önce yaptığımız kod üzerinde aşağıdaki değişikliği yapalım.
Type ve uses daki değişiklikler.
uses
ToolsAPI, Menus, Classes;
type
...
...
TycMenuEkleme = class(TNotifierObject, IOTAWizard)
private
delMenu : TMenuItem; //Delphi IDE'sine eklenecek
procedure CreateMenu;
procedure MenuClick(Sender:TObject);
public
constructor Create;
destructor Destroy; override;
procedure YukluPackageGoster;
{IOTAWizard}
{ Expert UI strings }
function GetIDString: string;
function GetName: string;
function GetState: TWizardState;
{ Launch the AddIn }
procedure Execute;
end;
Wizard çalıştığında ilk olarak Create metodunu çağıracaktır.
constructor TycMenuEkleme.Create;
var
intf : INTAServices; //Delphi IDE ile ilgili servistir
begin
delMenu := nil;
if not Supports(BorlandIDEServices, INTAServices, intf) then Exit;
delMenu := TMenuItem.Create(nil);
delMenu.Caption := 'YCMenu'; //Delpi IDE’de görünecek menu
CreateMenu; //Delpi IDE’de menu yaratalım
end;
Delpih IDE’sinde 'YCMenu' adlı menünün alt menülerini hazırlayalım
procedure TycMenuEkleme.CreateMenu;
var
itm: TMenuItem;
DelphiAnaMenu : TMainMenu;
bmp : TBitmap;
il : TCustomImageList;
begin
itm := TMenuItem.Create(delMenu);
itm.Caption := 'Menu1';
itm.Tag := 0;
//Menu seçildiğinde MenuClick çağrılacaktır.
itm.OnClick := MenuClick;
delMenu.Add(itm);
itm := TMenuItem.Create(delMenu);
itm.Caption := 'Menu2';
itm.Tag := 1;
itm.OnClick := MenuClick;
delMenu.Add(itm);
//Open menu item icin icon kullanalim
itm := TMenuItem.Create(delMenu);
itm.Caption := 'Open...';
itm.Tag := 2;
itm.OnClick := MenuClick;
bmp := TBitmap.Create;
try
bmp.LoadFromResourceName(hInstance, BMP_SCREEN);
//Bitmap'i Open menusune ekleyelim icin kullanalim.
itm.ImageIndex := (BorlandIDEServices as INTAServices).
AddMasked(bmp, clBlack)
finally
bmp.Free;
end;
delMenu.Add(itm);
//Not: Diger menu itemlari icin imaj eklemek icin yukardaki yontem
//kullanilabilir. Designer'da kullanıldığı gibi TAction da kullanılabilir.
itm := TMenuItem.Create(delMenu);
itm.Caption := 'Yüklü packageleri göster...';
itm.Tag := 3;
itm.OnClick := MenuClick;
delMenu.Add(itm);
itm := TMenuItem.Create(delMenu);
itm.Caption := '-';
delMenu.Add(itm);
itm := TMenuItem.Create(delMenu);
itm.Caption := 'Hakkında...';
itm.Tag := 4;
bmp := TBitmap.Create;
try
//Delphi IDE’sinde bulunan bütün imajları kullanalım
il := (BorlandIDEServices as INTAServices).ImageList;
il.GetBitmap(100, bmp); //Hakkında... için 100 numaralı imajı kullanalım
itm.ImageIndex := (BorlandIDEServices as INTAServices).
AddMasked(bmp, clBlack);
finally
bmp.Free;
end;
itm.OnClick := MenuClick;
delMenu.Add(itm);
//Delphi menüsünü alalım
DelphiAnaMenu := (BorlandIDEServices as INTAServices).MainMenu;
//Kendi menumuzu Delphi ana menusune ekleyelim
DelphiAnaMenu.Items.Add(delMenu);
end;
Menu seçildiğinde alınan aksiyonu tanımlayalım.
procedure TycMenuEkleme.MenuClick(Sender: TObject);
var
mi : TCustomAction;
cap : string;
itomod : IOTAModuleServices;
begin
mi := Sender as TCustomAction;
cap := mi.Caption;
case mi.Tag of
0 : ShowMessage('1 numaralı menu tıklandı');
1 : ShowMessage('2 numaralı menu tıklandı');
2 : //Bir dosyayı Delphi'de açalım
begin
with TOpenDialog.Create(nil) do
try
if Execute() then
begin
//Dosyayı delphi'ye yükleyelim
if Supports(BorlandIDEServices, IOTAModuleServices,
itomod) then
begin
itomod.OpenModule(FileName).Show;
end;
end;
finally
Free;
end;
end;
3 : YukluPackageGoster();
4 : ShowMessage('Bu Delpi IDE Plug-'+
'In Yusuf ÇELIK tarafından yazılmıştır');
end;
end;
Yüklü packagelerin gösterilmesi. Burada IOTAPackageServices interface’inden yararlanılmıştır. IOTAPackageServices interface’i kısaca şöyle tanımlanmıştır.
IOTAPackageServices = interface(IUnknown)
['{26EB0E4D-F97B-11D1-AB27-00C04FB16FB3}']
...
...
property PackageCount: Integer read GetPackageCount;
property PackageNames[Index: Integer]: string
read GetPackageName;
property ComponentCount[PkgIndex: Integer]: Integer
read GetComponentCount;
property ComponentNames[PkgIndex, CompIndex: Integer]: string
read GetComponentName;
end;
PackageCount: Delphi içinde yüklü package sayısını döner.
PackageNames[Index: Integer]: Index numaralı package adını verir.
ComponentCount[PkgIndex: Integer]: PkgIndex numaralı package da kaç tane component olduğu bilgisini verir.
ComponentNames[PkgIndex, CompIndex: Integer]: PkgIndex numaralı package da CompIndex numaralı component adını verir.
Yukardaki bilgileri baz alarak, Delphi içinde yüklü package ve bu package lerde bulunan component’ları bulabiliriz. Şimdilik package adlarını bulmamız yeterli.
procedure TycMenuEkleme.YukluPackageGoster;
var
ps : IOTAPackageServices;
i : Integer;
str : string;
begin
if not Supports(BorlandIDEServices, IOTAPackageServices, ps) then
begin
ShowMessage('Desteklenmemektedir');
Exit;
end;
ps := BorlandIDEServices as IOTAPackageServices;
str := '';
for i := 0 to ps.PackageCount - 1 do
begin
str := str + ps.PackageNames[i] + #13#10;
end;
ShowMessage(str);
end;
Daha da ileri gidelim ve bu package isimlerini Delphi’nin Compile hatalarını gösterdiği Mesaj alanına yazalım. Bunun için IOTAMessageServices servisinden yaralanabiliriz.
Yukardaki YukluPackageGoster procedur’unu farklı bir biçimde yazabiliriz.
function ms: IOTAMessageServices;
begin
Result := (BorlandIDEServices as IOTAMessageServices);
if not Assigned(Result) then
raise Exception.Create('IOTAMessageServices desteklenmemektedir');
end;
procedure TycMenuEkleme.YukluPackageGoster;
var
ps : IOTAPackageServices;
i : Integer;
begin
if not Supports(BorlandIDEServices, IOTAPackageServices, ps) then
begin
ShowMessage('Desteklenmemektedir');
Exit;
end;
ps := BorlandIDEServices as IOTAPackageServices;
ms.ShowMessageView(nil); //Önce Messages ekranını açalım
ms.ClearAllMessages; //Daha önceki mesajları silelim
//Ve kendi mesajlarımızı ekleyelim
ms.AddTitleMessage('Yüklenen packaga listesi');
ms.AddTitleMessage('------------------------');
for i := 0 to ps.PackageCount - 1 do
begin
ms.AddTitleMessage(ps.PackageNames[i]);
end;
end;
Bu durumda 'Yüklenen packaga listesi' Delphi’de aşağıdaki gibi görülür.
Aynı yöntemle package’lardaki component adlarını da bulabiliriz.
Wizarda UnInstall olduğunda Destroy otomatik olarak çağrılır.
Destroy metodunda da daha önce Create metodunda yaratttığım componentları memory’den silelim.
destructor TycMenuEkleme.Destroy;
begin
if Assigned(delMenu) then
delMenu.Free;
inherited;
end;
Geri kalanları da kısaca yazalım.
procedure TycMenuEkleme.Execute;
begin
//Burası çağrılmaz, ancak Help altına install edersek çağrılır.
//Ancak bizim yazdığımız Delphi’ye ek bir menü
ShowMessage('Execute');
end;
function TycMenuEkleme.GetIDString: string;
begin
//Unique bir isim
Result := 'Yusuf.CELIK.MenuEkleme'
end;
//Delphi tarafından kullanılır
function TycMenuEkleme.GetName: string;
begin
Result := 'Yusuf CELIK menu';
end;
//Menu durumunu gösterir, Enabled ya da Checked
function TycMenuEkleme.GetState: TWizardState;
begin
Result := [wsEnabled];
end;
Şimdi bunu Delphi IDE’sine kayıt etmemiz gerekir. Bu da Register procedurunda yapılır.
procedure Register;
var
KeyboardServices: IOTAKeyboardServices;
begin
TusTakimiIndex := -1;
InstallSplash;
if Supports(BorlandIDEServices, IOTAKeyboardServices,
KeyboardServices) then
TusTakimiIndex := KeyboardServices.AddKeyboardBinding
(TycKeyboardBinding.Create);
RegisterPackageWizard(TycMenuEkleme.Create);
end;
Yukarda anlatılanlar yalnızca Delphi OTA (OTAPI ya da Plug-In de denir) denizinde minik bir su birikintisidir.
Delphi OTA hakkında daha fazla bilgi için aşağıdaki sitelerden yararlanabilirsiniz.
http://www.gexperts.org/opentools/
http://www.tempest-sw.com/opentools/
http://www.mustangpeak.net/opentoolsape.htm
Sorularınız için bana yusufcelik@gmail.com adresinden ulaşabilirsiniz.
Not: Yukardaki örnekler Borland Delphi 2005 ve 2006 da test edilmiştir.




