UNIT Unit1; INTERFACE USES Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, StrUtils, Menus, Registry, Math, Buttons, Unit2, Unit3, Unit4, Unit5, Unit6, Unit7, Unit8, Unit9, Unit10, Unit11, Unit12, Unit13, Unit14, Unit15; TYPE TForm1 = Class(TForm) connect_timer: TTimer; InitStuff: TTimer; not_running: TLabel; get_values: TTimer; Menu: TMainMenu; Menu_Main: TMenuItem; Menu_AOT: TMenuItem; Menu_Exit: TMenuItem; Menu_Options: TMenuItem; Menu_SetHotKeys: TMenuItem; Menu_FreezeTime: TMenuItem; Menu_Windows: TMenuItem; Menu_Chars: TMenuItem; Menu_Items: TMenuItem; Menu_About: TMenuItem; Menu_RefreshTime: TMenuItem; Patches1: TMenuItem; Menu_Patch_Scriptvars: TMenuItem; Menu_Patch_Movements: TMenuItem; Menu_Patch_Messages: TMenuItem; menu_Anims: TMenuItem; menu_Models: TMenuItem; menu_Spawn: TMenuItem; procedure menu_SpawnClick(Sender: TObject); procedure menu_ModelsClick(Sender: TObject); procedure menu_AnimsClick(Sender: TObject); PROCEDURE Menu_Patch_MovementsClick(Sender: TObject); PROCEDURE Menu_Patch_MessagesClick(Sender: TObject); PROCEDURE Menu_Patch_ScriptvarsClick(Sender: TObject); PROCEDURE Menu_SetHotKeysClick(Sender: TObject); PROCEDURE FormCreate(Sender: TObject); PROCEDURE Menu_AboutClick(Sender: TObject); PROCEDURE Menu_FreezeTimeClick(Sender: TObject); PROCEDURE Menu_RefreshTimeClick(Sender: TObject); PROCEDURE get_valuesTimer(Sender: TObject); PROCEDURE InitStuffTimer(Sender: TObject); PROCEDURE Menu_CharsClick(Sender: TObject); PROCEDURE Menu_ExitClick(Sender: TObject); PROCEDURE Menu_AOTClick(Sender: TObject); PROCEDURE connect_timerTimer(Sender: TObject); PROCEDURE Form1Close(Sender: TObject; var Action: TCloseAction); PROCEDURE Menu_AnyCharClick(Sender: TObject); PROCEDURE Menu_CharOverview(Sender: TObject); PROCEDURE Debug_Click(Sender: TObject); PROCEDURE OpenCloseClick(Sender: TObject); PRIVATE PROCEDURE WMHotKey(VAR Msg : TWMHotKey); MESSAGE WM_HOTKEY; PUBLIC END; VAR Form1: TForm1; CharForms: Array[0..ais_controlled] OF TCharForm; CharMenus: Array[0..ais_controlled] OF TMenuItem; CharOverviewMenu: TMenuItem; IMPLEMENTATION {$R *.dfm} PROCEDURE TForm1.Menu_AOTClick(Sender: TObject); VAR i:Byte; BEGIN IF Form1.Menu_AOT.Checked THEN BEGIN SetWindowAOT(Form1.Handle,False); FOR i:=0 TO ais_controlled DO SetWindowAOT(CharForms[i].Handle,False); SetWindowAOT(Form5.Handle,False); SetWindowAOT(Form6.Handle,False); SetWindowAOT(Form7.Handle,False); SetWindowAOT(Form9.Handle,False); SetWindowAOT(Form10.Handle,False); Form1.Menu_AOT.Checked:=False; END ELSE BEGIN SetWindowAOT(Form1.Handle,True); FOR i:=0 TO ais_controlled DO SetWindowAOT(CharForms[i].Handle,True); SetWindowAOT(Form5.Handle,True); SetWindowAOT(Form6.Handle,True); SetWindowAOT(Form7.Handle,True); SetWindowAOT(Form9.Handle,True); SetWindowAOT(Form10.Handle,True); Form1.Menu_AOT.Checked:=True; END; END; PROCEDURE TForm1.Menu_ExitClick(Sender: TObject); BEGIN Close; END; PROCEDURE TForm1.Form1Close(Sender: TObject; var Action: TCloseAction); BEGIN UnregisterHotkey(Form1.Handle,1234); Form9.UnregisterHotkeys; CloseHandle(_ProcessHandle); AssignFile(HotKeysFile,_path+'\hotkeys.cfg'); Reset(HotKeysFile); Write(HotKeysFile,HotKeys); CloseFile(HotKeysFile); END; PROCEDURE TForm1.connect_timerTimer(Sender: TObject); VAR temp:byte_array; i:byte; _height:Word; BEGIN IF _Connected=False THEN BEGIN IF ConnectToProcess=True THEN BEGIN _Connected:=True; Menu_Windows.Enabled:=True; not_running.Visible:=False; IF menu_Anims.Checked THEN Form4.Visible:=False; FOR i:=0 TO ais_controlled DO BEGIN IF CharMenus[i].Checked THEN CharForms[i].Visible:=True; END; // IF Menu_Messages.Checked THEN Form4.Visible:=True; _height:=0; FOR i:=1 TO number_main_groups DO BEGIN _height:=_height+MainGroups[i].Count*16+20; MainGroups[i].Item.Visible:=True; END; Form1.Height:=_height+44; Form9.DrawTable; END; END ELSE BEGIN temp:=ReadMem($10F50, 4); IF temp[250]=123 THEN BEGIN _Connected:=False; Form1.Caption:='OniTrainer v'+version; lvlnumber:=0; Menu_Windows.Enabled:=False; not_running.Visible:=True; FOR i:=0 TO ais_controlled DO BEGIN CharForms[i].Visible:=False; END; FOR i:=1 TO number_main_groups DO BEGIN MainGroups[i].Item.Visible:=False; END; Form4.Visible:=False; Form7.Visible:=False; // Form4.Visible:=False; Form1.Height:=73; Form9.UnregisterHotkeys; END; END; END; PROCEDURE TForm1.Menu_AnyCharClick(Sender: TObject); VAR charnumber:Byte; BEGIN charnumber:=StrToInt(MidStr(TMenuItem(Sender).Name, 5, 10)); IF CharMenus[charnumber].Checked=False THEN BEGIN CharMenus[charnumber].Checked:=True; CharForms[charnumber].Visible:=True; END ELSE BEGIN CharMenus[charnumber].Checked:=False; CharForms[charnumber].Visible:=False; END; END; PROCEDURE TForm1.Menu_CharOverview(Sender: TObject); BEGIN IF CharOverviewMenu.Checked THEN BEGIN CharOverviewMenu.Checked:=False; Form7.Visible:=False; END ELSE BEGIN CharOverviewMenu.Checked:=True; Form7.Visible:=True; END; END; PROCEDURE TForm1.Menu_CharsClick(Sender: TObject); VAR i,j:Byte; _top:Word; tempitem:TMenuItem; BEGIN IF _charformsinitialized=False THEN BEGIN _charformsinitialized:=True; FOR i:=0 TO High(CharMenus) DO BEGIN CharMenus[i]:=TMenuItem.Create(Self); CharMenus[i].Name:='Char'+IntToStr(i); IF i=0 THEN CharMenus[i].Caption:='&Player' ELSE BEGIN IF i<10 THEN CharMenus[i].Caption:='AI&'+IntToStr(i); IF i=10 THEN CharMenus[i].Caption:='AI1&0'; IF i>10 THEN CharMenus[i].Caption:='AI'+IntToStr(i); END; IF i=0 THEN BEGIN Menu.Items.Find('Windows').Find('Characters').Add(CharMenus[i]); tempitem:=TMenuItem.Create(Self); tempitem.Caption:='-'; tempitem.Name:='spacer'; Menu.Items.Find('Windows').Find('Characters').Add(tempitem); CharOverviewMenu:=TMenuItem.Create(Self); CharOverviewMenu.Name:='CharOverviewMenu'; CharOverviewMenu.Caption:='&CharOverview'; CharOverviewMenu.OnClick:=Menu_CharOverview; CharOverviewMenu.ShortCut:=ShortCut(Word('O'),[ssCtrl]); Menu.Items.Find('Windows').Find('Characters').Add(CharOverviewMenu); END ELSE BEGIN IF ((i-1) MOD 10)=0 THEN BEGIN CharMenus[i].Break:=mbBarBreak; END; Menu.Items.Find('Windows').Find('Characters').Add(CharMenus[i]); END; CharMenus[i].OnClick:=Menu_AnyCharClick; END; FOR i:=0 TO ais_controlled DO BEGIN Application.CreateForm(TCharForm,CharForms[i]); CharForms[i].Name:='Char'+IntToStr(i); IF i=0 THEN CharForms[i].Caption:='Player (Char'+IntToStr(i)+')' ELSE CharForms[i].Caption:='AI'+IntToStr(i)+' (Char'+IntToStr(i)+')'; FOR j:=1 TO number_char_groups DO BEGIN WITH CharGroups[i][j] DO BEGIN name:=CharGroupsStuff[j].name; Count:=0; Item:=TGroupbox.Create(CharForms[i]); Item.Caption:=name; Item.Name:='Group'+IntToStr(j); Item.Width:=CharForms[i].Width-6; CharForms[i].InsertControl(Item); OpenClose:=TSpeedButton.Create(Item); OpenClose.AllowAllUp:=True; OpenClose.GroupIndex:=j; OpenClose.Flat:=True; OpenClose.Glyph.LoadFromResourceName(HInstance,'ARROWS'); OpenClose.Layout:=blGlyphTop; OpenClose.Margin:=0; OpenClose.NumGlyphs:=4; OpenClose.Transparent:=False; OpenClose.Name:='OpenClose'+IntToStr(j); OpenClose.Top:=0; OpenClose.Left:=Item.Width-20; OpenClose.Height:=13; OpenClose.Width:=17; OpenClose.OnClick:=CharForms[i].OpenCloseClick; Item.InsertControl(OpenClose); END; END; WITH CharData[i] DO BEGIN FOR j:=1 TO number_items DO BEGIN WITH Items[j] DO BEGIN struct:=CharDataStuff[j].struct; offset:=CharDataStuff[j].offset; data_type:=CharDataStuff[j].data_type; range:=CharDataStuff[j].range; group:=CharDataStuff[j].group; Inc(CharGroups[i][group].Count); name:=CharDataStuff[j].name; hint:=CharDataStuff[j].hint; Item_Freeze:=TCheckBox.Create(CharGroups[i][group].Item); Item_Freeze.Caption:=name; Item_Freeze.Hint:=hint; Item_Freeze.ShowHint:=True; Item_Freeze.Name:='Char'+IntToStr(j); Item_Freeze.Height:=19; Item_Freeze.Top:=CharGroups[i][group].Count*19-4; Item_Freeze.Left:=4; Item_Freeze.Width:=220; CharGroups[i][group].Item.InsertControl(Item_Freeze); Item_Edit:=TEdit.Create(CharGroups[i][group].Item); Item_Edit.AutoSize:=False; Item_Edit.Hint:=hint; Item_Edit.ShowHint:=True; Item_Edit.Name:='Edit'+IntToStr(j); Item_Edit.Top:=CharGroups[i][group].Count*19-5; Item_Edit.Left:=230; Item_Edit.Height:=18; Item_Edit.Width:=CharGroups[i][group].Item.Width-Item_Edit.Left-4; Item_Edit.OnChange:=CharForms[i].EditClick; //Item_Edit.Text:=IntToStr(Decode_Int(ReadMem(edit_address, 1))); CharGroups[i][group].Item.InsertControl(Item_Edit); END; END; END; _top:=1; FOR j:=1 TO number_char_groups DO BEGIN WITH CharGroups[i][j] DO BEGIN Item.Top:=_top; Item.Height:=Count*19+20; _top:=_top+Item.Height; END; END; CharForms[i].memo.Top:=_top+4; CharForms[i].memo.Width:=CharForms[i].Width-8; CharForms[i].Height:=CharForms[i].memo.Top+charforms[i].memo.height+26; END; Application.CreateForm(TForm9, Form9); END; END; PROCEDURE TForm1.Debug_Click(Sender: TObject); VAR debugnumber:Byte; bytes:Byte; tempint:integer; tempfloat:single; buffer:byte_array; BEGIN debugnumber:=StrToInt(MidStr(TComponent(Sender).Name, 6, 10)); IF MidStr(TComponent(Sender).Name, 1, 5)='DEdit' THEN BEGIN WITH Settings[debugnumber] DO BEGIN IF NOT updating THEN BEGIN CASE edit_type OF 1..4:BEGIN bytes:=edit_type; IF TryStrToInt(TEdit(Sender).Text,tempint) THEN BEGIN IF tempint>=Floor(Power(256,bytes)) THEN tempint:=Floor(Power(256,bytes))-1; IF tempint<0 THEN tempint:=0; TEdit(Sender).Text:=IntToStr(tempint); WriteMem(edit_address,bytes,Encode_Int(tempint)); END; END; 5: BEGIN bytes:=4; IF TryStrToFloat(TEdit(Sender).Text,tempfloat) THEN BEGIN IF Pos('(degrees)',TEdit(Sender).hint)>0 THEN tempfloat:=tempfloat*pi/180; WriteMem(edit_address,bytes,Encode_Float(tempfloat)); END; END; 6: BEGIN bytes:=Length(TEdit(Sender).Text)+1; WriteMem(edit_address,bytes,Encode_Str(TEdit(Sender).Text,bytes)); END; END; END; END; END ELSE BEGIN IF Settings[debugnumber].Item_Checkbox.Checked=False THEN BEGIN buffer[0]:=0; WriteMem(Settings[debugnumber].Address,1,buffer); END ELSE BEGIN buffer[0]:=1; WriteMem(Settings[debugnumber].Address,1,buffer); END; END; END; PROCEDURE Create_Settings_Array; VAR i:Byte; _top:Word; BEGIN IF _charformsinitialized=False THEN BEGIN FOR i:=1 TO number_main_groups DO BEGIN WITH MainGroups[i] DO BEGIN name:=MainGroupsStuff[i].name; Count:=0; Item:=TGroupbox.Create(Form1); Item.Caption:=name; Item.Name:='Group'+IntToStr(i); Item.Width:=Form1.Width-6; Item.Visible:=False; Form1.InsertControl(Item); OpenClose:=TSpeedButton.Create(Item); OpenClose.AllowAllUp:=True; OpenClose.GroupIndex:=i; OpenClose.Flat:=True; OpenClose.Glyph.LoadFromResourceName(HInstance,'ARROWS'); OpenClose.Layout:=blGlyphTop; OpenClose.Margin:=0; OpenClose.NumGlyphs:=4; OpenClose.Transparent:=False; OpenClose.Name:='OpenClose'+IntToStr(i); OpenClose.Top:=0; OpenClose.Left:=Item.Width-20; OpenClose.Height:=13; OpenClose.Width:=17; OpenClose.OnClick:=Form1.OpenCloseClick; Item.InsertControl(OpenClose); END; END; FOR i:=1 TO number_settings DO BEGIN WITH Settings[i] DO BEGIN address:=SettingsStuff[i].address; group:=SettingsStuff[i].group; has_box:=SettingsStuff[i].has_box; has_edit:=SettingsStuff[i].has_edit; Inc(MainGroups[group].Count); Item_Checkbox:=TCheckBox.Create(MainGroups[group].Item); Item_Checkbox.Caption:=SettingsStuff[i].caption; IF has_box THEN BEGIN Item_Checkbox:=TCheckBox.Create(MainGroups[group].Item); Item_Checkbox.Caption:=SettingsStuff[i].caption; Item_Checkbox.hint:=SettingsStuff[i].hint; Item_Checkbox.ShowHint:=True; Item_Checkbox.Name:='Debug'+IntToStr(i); Item_Checkbox.Height:=16; Item_Checkbox.Top:=MainGroups[group].Count*16-4; Item_Checkbox.Left:=8; Item_Checkbox.Width:=170; Item_Checkbox.OnClick:=Form1.Debug_Click; MainGroups[group].Item.InsertControl(Item_Checkbox); END ELSE BEGIN Item_Label:=TLabel.Create(MainGroups[group].Item); Item_Label.Caption:=SettingsStuff[i].caption; Item_Label.Hint:=SettingsStuff[i].hint; Item_Label.ShowHint:=True; Item_Label.Name:='Debug'+IntToStr(i); Item_Label.AutoSize:=False; Item_Label.Height:=16; Item_Label.Top:=MainGroups[group].Count*16-4; Item_Label.Left:=27; Item_Label.Width:=150; MainGroups[group].Item.InsertControl(Item_Label); END; IF has_edit THEN BEGIN edit_address:=SettingsStuff[i].edit_address; edit_type:=SettingsStuff[i].edit_type; Item_Edit:=TEdit.Create(MainGroups[group].Item); Item_Edit.AutoSize:=False; IF SettingsStuff[i].edit_hint='' THEN Item_Edit.Hint:=SettingsStuff[i].hint ELSE Item_Edit.Hint:=SettingsStuff[i].edit_hint; Item_Edit.ShowHint:=True; Item_Edit.Name:='DEdit'+IntToStr(i); Item_Edit.Top:=MainGroups[group].Count*16-6; Item_Edit.Left:=180; Item_Edit.Height:=16; Item_Edit.Width:=MainGroups[group].Item.Width-Item_Edit.Left-4; Item_Edit.OnChange:=Form1.Debug_Click; Item_Edit.Text:=''; MainGroups[group].Item.InsertControl(Item_Edit); END; END; END; _top:=1; FOR i:=1 TO number_main_groups DO BEGIN WITH MainGroups[i] DO BEGIN Item.Top:=_top; Item.Height:=Count*16+20; _top:=_top+Item.Height; END; END; END; END; PROCEDURE TForm1.OpenCloseClick(Sender: TObject); VAR number,i:Byte; _top:Word; BEGIN number:=StrToInt(MidStr(TSpeedButton(Sender).Name, 10, 10)); IF MainGroups[number].OpenClose.Down THEN BEGIN MainGroups[number].Item.Height:=20; FOR i:=1 TO number_settings DO BEGIN WITH Settings[i] DO BEGIN IF group=number THEN BEGIN IF has_box THEN Item_Checkbox.Visible:=False ELSE Item_Label.Visible:=False; IF has_edit THEN Item_Edit.Visible:=False; break; END; END; END; _top:=1; FOR i:=1 TO number_main_groups DO BEGIN WITH MainGroups[i] DO BEGIN Item.Top:=_top; _top:=_top+Item.Height; END; END; Form1.Height:=_top+44; END ELSE BEGIN MainGroups[number].Item.Height:=MainGroups[number].Count*16+20; FOR i:=1 TO number_settings DO BEGIN WITH Settings[i] DO BEGIN IF group=number THEN BEGIN IF has_box THEN Item_Checkbox.Visible:=True ELSE Item_Label.Visible:=True; IF has_edit THEN Item_Edit.Visible:=True; break; END; END; END; _top:=1; FOR i:=1 TO number_main_groups DO BEGIN WITH MainGroups[i] DO BEGIN Item.Top:=_top; _top:=_top+Item.Height; END; END; Form1.Height:=_top+44; END; END; PROCEDURE TForm1.InitStuffTimer(Sender: TObject); BEGIN Create_Settings_Array; Form1.Menu_CharsClick(Menu); Form1.InitStuff.Enabled:=False; END; PROCEDURE TForm1.get_valuesTimer(Sender: TObject); VAR i,bytes:byte; tempstring:String[2]; tempfloat:Single; BEGIN IF _connected THEN BEGIN FOR i:=1 TO number_settings DO BEGIN WITH Settings[i] DO BEGIN IF has_edit THEN BEGIN IF NOT Item_Edit.Focused THEN BEGIN updating:=True; CASE edit_type OF 1..4: bytes:=edit_type; 5: bytes:=4; 6: bytes:=100; ELSE bytes:=0; END; _temp:=ReadMem(edit_address,bytes); CASE edit_type OF 1..4: Item_Edit.Text:=IntToStr(Decode_Int(_temp)); 5: BEGIN tempfloat:=Decode_Float(_temp); IF Pos('(degrees)',Item_Edit.hint)>0 THEN tempfloat:=(tempfloat/pi)*180; Item_Edit.Text:=FloatToStr(tempfloat); END; 6: Item_Edit.Text:=Decode_Str(_temp); END; updating:=False; END; END; IF has_box THEN BEGIN IF Decode_Int(ReadMem(address,1))=1 THEN Item_checkbox.Checked:=True ELSE Item_checkbox.Checked:=False; END; END; END; tempstring:=Decode_Str(ReadMem($10F00,2)); FOR i:=0 TO 14 DO BEGIN IF lvl_mappings[i]=tempstring THEN BEGIN IF lvlnumber<>i THEN BEGIN lvlnumber:=i; Form1.Caption:='OniTrainer v'+version+' (Current level: '+IntToStr(lvlnumber)+')'; END; break; END; END; FOR i:=0 TO ais_controlled DO IF _ais_active[i] THEN CharMenus[i].Enabled:=True ELSE CharMenus[i].Enabled:=False; END; END; PROCEDURE TForm1.Menu_RefreshTimeClick(Sender: TObject); BEGIN Form1.Menu_FreezeTime.Enabled:=False; Form1.Menu_RefreshTime.Enabled:=False; Form5.Caption:='Set RefreshTimer'; Form5.timer_label.Caption:='Set interval to refresh data (1/1000 seconds):'; Form5.timer_edit.Text:=IntToStr(Form1.get_values.Interval); Form5.Visible:=True; END; PROCEDURE TForm1.Menu_FreezeTimeClick(Sender: TObject); BEGIN Form1.Menu_FreezeTime.Enabled:=False; Form1.Menu_RefreshTime.Enabled:=False; Form5.Caption:='Set FreezeTimer'; Form5.timer_label.Caption:='Set interval to write data (1/1000 seconds):'; Form5.timer_edit.Text:=IntToStr(CharForms[0].timer_freeze.Interval); Form5.Visible:=True; Form5.timer_edit.SetFocus; END; PROCEDURE TForm1.Menu_AboutClick(Sender: TObject); BEGIN IF Form6.Visible THEN Form6.Visible:=False ELSE Form6.Visible:=True; END; PROCEDURE TForm1.FormCreate(Sender: TObject); VAR start:Word; BEGIN Form1.Caption:='OniTrainer v'+version; Form1.Height:=73; RegisterHotkey(Form1.Handle,1234,MOD_CONTROL,$41 {'A'}); _path:=Application.ExeName; start:=1; WHILE (PosEx('\',_path,start)>0) DO BEGIN start:=PosEx('\',_path,start)+1; END; _path:=MidStr(_path,1,start-2); END; PROCEDURE TForm1.WMHotKey(VAR Msg : TWMHotKey); BEGIN IF Msg.Hotkey=1234 THEN BEGIN Form1.Menu_AOTClick(Form1); END; END; PROCEDURE TForm1.Menu_SetHotKeysClick(Sender: TObject); BEGIN IF Form9.Visible THEN Form9.Visible:=False ELSE Form9.Visible:=True; IF Form9.Visible THEN Form9.SetFocus; END; PROCEDURE TForm1.Menu_Patch_ScriptvarsClick(Sender: TObject); BEGIN Menu_Patch_Scriptvars.Checked:=NOT Menu_Patch_Scriptvars.Checked; Form11.Visible:=Menu_Patch_Scriptvars.Checked; IF Form11.Visible THEN Form11.SetFocus; END; PROCEDURE TForm1.Menu_Patch_MessagesClick(Sender: TObject); BEGIN Menu_Patch_Messages.Checked:=NOT Menu_Patch_Messages.Checked; Form12.Visible:=Menu_Patch_Messages.Checked; IF Form12.Visible THEN Form12.SetFocus; END; PROCEDURE TForm1.Menu_Patch_MovementsClick(Sender: TObject); BEGIN Menu_Patch_Movements.Checked:=NOT Menu_Patch_Movements.Checked; Form13.Visible:=Menu_Patch_Movements.Checked; IF Form13.Visible THEN Form13.SetFocus; END; PROCEDURE TForm1.menu_AnimsClick(Sender: TObject); BEGIN menu_Anims.Checked:=NOT menu_Anims.Checked; Form4.Visible:=menu_Anims.Checked; IF Form4.Visible THEN Form4.SetFocus; END; PROCEDURE TForm1.menu_ModelsClick(Sender: TObject); BEGIN menu_Models.Checked:=NOT menu_Models.Checked; Form14.Visible:=menu_Models.Checked; IF Form14.Visible THEN Form14.SetFocus; END; PROCEDURE TForm1.menu_SpawnClick(Sender: TObject); BEGIN menu_Spawn.Checked:=NOT menu_Spawn.Checked; Form15.Visible:=menu_Spawn.Checked; IF Form15.Visible THEN Form15.SetFocus; END; END.