delphi7 ide擴展,類似vc6,通過編譯指令控制多項目工程編譯輸出

參考《Delphi Open Tools Api實例研究(一)》http://www.xuebuyuan.com/zh-tw/1275460.html,在此特別表示感謝!!!


//本單元文件,根據compile.inc編譯指令文件中的不同編譯指令,同時讀取工程配置config.ini文件,一次編譯輸出多個項目工程結果。

compile.inc

{$UNDEF NoFinger}
{$DEFINE Ok}
{$DEFINE release}
{$DEFINE NoFinger}
{$DEFINE Hello}
{$DEFINE debug}


config.ini

[General]
//工程輸出目標程序文件配置列表,後面的每個小節必須以此列表命名,子項key爲固定值,如需添加,要修改程序
sections=nofinger,finger
//單獨編譯某段,如果全編譯使用 all
activesection=nofinger
[nofinger]
//編譯指令集,將輸出到工程目錄下的compile.inc文件中,作爲工程編譯時條件指令集
compilationDirective={$DEFINE NoFinger},{$DEFINE Hello},{$DEFINE debug}
//目標程序文件目錄
outDir=..\bin_NoFinger
//目標程序文件名稱
ExeName=FGDC_NoFinger.exe
//目標程序文件屬性中的文件描述信息
FileDescription=無指紋版本
FileVersion=1.0.0.6
[finger]
compilationDirective={$UNDEF NoFinger},{$DEFINE Ok},{$DEFINE release}
outDir=..\bin_Finger
ExeName=FGDC_Finger.exe
FileDescription=有指紋版本
FileVersion=1.0.0.6


//單元文件

unit u_main;


interface

uses
  SysUtils, Classes, Menus, ToolsApi, Controls, ImgList, Graphics, Forms,
  ComCtrls, windows, TypInfo, variants, auto_object, IdStrings, dialogs, u_inifile_C;
type
  TNTATest = class
  private
    FMainMenu: TMainMenu; //用來存貯delphi IDE的主菜單
    NewMenu: TMenuItem; //我們將要插入的菜單
    FImageList: TCustomImageList; //用來存貯delphi IDE主菜單和工具欄的ImageList
    ImageIndex1: integer; //檢測量,請參看後面的代碼
    IDEHandle: HWND;
    procedure BuildAllProjects(sender: TObject);


    procedure BuildPrj(sOutDir, sExeName, sFileDesc, sFileVersion: string);
    procedure BuildPrjBefore(sSection, sprj_path: string;
      var sLst_compilefile: TStringList);
    procedure BuildProject(sender: TObject);
    procedure DynamicAddMenu(sender: TObject);
    function GetProjectResource(Project: IOTAProject): IOTAProjectResource;
    procedure IncrementVersion(sender: TObject);
  protected
    procedure AddMenu; //加入我們的菜單
    procedure ReMoveMenu; //卸載我們的菜單
    procedure ReCodeEditer(sender: TObject); //菜單項一的事件
    procedure AboutForm(sender: TObject); //菜單項二的事件


    procedure drawFormcustom(Sender: TObject; ACanvas: TCanvas;
      ARect: TRect; Selected: Boolean);
  public
    constructor Create;
    destructor Destroy; override;
  private
    index: integer;
  end;


  TProjectNotifer = class(TNotifierObject, IOTAIDENotifier)
  public
    procedure AfterCompile(Succeeded: Boolean);
    procedure BeforeCompile(const Project: IOTAProject;
      var Cancel: Boolean);
    procedure FileNotification(NotifyCode: TOTAFileNotification;
      const FileName: string; var Cancel: Boolean);
  end;


procedure Register;


var
  MyNTATest: TNTATest;


implementation


uses VersionInfo;


const
  FIXED_MENU_COUNT = 4;


function printLogToFile(sfmt: string; ss: array of const; apppath: string): string;
  procedure writeLnToFile(s: ansistring);
  var
    tf: TextFile;
    strFileName: ansistring;
  begin
    if not DirectoryExists(apppath + 'log\') then CreateDir(apppath + 'log\');
    strFileName := Format('%s%s.log', [apppath + 'log\', FormatDateTime('yyyymmdd', now)]);
    AssignFile(tf, strFileName);
    if FileExists(strFileName) then
    begin
      Append(tf);
    end
    else
    begin
      Rewrite(tf);
    end;
    writeln(tf, s);
    Flush(tf);
    CloseFile(tf);
  end;
var
  sStr, sStr1, sStr2: ansistring;
begin
  sStr := Format('%s', [FormatDateTime('hh:nn:ss', now)]);
  sStr1 := Format(sfmt, ss);
  sStr2 := Format('%s %s', [sStr, sstr1]);
  writeLnToFile(sStr2);
  result := sStr1;
end;


procedure Register;
begin
  MyNTATest.AddMenu;
  //和傳統組件的同名方法不同,這裡沒有在組件面板上安裝圖標
  //而是直接調用AddMenu方法添加我們的菜單
end;
{ TNTATest }


constructor TNTATest.Create;
begin
  IDEHandle := (BorlandIDEServices as IOTAServices).GetParentHandle;
 //我們用IOTAServices介面的GetParentHandle方法取得了ide的handle
  Index := (BorlandIDEServices as IOTAServices).AddNotifier(TProjectNotifer.create);
end;


procedure TNTATest.AddMenu;
//var
  //MenuItem: array[0..2] of TMenuItem;
  //i: integer;
  //Icon1: TIcon; //菜單項一的圖標
begin
  FMainMenu := (BorlandIDEServices as INTAServices).MainMenu;
  //我們用 INTAServices的MainMenu屬性直接得到了IDE的主菜單
  FImageList := (BorlandIDEServices as INTAServices).ImageList;
  //我們用 INTAServices的ImageList屬性直接得到了IDE的圖象列表
  NewMenu := TMenuItem.Create(FMainMenu);
  //創建我們的菜單
  NewMenu.Caption := 'wata';
  ImageIndex1 := -1; //沒有載入圖標
  //下面的代碼使用for和case來添加兩個菜單項有點小題大作,但
  //我們展示了一種更通用的方法使你能夠添加更多的菜單項,而不必簡單的複製代碼。


  NewMenu.OnClick := DynamicAddMenu; //從本地配置中讀取要編譯的工程列表動態加載菜單
 // NewMenu.OnDrawItem := self.drawFormcustom;


  FMainMenu.Items.Add(NewMenu); //最後添加我們的菜單到IDE主菜單
end;


procedure TNTATest.DynamicAddMenu(sender: TObject);
var
  MenuItem: array of TMenuItem;
  i: integer;
  //Icon1: TIcon; //菜單項一的圖標


  sLst_section: TStringlist;
  sprj_path, sSections: string;
  icount, iindx: integer;
  sFileVersion: string;
  prj: IOTAProject;
begin
  prj := GetActiveProject;
  if prj = nil then exit;
  sprj_path := extractfilepath(prj.FileName);
  //showmessage(sprj_path);


  //工程使用編譯指令文件,固定名稱爲compile.inc,固定路徑爲工程當前路徑
 { if not fileExists(sprj_path + 'compile.inc') then
  begin
    Messagebox(IDEHandle, pchar(sprj_path + 'compile.inc文件不存在!'), '提示', mb_iconinformation);
    exit;
  end;
  }




  //工程使用目標程序文件輸出配置文件,固定名稱爲config.ini,固定路徑爲工程當前路徑
  TAuto_object.New(iniRw, TIniRW_Env.create(sprj_path + 'config.ini'));
  sSections := iniRw.readFromIni('General', 'sections', 'bin_1,bin_2');


  TAuto_object.New(sLst_section, TStringList.Create);
  sLst_section.Delimiter := ',';
  sLst_section.DelimitedText := sSections;
  icount := sLst_section.Count + FIXED_MENU_COUNT;


//  SplitColumns(sDefines, sLst_defines, ',');


  FMainMenu := (BorlandIDEServices as INTAServices).MainMenu;
  //我們用 INTAServices的MainMenu屬性直接得到了IDE的主菜單
  FImageList := (BorlandIDEServices as INTAServices).ImageList;
  //我們用 INTAServices的ImageList屬性直接得到了IDE的圖象列表
  for i := 0 to FMainMenu.Items.Count - 1 do
  begin
    //printlogtofile('%d =>%s', [i, FMainMenu.Items[i].Caption], sprj_path);
    if FMainMenu.Items[i].Caption = 'wata' then
    begin
      FMainMenu.Items.Delete(i);
      break;
    end;
  end;
  NewMenu := TMenuItem.Create(FMainMenu);
  //創建我們的菜單
  NewMenu.Caption := 'wata';
  NewMenu.Tag := 20;


  setlength(MenuItem, icount);
  for i := 0 to icount - 1 do
  begin
    MenuItem[i] := TMenuItem.Create(NewMenu); //創建子菜單項
    case i of
      0:
        begin
          MenuItem[i].Caption := 'About';
          MenuItem[i].OnClick := AboutForm;
        end;
      1: MenuItem[i].Caption := '-'; //當然還有一個分割符號,其實是3個菜單項
      2:
        begin
          MenuItem[i].Caption := 'Increment Version';
          MenuItem[i].OnClick := IncrementVersion; //添加事件處理程序
        end;
      3:
        begin
          MenuItem[i].Caption := 'Build All Projects';
          {
          Icon1 := TIcon.Create;
          try
            Icon1.LoadFromFile('MAI2.ICO');
       //我從硬碟的文件上載入了一個圖標作為菜單項一的圖標
          except
            on E: Exception do
            begin
              raise Exception.Create(E.Message);
              exit;
            end;
          end;
          ImageIndex1 := FImageList.AddIcon(Icon1);


      //加入那個載入的圖標並返回一個ImageIndex
          MenuItem[i].ImageIndex := ImageIndex1;
          }
          MenuItem[i].OnClick := BuildAllProjects; //添加事件處理程序
        end;
    else begin
        iindx := i - FIXED_MENU_COUNT;
        MenuItem[i].Tag := iindx;
        sFileVersion := iniRw.readFromIni(sLst_section[iindx], 'FileVersion', '1.0.0.0');
        MenuItem[i].Caption := 'Build => ' + sLst_section[iindx] + ' v' + sFileVersion;
        MenuItem[i].OnClick := BuildProject;
      end;
    end;


    NewMenu.Add(MenuItem[i]); //添加菜單項
  end;
  FMainMenu.Items.Add(NewMenu); //最後添加我們的菜單到IDE主菜單
end;


procedure TNTATest.IncrementVersion(sender: TObject);
var
  i: integer;
  sLst_section, sLst_version: TStringlist;
  sprj_path, sSections: string;
  iindx: integer;
  sFileVersion: string;
  iVer: Integer;
  prj: IOTAProject;
begin
  prj := GetActiveProject;
  if prj = nil then exit;
  sprj_path := extractfilepath(prj.FileName);
 // showmessage(sprj_path);


  //工程使用目標程序文件輸出配置文件,固定名稱爲config.ini,固定路徑爲工程當前路徑
  TAuto_object.New(iniRw, TIniRW_Env.create(sprj_path + 'config.ini'));
  sSections := iniRw.readFromIni('General', 'sections', 'bin_1,bin_2');


  TAuto_object.New(sLst_version, TStringList.Create);
  sLst_version.Delimiter := '.';


  TAuto_object.New(sLst_section, TStringList.Create);
  sLst_section.Delimiter := ',';
  sLst_section.DelimitedText := sSections;
  //icount := sLst_section.Count + FIXED_MENU_COUNT;


//  SplitColumns(sDefines, sLst_defines, ',');


  FMainMenu := (BorlandIDEServices as INTAServices).MainMenu;
  //我們用 INTAServices的MainMenu屬性直接得到了IDE的主菜單


  for i := 0 to FMainMenu.Items.Count - 1 do
  begin
    //printlogtofile('%d =>%s', [i, FMainMenu.Items[i].Caption], sprj_path);
    if FMainMenu.Items[i].Caption = 'wata' then
    begin
      NewMenu := FMainMenu.Items[i];
      break;
    end;
  end;


  for i := 0 to NewMenu.Count - 1 do
  begin
   // showmessage(format('%d =>%s', [i, NewMenu.Items[i].Caption]));
    case i of
      0, 1, 2, 3:
        begin
        end;
    else begin
        iindx := i - FIXED_MENU_COUNT;
        sFileVersion := iniRw.readFromIni(sLst_section[iindx], 'FileVersion', '1.0.0.0');
        sLst_version.DelimitedText := sFileVersion;
        iVer := strtoint(sLst_version[3]);
        inc(iVer);
        sFileVersion := format('%s.%s.%s.%d', [sLst_version[0], sLst_version[1], sLst_version[2], iVer]);
        iniRw.writeToIni(sLst_section[iindx], 'FileVersion', sFileVersion);
        NewMenu[i].Caption := 'Build => ' + sLst_section[iindx] + ' v' + sFileVersion;
      end;
    end;
  end;
end;


procedure TNTATest.AboutForm(sender: TObject);
//一個簡單的關於對話框,注意參數中的IDEHandle
begin
//  showmessage(inttostr(TMenuItem(sender).tag));
  messagebox(IDEHandle, '此菜單實現了根據配置文件按照編譯指令輸出不同目錄、執行文件、版本號等功能!', 'by wata', MB_ICONINFORMATION);


  DynamicAddMenu(nil);
end;


procedure TNTATest.BuildPrj(sOutDir, sExeName, sFileDesc, sFileVersion: string);
  function getSubstr(var sSTr: string): string;
  var
    iPos: integer;
  begin
    ipos := pos('.', sStr);
    if ipos = 0 then
    begin
      result := sStr;
    end else begin
      result := copy(sStr, 1, ipos - 1);
      sSTr := copy(sStr, ipos + 1, length(sStr) - ipos);
    end;
  end;
var
  prjbuild: IOTAProjectBuilder;


  sprj_path, sprj_name, sprj_name_t: string;
  oarr: TOTAOptionNameArray;
  i: integer;
  v: variant;
  bOk: boolean;


  ProjectResource: IOTAProjectResource;
  ResourceEntry: IOTAResourceEntry;
  vi: TVersionInfo;
  Stream: TMemoryStream;
  srcFileName, destFileName: string;
  ver1, ver2, ver3, ver4: string;
  prj: IOTAProject;
begin
  prj := GetActiveProject;
  if prj = nil then exit;
  sprj_path := extractfilepath(prj.FileName);
  sprj_name_t := extractfileName(prj.FileName);
  sprj_name := copy(sprj_name_t, 1, length(sprj_name_t) - 4);
  //showmessage(sprj_path);


  oarr := prj.ProjectOptions.GetOptionNames;


  {
  for i := 0 to high(oarr) do
  begin
    printlogtofile('%d =>%s,type =>%s,value =>%s',
      [i, oarr[i].Name, TypInfo.GetEnumName(TypeInfo(TTypeKind),
        Ord(oarr[i].Kind)), prj.ProjectOptions.Values[oarr[i].Name]], sprj_path);
  end;
  }


  v := prj.ProjectOptions.Values['OutputDir'];
  bOk := true;
  if VarIsNull(v) then
  begin
    printlogtofile('OutputDir is null', [], sprj_path);
    bOk := false;
  end;
  if VarIsEmpty(v) then
  begin
    printlogtofile('OutputDir is empty', [], sprj_path);
    bOk := false;
  end;
  if bOK then
    printlogtofile('OutputDir =>%s', [vartostr(v)], sprj_path);


  //設置文件輸出路徑
  prj.ProjectOptions.Values['OutputDir'] := soutDir;
  ForceDirectories(sprj_path + soutDir);


//  設置文件版本號
  ver1 := getSubstr(sFileVersion);
  ver2 := getSubstr(sFileVersion);
  ver3 := getSubstr(sFileVersion);
  ver4 := getSubstr(sFileVersion);


 // showmessage(ver1 + ',' + ver2 + ',' + ver3 + ',' + ver4);


  prj.ProjectOptions.Values['MajorVersion'] := strtointdef(ver1, 0);
  prj.ProjectOptions.Values['MinorVersion'] := strtointdef(ver2, 0);
  prj.ProjectOptions.Values['Release'] := strtointdef(ver3, 0);
  prj.ProjectOptions.Values['Build'] := strtointdef(ver4, 0);


  ProjectResource := GetProjectResource(prj);
  //showmessage(ProjectResource.FileName);


  ResourceEntry := ProjectResource.FindEntry(RT_VERSION, PChar(1));
  if Assigned(ResourceEntry) then
  begin
    TAuto_object.New(VI, TVersionInfo.Create(PChar(ResourceEntry.GetData)));
    for i := 0 to VI.KeyCount - 1 do
    begin
      printlogtofile('%d =>%s,svalue =>%s',
        [i, VI.KeyName[i], VI.KeyValue[VI.KeyName[i]]], sprj_path);
    end;
    //VI.KeyValue['Comments'] := 'hall';
    //設置文件描述
    VI.KeyValue['FileDescription'] := sFileDesc;
    //VI.KeyValue['ProductVersion'] := sFileVersion;
    //此處設置文件版本號不起作用,必須在options中設置
    //VI.KeyValue['FileVersion'] := sFileVersion;
   // showmessage(sFileVersion);
    try


      TAuto_object.New(Stream, TMemoryStream.Create);
      try
        VI.SaveToStream(Stream);
        ResourceEntry.DataSize := Stream.Size;
        Move(Stream.Memory^, ResourceEntry.GetData^, Stream.Size);
      finally
      end;


    finally
    end;
  end;


  prjbuild := prj.GetProjectBuilder();
  if prjbuild.BuildProject(cmOTABuild, true) then
  begin
    srcfilename := sprj_path + soutDir + '\' + sprj_name + '.exe';
    destFileName := sprj_path + soutDir + '\' + sExeName;
    if not sametext(srcfilename, destFileName) then
    begin
      copyfile(pchar(srcfilename), pchar(destFileName), false);
      deletefile(pchar(srcfilename));
    end;
  end;
end;


function TNTATest.GetProjectResource(Project: IOTAProject): IOTAProjectResource;
var
  i: Integer;
  Editor: IOTAEditor;
begin
  Result := nil;
  for i := 0 to (Project.GetModuleFileCount - 1) do
  begin
    Editor := Project.GetModuleFileEditor(i);
    if Supports(Editor, IOTAProjectResource, Result) then
      Break;
  end;
end;


procedure TNTATest.BuildPrjBefore(sSection, sprj_path: string; var sLst_compilefile: TStringList);
var
  sOutDir, sExeName, scompilationDirective, sFileDesc, sFileVersion: string;
  sLst_compiledirective, sLst_compilefile_t: TStringList;
  i, k: integer;
begin


  TAuto_object.New(sLst_compilefile_t, TStringList.Create);
  TAuto_object.New(sLst_compiledirective, TStringList.Create);
  sLst_compiledirective.Delimiter := ',';


  //本程序支持多編譯指令輸出目標程序文件
  //編譯指令集中包含空格,使用DelimitedText解析結果不正確,所以採用如下函數解析
  SplitColumns(iniRw.readFromIni(sSection, 'compilationDirective', '{$nodefine}'),
    sLst_compiledirective, ',');


  sOutDir := iniRw.readFromIni(sSection, 'outDir', '..\noDir');
  sExeName := iniRw.readFromIni(sSection, 'ExeName', 'noExeName.exe');
  sFileDesc := iniRw.readFromIni(sSection, 'FileDescription', 'noFileDesc');
  sFileVersion := iniRw.readFromIni(sSection, 'FileVersion', '1.0.0.0');
  for k := 0 to sLst_compiledirective.Count - 1 do
  begin
    scompilationDirective := sLst_compiledirective[k];
    for i := 0 to sLst_compilefile.Count - 1 do
    begin
      if pos(uppercase(scompilationDirective), uppercase(sLst_compilefile[i])) > 0 then
      begin
          //如果有重複的,會出現out of index錯誤,所以使用另一個lst作爲過渡
          //sLst_compilefile.Delete(i);
          //如果有重複的,全刪除
          //break;
        continue;
      end;
      sLst_compilefile_t.Add(sLst_compilefile[i]);
    end;
    sLst_compilefile_t.Add(scompilationDirective);
    sLst_compilefile.Assign(sLst_compilefile_t);


      //修改編譯指令文件
    sLst_compilefile_t.SaveToFile(sprj_path + 'compile.inc');
    sLst_compilefile_t.Clear;
  end;


  BuildPrj(sOutDir, sExeName, sFileDesc, sFileVersion);
end;


procedure TNTATest.BuildAllProjects(sender: TObject);
var
  sLst_section, sLst_compilefile: TStringlist;
  sprj_path: string;
  j: integer;


  sSections, sActiveSection: string;
  prj: IOTAProject;
begin
  prj := GetActiveProject;
  if prj = nil then exit;
  sprj_path := extractfilepath(prj.FileName);


  //工程使用編譯指令文件,固定名稱爲compile.inc,固定路徑爲工程當前路徑
  if not fileExists(sprj_path + 'compile.inc') then
  begin
    Messagebox(IDEHandle, pchar(sprj_path + 'compile.inc文件不存在!'), '提示', mb_iconinformation);
    exit;
  end;


  //工程使用目標程序文件輸出配置文件,固定名稱爲config.ini,固定路徑爲工程當前路徑
  TAuto_object.New(iniRw, TIniRW_Env.create(sprj_path + 'config.ini'));
  sSections := iniRw.readFromIni('General', 'sections', 'bin_1,bin_2');
  sActiveSection := iniRw.readFromIni('General', 'activesection', 'all');


  TAuto_object.New(sLst_section, TStringList.Create);
  sLst_section.Delimiter := ',';
  sLst_section.DelimitedText := sSections;


//  SplitColumns(sDefines, sLst_defines, ',');


  TAuto_object.New(sLst_compilefile, TStringList.Create);
  sLst_compilefile.LoadFromFile(sprj_path + 'compile.inc');
{
  if sActiveSection = 'all' then
  begin
}
  for j := 0 to sLst_section.Count - 1 do
  begin
    printlogtofile('%d =>%s', [j, sLst_section[j]], sprj_path);
    BuildPrjBefore(sLst_section[j], sprj_path, sLst_compilefile);
  end;
{
  end else begin
    printlogtofile('=>%s', [sActiveSection], sprj_path);
    BuildPrjBefore(sActiveSection, sprj_path, sLst_compilefile);
  end;
  }
end;


procedure TNTATest.BuildProject(sender: TObject);
var
  sLst_section, sLst_compilefile: TStringlist;
  sprj_path: string;
  j: integer;


  sSections, sActiveSection: string;
  prj: IOTAProject;
begin
  prj := GetActiveProject;
  if prj = nil then exit;
  sprj_path := extractfilepath(prj.FileName);


  //工程使用編譯指令文件,固定名稱爲compile.inc,固定路徑爲工程當前路徑
  if not fileExists(sprj_path + 'compile.inc') then
  begin
    Messagebox(IDEHandle, pchar(sprj_path + 'compile.inc文件不存在!'), '提示', mb_iconinformation);
    exit;
  end;


  //工程使用目標程序文件輸出配置文件,固定名稱爲config.ini,固定路徑爲工程當前路徑
  TAuto_object.New(iniRw, TIniRW_Env.create(sprj_path + 'config.ini'));
  sSections := iniRw.readFromIni('General', 'sections', 'bin_1,bin_2');
  sActiveSection := iniRw.readFromIni('General', 'activesection', 'all');


  TAuto_object.New(sLst_section, TStringList.Create);
  sLst_section.Delimiter := ',';
  sLst_section.DelimitedText := sSections;


//  SplitColumns(sDefines, sLst_defines, ',');


  TAuto_object.New(sLst_compilefile, TStringList.Create);
  sLst_compilefile.LoadFromFile(sprj_path + 'compile.inc');


  j := TMenuItem(Sender).Tag;
  printlogtofile('BuildProject %d =>%s', [j, sLst_section[j]], sprj_path);
  BuildPrjBefore(sLst_section[j], sprj_path, sLst_compilefile);


end;


procedure TNTATest.ReMoveMenu;
//卸載菜單
begin
  if assigned(NewMenu) then NewMenu.Free;
end;


destructor TNTATest.Destroy;
begin
  MyNTATest.ReMoveMenu;
  if ImageIndex1 <> -1 then
 //如果在前面載入圖標的工作出現異常就不釋放圖標,否則會釋放到delphi本身使用的圖標
    MyNTATest.FImageList.Delete(MyNTATest.ImageIndex1);
  (BorlandIDEServices as IOTAServices).RemoveNotifier(Index);
  inherited;
end;


procedure TNTATest.ReCodeEditer(sender: TObject);
begin


end;


procedure TNTATest.drawFormcustom(Sender: TObject; ACanvas: TCanvas;
  ARect: TRect; Selected: Boolean);
begin
//  self.DynamicAddMenu(nil);
end;


{ TProjectNotifer }


procedure TProjectNotifer.AfterCompile(Succeeded: Boolean);
begin


end;


procedure TProjectNotifer.BeforeCompile(const Project: IOTAProject;
  var Cancel: Boolean);
begin


end;


procedure TProjectNotifer.FileNotification(
  NotifyCode: TOTAFileNotification; const FileName: string;
  var Cancel: Boolean);
begin
  //新工程打開時更新wata菜單
  if ofnActiveProjectChanged = NotifyCode then MyNTATest.DynamicAddMenu(nil);
end;


initialization
//在組件第一次被安裝時創建了TNTATest
  MyNTATest := TNTATest.Create;
finalization
//在組件被卸載時釋放了MyNTATest
  MyNTATest.Free;


end.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章