Unit1.pas 12.2 KB
Newer Older
cz_012273's avatar
cz_012273 已提交
1 2 3 4 5
unit Unit1;

interface

uses
6 7
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants,
cz_012273's avatar
cz_012273 已提交
8 9
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types,
  FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, FMX.Layouts, FMX.StdCtrls,
10
  System.IOUtils, FMX.Objects, FMX.Ani, FMX.Effects, System.DateUtils, Posix.Unistd;
cz_012273's avatar
cz_012273 已提交
11 12 13 14

type
  TForm1 = class(TForm)
    Memo1: TMemo;
15 16 17
    Button1: TButton;
    Filedelete: TButton;
    FileExit: TButton;
cz_012273's avatar
cz_012273 已提交
18 19 20 21
    FileNew: TButton;
    FileOpen: TButton;
    FileSave: TButton;
    FileSaveAs: TButton;
C
cz_012273 已提交
22
    Label1: TLabel;
23
    Image1: TImage;
cz_012273's avatar
cz_012273 已提交
24 25 26 27 28 29

    procedure FileNewClick(Sender: TObject);
    procedure FileOpenClick(Sender: TObject);
    procedure FileSaveClick(Sender: TObject);
    procedure FileSaveAsClick(Sender: TObject);
    procedure FileExitClick(Sender: TObject);
30
    procedure FormShow(Sender: TObject);
cz_012273's avatar
cz_012273 已提交
31
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
C
cz_012273 已提交
32
    procedure Memo1MouseLeave(Sender: TObject);
C
cz_012273 已提交
33
    procedure Button1Click(Sender: TObject);
34 35 36 37
    procedure FiledeleteMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
    procedure FiledeleteMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
38
    procedure Memo1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
cz_012273's avatar
cz_012273 已提交
39 40 41 42 43 44 45

  private
    { Private declarations }

    procedure ToastConfirm(const AStr: string);
    procedure AniToastFinish(Ani: TObject);
    procedure SetFileName(const FileName: String);
46 47
    procedure ResultProc(AResult: Boolean; AFileName: string); // 打开参数过程
    procedure ResultProc1(AResult: Boolean; AFileName: string); // 另存参数过程
cz_012273's avatar
cz_012273 已提交
48 49 50

  public
    { Public declarations }
51 52
    procedure Button_A_Click(Sender: TObject);
    procedure Button_B_Click(Sender: TObject);
cz_012273's avatar
cz_012273 已提交
53 54 55 56 57 58
  end;

var
  Form1: TForm1;
  FFileName: string;
  FWantExit: Boolean;
C
cz_012273 已提交
59
  Label_A,Label_B:Tlabel;
60
  Button_A,Button_B:Tbutton;
61
function GetTextType(const FileName: string): String;
cz_012273's avatar
cz_012273 已提交
62 63 64 65 66 67

implementation

uses
{$IFDEF ANDROID}
{$ENDIF}
cz_012273's avatar
cz_012273 已提交
68
  MyDialogs;
69

cz_012273's avatar
cz_012273 已提交
70
type
71 72
  TTextFormat = (tfAnsi, tfUnicode, tfUnicodeBigEndian, tfUtf8);

73
var
74
  today: Cardinal;
75 76
  selstart: integer;
  sellength: integer;
77

cz_012273's avatar
cz_012273 已提交
78
const
79 80 81
  // TextFormatFlag: array[tfAnsi..tfUtf8] of word=($0000,$FFFE,$FEFF,$EFBB);
  TextFormatFlag: array [tfAnsi .. tfUtf8] of word = ($0000, $FEFF, $FFFE,
    $BBEF); // 编码标志高低字节互换
cz_012273's avatar
cz_012273 已提交
82 83 84 85 86 87

{$R *.fmx}
{$R *.LgXhdpiPh.fmx ANDROID}

resourcestring
  sSaveChanges = '是否将未更改保存到 %s?';
88
  sOverWrite = '%s 已存在。' + #13#10 + '要替换它吗?';
cz_012273's avatar
cz_012273 已提交
89 90 91 92 93 94 95
  sTitle = '记事本';
  sUntitled = '未命名';
  sColRowInfo = 'Line: %3d   Col: %3d';
  sCommonDlgFileName = '文本文档(*.txt)|*.txt|所有文件(*.*)|*.*';

procedure TForm1.SetFileName(const FileName: String);
begin
96 97
  FFileName := System.IOUtils.Tpath.GetSharedDocumentsPath + '/' +
    FileName + '.txt';
cz_012273's avatar
cz_012273 已提交
98 99 100
  Caption := Format('%s - %s', [ExtractFileName(FileName), sTitle]);
end;

101
procedure TForm1.ResultProc(AResult: Boolean; AFileName: string); // 默认参数过程,打开用到
cz_012273's avatar
cz_012273 已提交
102 103
var
  reader: TStreamReader;
104
  TextEncode, s, s1: string;
cz_012273's avatar
cz_012273 已提交
105 106
begin
  if AResult then
107
  begin
cz_012273's avatar
cz_012273 已提交
108

109 110
    TextEncode := GetTextType(AFileName); // 获取文件编码类型
    // showmessage(TextEncode);
cz_012273's avatar
cz_012273 已提交
111

112 113 114 115 116 117 118 119
    if TextEncode = 'ANSI' then // 注意:字符串比较大小写敏感!
      reader := TStreamReader.Create(AFileName, TEncoding.ansi)
    else if TextEncode = 'Utf8' then
      reader := TStreamReader.Create(AFileName, TEncoding.utf8)
    else if TextEncode = 'Unicode' then
      reader := TStreamReader.Create(AFileName, TEncoding.unicode)
    else
      reader := TStreamReader.Create(AFileName, TEncoding.BigEndianUnicode);
cz_012273's avatar
cz_012273 已提交
120

121
    Memo1.Lines.clear; // 清空Memo1中原有内容
cz_012273's avatar
cz_012273 已提交
122

123 124 125 126
    while not reader.EndOfStream do
    begin
      Memo1.Lines.Add(reader.ReadLine);
    end;
cz_012273's avatar
cz_012273 已提交
127 128

    reader.Free;
129 130 131
    s := copy(AFileName, pos('Documents/', AFileName) + 10, 50); // 取文件名(不带路径)
    s1 := copy(s, pos('.', s) + 1, 5); // 取扩展名
    Label1.text := '当前文件:' + s;
132 133

    Button1.text := '选择'; // 加入选择当前行功能
134

135 136
    Memo1.selstart := 0; // 光标放最前面
  end;
cz_012273's avatar
cz_012273 已提交
137 138
end;

139 140
procedure TForm1.ResultProc1(AResult: Boolean; AFileName: string);
// 默认参数过程1,另存用到
C
cz_012273 已提交
141
var
142
  s: string;
cz_012273's avatar
cz_012273 已提交
143
begin
144

cz_012273's avatar
cz_012273 已提交
145
  if AResult then
146 147 148 149 150
  begin
    Memo1.Lines.SaveToFile(AFileName);
    s := copy(AFileName, pos('Documents/', AFileName) + 10, 50); // 取文件名(不带路径)
    Label1.text := '当前文件:' + s;
  end;
cz_012273's avatar
cz_012273 已提交
151 152
end;

153
procedure TForm1.FileNewClick(Sender: TObject); // 新建
cz_012273's avatar
cz_012273 已提交
154 155 156
begin

  SetFileName(sUntitled);
157 158
  Label1.text := '当前文件:' + sUntitled + '.txt';
  Memo1.Lines.clear;
cz_012273's avatar
cz_012273 已提交
159 160 161
  Memo1.text := '';
end;

162
procedure TForm1.FileOpenClick(Sender: TObject); // 打开
cz_012273's avatar
cz_012273 已提交
163 164 165 166
begin

  GetFileOpenDialog(ResultProc);
  {
167
    case TComponent(Sender).Tag of
cz_012273's avatar
cz_012273 已提交
168 169 170
    1: GetFileOpenDialog(ResultProc);
    2: GetFileSaveDialog(ResultProc);
    3: GetSelectDirectoryDialog(ResultProc);
171
    end;
cz_012273's avatar
cz_012273 已提交
172 173 174 175
  }

end;

176
procedure TForm1.FileSaveClick(Sender: TObject); // 保存
177 178
  var
    s: string;
cz_012273's avatar
cz_012273 已提交
179 180
begin

181 182
  s := copy(FFileName, pos('Documents/', FFileName) + 10, 50);
  if s = '.txt' then
183
    FileSaveAsClick(Sender)
cz_012273's avatar
cz_012273 已提交
184 185
  else
  begin
186
    showmessage('当前保存位置及文件名:' + FFileName);
cz_012273's avatar
cz_012273 已提交
187
    Memo1.Lines.SaveToFile(FFileName);
188
    // Memo1.text := '';
cz_012273's avatar
cz_012273 已提交
189 190 191
  end;
end;

192
procedure TForm1.FileSaveAsClick(Sender: TObject); // 另存
cz_012273's avatar
cz_012273 已提交
193
begin
194
  GetFileSaveDialog(ResultProc1); // 调用通用对话框
cz_012273's avatar
cz_012273 已提交
195 196
end;

197
procedure TForm1.Button1Click(Sender: TObject); // 选择当前行文本(或调试运行html)
C
cz_012273 已提交
198
var
199
  Line: integer;
C
cz_012273 已提交
200
begin
201

202 203
  Memo1.setfocus;
  with Memo1 do
204
  begin
205 206 207 208
    Line := CaretPosition.Line;
    selstart := selstart - CaretPosition.pos;
    if Lines.count > 0 then
      sellength := Length(Lines[Line]); // 如不是空文件,选择当前行
209
  end;
210

C
cz_012273 已提交
211 212
end;

213 214 215 216 217 218 219 220 221 222
procedure TForm1.FiledeleteMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);

begin
  today := MilliSecondOfTheDay(Now);
end;

procedure TForm1.FiledeleteMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
var
223
  today1: Cardinal;
224
begin
225 226
  today1 := MilliSecondOfTheDay(Now) - today;
  if today1 > 2000 then
227
  begin
228
    if Label1.text <> '当前文件:未命名.txt' then
229
    begin
230
      showmessage('已删除' + Label1.text);
231 232 233 234
      deletefile(FFileName);
    end;

    SetFileName(sUntitled);
235 236
    Label1.text := '当前文件:' + sUntitled + '.txt';
    Memo1.Lines.clear;
237 238 239 240 241 242
    Memo1.text := '';
  end
  else
    showmessage('确认删除文件请长按此按钮!');
end;

243
procedure TForm1.FileExitClick(Sender: TObject); // 退出
cz_012273's avatar
cz_012273 已提交
244 245 246 247
begin
  Close;
end;

248
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); // 按两次退出
cz_012273's avatar
cz_012273 已提交
249 250 251 252 253 254
begin
{$IFDEF ANDROID}
  if not FWantExit then
  begin
    ToastConfirm('再按一次退出程序.');
    Action := TCloseAction.caNone;
255 256
  end
  else
257
  begin
C
cz_012273 已提交
258 259
    Label_A.free;
    Label_B.free;
260 261
    Button_A.free;
    Button_B.free;
262
    Memo1.height := 510; // 将meno控件恢复到默认高度
263
    Memo1.Lines.clear;
264
  end;
cz_012273's avatar
cz_012273 已提交
265
  FWantExit := True;
266

cz_012273's avatar
cz_012273 已提交
267 268 269
{$ENDIF}
end;

270
procedure TForm1.FormShow(Sender: TObject); // form1显示
cz_012273's avatar
cz_012273 已提交
271 272 273
begin

  SetFileName(sUntitled);
274
  Label1.text := '当前文件:' + sUntitled + '.txt';
275
  //Memo1.height := 436;
276

cz_012273's avatar
cz_012273 已提交
277 278
end;

279 280 281 282 283 284 285 286 287
procedure TForm1.Button_A_Click(Sender: TObject); //光标回首行
begin
  Form1.Memo1.selstart := 0;
end;

procedure TForm1.Button_B_Click(Sender: TObject); //光标到末行
begin
  Form1.Memo1.selstart := Form1.Memo1.text.length;
end;
288

289
procedure TForm1.Memo1MouseLeave(Sender: TObject); // 改变memo1高度以适应虚拟键盘
C
cz_012273 已提交
290
var
291
  i: integer;
292 293
const
  halfscreen :integer = 403;  //显示输入法界面后的memo高度
C
cz_012273 已提交
294 295

begin
296 297
  i := Memo1.selstart;
  // showmessage(inttostr(i));
C
cz_012273 已提交
298

299
  if (i>0) and (Memo1.height > 430) then
C
cz_012273 已提交
300
  begin
301
    Memo1.height := halfscreen;
302
    Memo1.selstart := i;
C
cz_012273 已提交
303

304 305
    //创建显示行、列号标签
      Label_A := tlabel.Create(Self);
C
cz_012273 已提交
306 307 308 309
      with Label_A do
      begin
        Parent := Self;
        position.x := 6;
310
        position.y := halfscreen+30;
311
        //Text := '行号:'+IntToStr(Memo1.CaretPosition.line); // 显示行号
C
cz_012273 已提交
312 313 314 315 316 317 318 319 320
        Width := 165;
        Height := 20;
        Visible := true;
      end;

      Label_B := tlabel.Create(Self);
      with Label_B do
      begin
        Parent := Self;
321
        position.x := 230;
322
        position.y := halfscreen+30;
323
        //Text := '列号:'+IntToStr(Memo1.CaretPosition.Pos); // 显示列号
C
cz_012273 已提交
324 325 326 327 328
        Width := 165;
        Height := 20;
        Visible := true;
      end;

329 330 331 332 333 334
      //创建滚动条加速按钮

      Button_A := tButton.Create(Self);
      with Button_A do
      begin
        Parent := Self;
335
        position.x := 135;
336
        position.y := halfscreen+30;
337 338 339 340 341 342 343 344 345 346 347
        Text := '|←';
        Width := 32;
        Height := 20;
        Visible := true;
        onclick := Button_A_Click;  //设置点击事件
      end;

      Button_B := tButton.Create(Self);
      with Button_B do
      begin
        Parent := Self;
348
        position.x := 193;
349
        position.y := halfscreen+30;
350 351 352 353 354 355 356
        Text := '→|';
        Width := 32;
        Height := 20;
        Visible := true;
        onclick := Button_B_Click;  //设置点击事件
      end;

C
cz_012273 已提交
357 358
  end;

359
  if Memo1.height = halfscreen then   //动态更新行列号
360 361 362 363
  begin
      Label_A.Text := '当前行号:'+IntToStr(Memo1.CaretPosition.line+1);
      Label_B.Text := '当前列号:'+IntToStr(Memo1.CaretPosition.Pos+1);
  end;
C
cz_012273 已提交
364

365 366
  if (Memo1.selstart = selstart) and (Memo1.sellength = sellength) then
    Memo1.enabledscroll := false; // 选择区域未发生变化,禁止滚动
367 368 369

end;

370

371 372
procedure TForm1.Memo1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Single); // 控制memo1选择文本时不滚动
373 374

begin
375 376
  selstart := Memo1.selstart;
  sellength := Memo1.sellength;
377

378 379
  if (Memo1.sellength < 50) and (Memo1.sellength > 0) then
    Memo1.enabledscroll := false
380
  else
381
    Memo1.enabledscroll := True;
382

C
cz_012273 已提交
383 384
end;

385
function WordLoHiExchange(w: word): word; // 高低位互换
cz_012273's avatar
cz_012273 已提交
386
var
387 388
  hi: word;
  lo: word;
cz_012273's avatar
cz_012273 已提交
389 390

begin
391 392 393
  hi := w shl 8;
  lo := w shr 8;
  result := hi or lo
cz_012273's avatar
cz_012273 已提交
394 395
end;

396
function GetTextType(const FileName: string): String; // 获取编码类型
cz_012273's avatar
cz_012273 已提交
397
var
398
  w: word;
cz_012273's avatar
cz_012273 已提交
399 400 401
begin
  with TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone) do
    try
402 403 404
      Read(w, 2);
      // w:=WordLoHiExchange(w);//因为是以Word数据类型读取,故高低字节互换
      // ShowMessage(IntToStr(w));  //查看word变量值
cz_012273's avatar
cz_012273 已提交
405
      if w = TextFormatFlag[tfUnicode] then
406
        result := 'Unicode'
cz_012273's avatar
cz_012273 已提交
407
      else if w = TextFormatFlag[tfUnicodeBigEndian] then
408
        result := 'UnicodeBigEndian'
cz_012273's avatar
cz_012273 已提交
409
      else if w = TextFormatFlag[tfUtf8] then
410
        result := 'Utf8'
cz_012273's avatar
cz_012273 已提交
411
      else
412
        result := 'ANSI';
cz_012273's avatar
cz_012273 已提交
413 414 415 416 417
    finally
      Free;
    end;
end;

418
procedure TForm1.AniToastFinish(Ani: TObject); // 按两次退出提示框结束
cz_012273's avatar
cz_012273 已提交
419 420 421 422 423 424 425
begin
  with TFloatAnimation(Ani) do
  begin
    Delay := 2;
    Duration := 0.3;
    Inverse := True;
    if (TControl(Parent).Opacity = 1) then
426
      FMX.Ani.TAnimator.StartAnimation(Parent, 'Ani')
cz_012273's avatar
cz_012273 已提交
427 428 429 430 431
    else
      FWantExit := not Inverse;
  end;
end;

432
procedure TForm1.ToastConfirm(const AStr: string); // 按两次退出提示框
cz_012273's avatar
cz_012273 已提交
433

434
  procedure AniInit(A: TFloatAnimation); // 内部过程
cz_012273's avatar
cz_012273 已提交
435 436 437 438 439 440 441 442 443 444
  begin
    with A do
    begin
      Parent := TFmxObject(Owner);
      Name := 'Ani';
      PropertyName := 'Opacity';
      StartValue := 0;
      StopValue := 1;
      Delay := 0;
      Duration := 0;
445
      Inverse := false;
cz_012273's avatar
cz_012273 已提交
446 447 448 449 450
      OnFinish := AniToastFinish;
      Start;
    end;
  end;

451 452
  function Find(ACName: string; ACClass: TComponentClass; AOwner: TComponent)
    : TObject; // 内部函数
cz_012273's avatar
cz_012273 已提交
453
  begin
454 455 456
    result := AOwner.FindComponent(ACName);
    if not Assigned(result) then
      result := ACClass.Create(AOwner);
cz_012273's avatar
cz_012273 已提交
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
  end;

var
  LR: TRectangle;
begin
  LR := TRectangle(Find('Toast', TRectangle, Self));
  with LR do
  begin
    if (Name = '') then
    begin
      Name := 'Toast';
      XRadius := 1;
      YRadius := 1;
      Stroke.Kind := TBrushKind.None;
      Fill.Color := TAlphaColorRec.Black;
472
      HitTest := false;
cz_012273's avatar
cz_012273 已提交
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492

      with TGlowEffect.Create(LR) do
      begin
        Parent := LR;
        GlowColor := TAlphaColorRec.Black;
      end;

      with TText.Create(LR) do
      begin
        Name := 'ShowText';
        Parent := LR;
        Font.Size := 12;
        Align := TAlignLayout.Client;
        Color := TAlphaColorRec.White;
      end;
      Parent := Self;
    end;

    with TText(LR.FindComponent('ShowText')) do
    begin
493
      text := AStr;
cz_012273's avatar
cz_012273 已提交
494
      LR.Width := Canvas.TextWidth(AStr) + 35;
495
      LR.height := Canvas.TextHeight(AStr) + 16;
cz_012273's avatar
cz_012273 已提交
496 497
    end;

498 499
    LR.Position.X := (Self.Width - LR.Width) / 2;
    LR.Position.Y := (Self.height - LR.height) / 1.25;
cz_012273's avatar
cz_012273 已提交
500 501 502 503 504 505 506 507
    LR.Repaint;
    LR.BringToFront;
    AniInit(TFloatAnimation(Find('Ani', TFloatAnimation, LR)));
  end;

end;

end.