📄 fqbsynmemo.pas
字号:
FSelEnd := FPos;
Repaint;
end;
procedure TfqbSyntaxMemo.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
if FDoubleClicked then
begin
FDoubleClicked := False;
Exit;
end;
if (Button = mbRight) and (PopupMenu = nil) then
{$IFDEF Delphi4}
FPopUpMenu.Popup(Mouse.CursorPos.x, Mouse.CursorPos.y)
{$ENDIF}
else
begin
FMoved := True;
if not Focused then
SetFocus;
FDown := True;
SetPos((X - FGutterWidth) div FCharWidth + 1 + FOffset.X,
Y div FCharHeight + 1 + FOffset.Y);
ClearSel;
end;
end;
procedure TfqbSyntaxMemo.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
if FDown then
begin
FTempPos := FPos;
FPos.X := (X - FGutterWidth) div FCharWidth + 1 + FOffset.X;
FPos.Y := Y div FCharHeight + 1 + FOffset.Y;
if (FPos.X <> FTempPos.X) or (FPos.Y <> FTempPos.Y) then
begin
SetPos(FPos.X, FPos.Y);
AddSel;
end;
end;
end;
procedure TfqbSyntaxMemo.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
FDown := False;
end;
procedure TfqbSyntaxMemo.KeyDown(var Key: Word; Shift: TShiftState);
var
MyKey: Boolean;
begin
inherited;
FAllowLinesChange := False;
FTempPos := FPos;
MyKey := True;
case Key of
vk_Left:
if ssCtrl in Shift then
DoCtrlL else
DoLeft;
vk_Right:
if ssCtrl in Shift then
DoCtrlR else
DoRight;
vk_Up:
DoUp;
vk_Down:
DoDown;
vk_Home:
DoHome(ssCtrl in Shift);
vk_End:
DoEnd(ssCtrl in Shift);
vk_Prior:
DoPgUp;
vk_Next:
DoPgDn;
vk_Return:
if Shift = [] then
DoReturn;
vk_Delete:
if ssShift in Shift then
CutToClipboard else
DoDel;
vk_Back:
DoBackspace;
vk_Insert:
if ssCtrl in Shift then
CopyToClipboard
else if ssShift in Shift then
PasteFromClipboard;
vk_Tab:
TabIndent;
vk_F3:
Find(LastSearch); // F3 Repeat search
else
MyKey := False;
end;
if Shift = [ssCtrl] then
if Key = 65 then // Ctrl+A Select all
begin
SetPos(0, 0);
FSelStart := FPos;
SetPos(LineLength(FText.Count - 1) + 1, FText.Count);
FSelEnd := FPos;
Repaint;
end
else
if Key = 70 then // Ctrl+F Search
begin
fqbSynMemoSearch := TfqbSynMemoSearch.Create(nil);
if fqbSynMemoSearch.ShowModal = mrOk then
Find(fqbSynMemoSearch.Edit1.Text);
LastSearch := fqbSynMemoSearch.Edit1.Text;
fqbSynMemoSearch.Free;
end
else
if Key = 89 then // Ctrl+Y Delete line
begin
if FText.Count > FPos.Y then
begin
FMoved := True;
AddUndo;
FText.Delete(FPos.Y - 1);
CorrectBookmark(FPos.Y, -1);
UpdateSyntax;
end
else
if FText.Count = FPos.Y then
begin
FMoved := True;
AddUndo;
FText[FPos.Y - 1] := '';
FPos.X := 1;
SetPos(FPos.X, FPos.Y);
UpdateSyntax;
end
end
else
if Key in [48..57] then
GotoBookmark(Key-48);
if Shift = [ssCtrl, ssShift] then
if Key in [48..57] then
if IsBookmark(FPos.Y - 1) < 0 then
AddBookmark(FPos.Y - 1, Key-48)
else
if IsBookmark(FPos.Y - 1) = (Key-48) then
DeleteBookmark(Key-48);
if Key in [vk_Left, vk_Right, vk_Up, vk_Down, vk_Home, vk_End, vk_Prior, vk_Next] then
begin
FMoved := True;
if ssShift in Shift then
AddSel else
ClearSel;
end
else if Key in [vk_Return, vk_Delete, vk_Back, vk_Insert, vk_Tab] then
FMoved := True;
if MyKey then
Key := 0;
end;
procedure TfqbSyntaxMemo.KeyPress(var Key: Char);
var
MyKey: Boolean;
begin
inherited;
MyKey := True;
case Key of
#3:
CopyToClipboard;
#9:
DoCtrlI;
#21:
DoCtrlU;
#22:
PasteFromClipboard;
#24:
CutToClipboard;
#26:
Undo;
#32..#255:
begin
DoChar(Key);
FMoved := True;
end;
else
MyKey := False;
end;
if MyKey then
Key := #0;
end;
procedure TfqbSyntaxMemo.DoLeft;
begin
Dec(FPos.X);
if FPos.X < 1 then
FPos.X := 1;
SetPos(FPos.X, FPos.Y);
end;
procedure TfqbSyntaxMemo.DoRight;
begin
Inc(FPos.X);
if FPos.X > FMaxLength then
FPos.X := FMaxLength;
SetPos(FPos.X, FPos.Y);
end;
procedure TfqbSyntaxMemo.DoUp;
begin
Dec(FPos.Y);
if FPos.Y < 1 then
FPos.Y := 1;
SetPos(FPos.X, FPos.Y);
end;
procedure TfqbSyntaxMemo.DoDown;
begin
Inc(FPos.Y);
if FPos.Y > FText.Count then
FPos.Y := FText.Count;
SetPos(FPos.X, FPos.Y);
end;
procedure TfqbSyntaxMemo.DoHome(Ctrl: Boolean);
begin
if Ctrl then
SetPos(1, 1) else
SetPos(1, FPos.Y);
end;
procedure TfqbSyntaxMemo.DoEnd(Ctrl: Boolean);
begin
if Ctrl then
SetPos(LineLength(FText.Count - 1) + 1, FText.Count) else
SetPos(LineLength(FPos.Y - 1) + 1, FPos.Y);
end;
procedure TfqbSyntaxMemo.DoPgUp;
begin
if FOffset.Y > FWindowSize.Y then
begin
Dec(FOffset.Y, FWindowSize.Y - 1);
Dec(FPos.Y, FWindowSize.Y - 1);
end
else
begin
if FOffset.Y > 0 then
begin
Dec(FPos.Y, FOffset.Y);
FOffset.Y := 0;
end
else
FPos.Y := 1;
end;
SetPos(FPos.X, FPos.Y);
Repaint;
end;
procedure TfqbSyntaxMemo.DoPgDn;
begin
if FOffset.Y + FWindowSize.Y < FText.Count then
begin
Inc(FOffset.Y, FWindowSize.Y - 1);
Inc(FPos.Y, FWindowSize.Y - 1);
end
else
begin
FOffset.Y := FText.Count;
FPos.Y := FText.Count;
end;
SetPos(FPos.X, FPos.Y);
Repaint;
end;
procedure TfqbSyntaxMemo.DoReturn;
var
s: String;
begin
if FReadOnly then exit;
s := LineAt(FPos.Y - 1);
FText[FPos.Y - 1] := Copy(s, 1, FPos.X - 1);
FText.Insert(FPos.Y, Copy(s, FPos.X, FMaxLength));
EnterIndent;
end;
procedure TfqbSyntaxMemo.DoDel;
var
s: String;
begin
if FReadOnly then exit;
FMessage := '';
if FSelStart.X <> 0 then
SelText := ''
else
begin
s := FText[FPos.Y - 1];
AddUndo;
if FPos.X <= LineLength(FPos.Y - 1) then
begin
Delete(s, FPos.X, 1);
FText[FPos.Y - 1] := s;
end
else if FPos.Y < FText.Count then
begin
s := s + Pad(FPos.X - Length(s) - 1) + LineAt(FPos.Y);
FText[FPos.Y - 1] := s;
FText.Delete(FPos.Y);
CorrectBookmark(FSelStart.Y, -1);
end;
UpdateScrollBar;
UpdateSyntax;
DoChange;
end;
end;
procedure TfqbSyntaxMemo.DoBackspace;
var
s: String;
begin
if FReadOnly then exit;
FMessage := '';
if FSelStart.X <> 0 then
SelText := ''
else
begin
s := FText[FPos.Y - 1];
if FPos.X > 1 then
begin
if (GetLineBegin(FPos.Y - 1) = FPos.X) or (Trim(s) = '') then
UnIndent
else
begin
AddUndo;
if Trim(s) <> '' then
begin
Delete(s, FPos.X - 1, 1);
FText[FPos.Y - 1] := s;
DoLeft;
end
else
DoHome(False);
UpdateSyntax;
DoChange;
end;
end
else if FPos.Y > 1 then
begin
AddUndo;
CorrectBookmark(FPos.Y, -1);
s := LineAt(FPos.Y - 2);
FText[FPos.Y - 2] := s + FText[FPos.Y - 1];
FText.Delete(FPos.Y - 1);
SetPos(Length(s) + 1, FPos.Y - 1);
UpdateSyntax;
DoChange;
end;
end;
end;
procedure TfqbSyntaxMemo.DoCtrlI;
begin
if FSelStart.X <> 0 then
ShiftSelected(True);
end;
procedure TfqbSyntaxMemo.DoCtrlU;
begin
if FSelStart.X <> 0 then
ShiftSelected(False);
end;
procedure TfqbSyntaxMemo.DoCtrlL;
var
i: Integer;
s: String;
begin
s := FText.Text;
i := Length(LineAt(FPos.Y - 1));
if FPos.X > i then
FPos.X := i;
i := GetPlainTextPos(FPos);
Dec(i);
while (i > 0) and not (s[i] in WordChars) do
if s[i] = #13 then
break else
Dec(i);
while (i > 0) and (s[i] in WordChars) do
Dec(i);
Inc(i);
FPos := GetPosPlainText(i);
SetPos(FPos.X, FPos.Y);
end;
procedure TfqbSyntaxMemo.DoCtrlR;
var
i: Integer;
s: String;
begin
s := FText.Text;
i := Length(LineAt(FPos.Y - 1));
if FPos.X > i then
begin
DoDown;
DoHome(False);
FPos.X := 0;
end;
i := GetPlainTextPos(FPos);
while (i < Length(s)) and (s[i] in WordChars) do
Inc(i);
while (i < Length(s)) and not (s[i] in WordChars) do
if s[i] = #13 then
break else
Inc(i);
FPos := GetPosPlainText(i);
SetPos(FPos.X, FPos.Y);
end;
procedure TfqbSyntaxMemo.DoChar(Ch: Char);
begin
SelText := Ch;
end;
function TfqbSyntaxMemo.GetCharAttr(Pos: TPoint): TCharAttributes;
function IsBlock: Boolean;
var
p1, p2, p3: Integer;
begin
Result := False;
if FSelStart.X = 0 then exit;
p1 := FSelStart.X + FSelStart.Y * FMaxLength;
p2 := FSelEnd.X + FSelEnd.Y * FMaxLength;
if p1 > p2 then
begin
p3 := p1;
p1 := p2;
p2 := p3;
end;
p3 := Pos.X + Pos.Y * FMaxLength;
Result := (p3 >= p1) and (p3 < p2);
end;
function CharAttr: TCharAttr;
var
s: String;
begin
if Pos.Y - 1 < FSynStrings.Count then
begin
s := FSynStrings[Pos.Y - 1];
if Pos.X <= Length(s) then
Result := TCharAttr(Ord(s[Pos.X])) else
Result := caText;
end
else
Result := caText;
end;
begin
Result := [CharAttr];
if IsBlock then
Result := Result + [caBlock];
end;
procedure TfqbSyntaxMemo.Paint;
var
i, j, j1: Integer;
a, a1: TCharAttributes;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -