📄 syneditmiscclasses.pas
字号:
begin
i := 0;
with FNotifyProcs, AMethod do
while i < Count do
try
repeat
Code := Items[i];
Inc(i);
Data := Items[i];
Inc(i);
DoFire(AMethod)
until i >= Count;
except
on E: Exception do
if not DoHandleException(E) then
i := MaxInt;
end;
end;
procedure TSynMethodChain.Remove(AEvent: TMethod);
var
i: Integer;
begin
if not Assigned(@AEvent) then
raise ESynMethodChain.CreateFmt(
'%s.Remove: the parameter `AEvent'' must be specified.', [ClassName]);
with FNotifyProcs, AEvent do
begin
i := Count - 1;
while i > 0 do
if Items[i] <> Data then
Dec(i, 2)
else
begin
Dec(i);
if Items[i] = Code then
begin
Delete(i);
Delete(i);
end;
Dec(i);
end;
end;
end;
{ TSynNotifyEventChain }
procedure TSynNotifyEventChain.Add(AEvent: TNotifyEvent);
begin
inherited Add(TMethod(AEvent));
end;
constructor TSynNotifyEventChain.CreateEx(ASender: TObject);
begin
inherited Create;
FSender := ASender;
end;
procedure TSynNotifyEventChain.DoFire(const AEvent: TMethod);
begin
TNotifyEvent(AEvent)(FSender);
end;
procedure TSynNotifyEventChain.Remove(AEvent: TNotifyEvent);
begin
inherited Remove(TMethod(AEvent));
end;
{ TSynInternalImage }
type
TInternalResource = class (TObject)
public
UsageCount : Integer;
Name : string;
Bitmap : TBitmap;
end;
var
InternalResources: TList;
constructor TSynInternalImage.Create(aModule: THandle; const Name: string; Count: integer);
begin
inherited Create;
fImages := CreateBitmapFromInternalList( aModule, Name );
fWidth := (fImages.Width + Count shr 1) div Count;
fHeight := fImages.Height;
fCount := Count;
end;
destructor TSynInternalImage.Destroy;
begin
FreeBitmapFromInternalList;
inherited Destroy;
end;
function TSynInternalImage.CreateBitmapFromInternalList(aModule: THandle;
const Name: string): TBitmap;
var
idx: Integer;
newIntRes: TInternalResource;
begin
{ There is no list until now }
if (InternalResources = nil) then
InternalResources := TList.Create;
{ Search the list for the needed resource }
for idx := 0 to InternalResources.Count - 1 do
if (TInternalResource (InternalResources[idx]).Name = UpperCase (Name)) then
with TInternalResource (InternalResources[idx]) do begin
UsageCount := UsageCount + 1;
Result := Bitmap;
exit;
end;
{ There is no loaded resource in the list so let's create a new one }
Result := TBitmap.Create;
Result.LoadFromResourceName( aModule, Name );
{ Add the new resource to our list }
newIntRes:= TInternalResource.Create;
newIntRes.UsageCount := 1;
newIntRes.Name := UpperCase (Name);
newIntRes.Bitmap := Result;
InternalResources.Add (newIntRes);
end;
procedure TSynInternalImage.FreeBitmapFromInternalList;
var
idx: Integer;
intRes: TInternalResource;
function FindImageInList: Integer;
begin
for Result := 0 to InternalResources.Count - 1 do
if (TInternalResource (InternalResources[Result]).Bitmap = fImages) then
exit;
Result := -1;
end;
begin
{ Search the index of our resource in the list }
idx := FindImageInList;
{ Ey, what's this ???? }
if (idx = -1) then
exit;
{ Decrement the usagecount in the object. If there are no more users
remove the object from the list and free it }
intRes := TInternalResource (InternalResources[idx]);
with intRes do begin
UsageCount := UsageCount - 1;
if (UsageCount = 0) then begin
Bitmap.Free;
InternalResources.Delete (idx);
intRes.Free;
end;
end;
{ If there are no more entries in the list free it }
if (InternalResources.Count = 0) then begin
InternalResources.Free;
InternalResources := nil;
end;
end;
procedure TSynInternalImage.Draw(ACanvas: TCanvas;
Number, X, Y, LineHeight: integer);
var
rcSrc, rcDest: TRect;
begin
if (Number >= 0) and (Number < fCount) then
begin
if LineHeight >= fHeight then begin
rcSrc := Rect(Number * fWidth, 0, (Number + 1) * fWidth, fHeight);
Inc(Y, (LineHeight - fHeight) div 2);
rcDest := Rect(X, Y, X + fWidth, Y + fHeight);
end else begin
rcDest := Rect(X, Y, X + fWidth, Y + LineHeight);
Y := (fHeight - LineHeight) div 2;
rcSrc := Rect(Number * fWidth, Y, (Number + 1) * fWidth,
Y + LineHeight);
end;
ACanvas.CopyRect(rcDest, fImages.Canvas, rcSrc);
end;
end;
procedure TSynInternalImage.DrawTransparent(ACanvas: TCanvas; Number, X, Y,
LineHeight: integer; TransparentColor: TColor);
var
rcSrc, rcDest: TRect;
begin
if (Number >= 0) and (Number < fCount) then
begin
if LineHeight >= fHeight then begin
rcSrc := Rect(Number * fWidth, 0, (Number + 1) * fWidth, fHeight);
Inc(Y, (LineHeight - fHeight) div 2);
rcDest := Rect(X, Y, X + fWidth, Y + fHeight);
end else begin
rcDest := Rect(X, Y, X + fWidth, Y + LineHeight);
Y := (fHeight - LineHeight) div 2;
rcSrc := Rect(Number * fWidth, Y, (Number + 1) * fWidth,
Y + LineHeight);
end;
{$IFDEF SYN_CLX}
ACanvas.CopyMode := cmMergeCopy;
ACanvas.CopyRect(rcDest, fImages.Canvas, rcSrc);
{$ELSE}
ACanvas.BrushCopy(rcDest, fImages, rcSrc, TransparentColor);
{$ENDIF}
end;
end;
{ TSynHotKey }
function KeySameAsShiftState(Key: Word; Shift: TShiftState): Boolean;
begin
Result := (Key = SYNEDIT_SHIFT) and (ssShift in Shift) or
(Key = SYNEDIT_CONTROL) and (ssCtrl in Shift) or
(Key = SYNEDIT_MENU) and (ssAlt in Shift);
end;
function ModifiersToShiftState(Modifiers: THKModifiers): TShiftState;
begin
Result := [];
if hkShift in Modifiers then Include(Result, ssShift);
if hkCtrl in Modifiers then Include(Result, ssCtrl);
if hkAlt in Modifiers then Include(Result, ssAlt);
end;
function ShiftStateToTHKInvalidKey(Shift: TShiftState): THKInvalidKey;
begin
Shift := Shift * [ssShift, ssAlt, ssCtrl];
if Shift = [ssShift] then
Result := hcShift
else if Shift = [ssCtrl] then
Result := hcCtrl
else if Shift = [ssAlt] then
Result := hcAlt
else if Shift = [ssShift, ssCtrl] then
Result := hcShiftCtrl
else if Shift = [ssShift, ssAlt] then
Result := hcShiftAlt
else if Shift = [ssCtrl, ssAlt] then
Result := hcCtrlAlt
else if Shift = [ssShift, ssCtrl, ssAlt] then
Result := hcShiftCtrlAlt
else
Result := hcNone;
end;
function ShortCutToTextEx(Key: Word; Shift: TShiftState): WideString;
begin
if ssCtrl in Shift then Result := SmkcCtrl;
if ssShift in Shift then Result := Result + SmkcShift;
if ssAlt in Shift then Result := Result + SmkcAlt;
{$IFDEF SYN_CLX}
if Lo(Key) > Ord('Z') then
Result := Result + Chr(Key)
else
{$ENDIF}
Result := Result + ShortCutToText(TShortCut(Key));
if Result = '' then
Result := srNone;
end;
constructor TSynHotKey.Create(AOwner: TComponent);
begin
inherited;
{$IFDEF SYN_CLX}
InputKeys := [ikAll];
{$ENDIF}
BorderStyle := bsSingle;
{$IFNDEF SYN_CLX}
{$IFDEF SYN_COMPILER_7_UP}
ControlStyle := ControlStyle + [csNeedsBorderPaint];
{$ENDIF}
{$ENDIF}
FInvalidKeys := [hcNone, hcShift];
FModifiers := [hkAlt];
SetHotKey($0041); { Alt+A }
ParentColor := False;
Color := clWindow;
TabStop := True;
end;
{$IFNDEF SYN_CLX}
procedure TSynHotKey.CreateParams(var Params: TCreateParams);
const
BorderStyles: array[TSynBorderStyle] of DWORD = (0, WS_BORDER);
ClassStylesOff = CS_VREDRAW or CS_HREDRAW;
begin
inherited CreateParams(Params);
with Params do
begin
WindowClass.Style := WindowClass.Style and not ClassStylesOff;
Style := Style or BorderStyles[fBorderStyle] or WS_CLIPCHILDREN;
if NewStyleControls and Ctl3D and (fBorderStyle = bsSingle) then
begin
Style := Style and not WS_BORDER;
ExStyle := ExStyle or WS_EX_CLIENTEDGE;
end;
end;
end;
{$ENDIF}
procedure TSynHotKey.DoExit;
begin
inherited;
if FPressedOnlyModifiers then
begin
Text := srNone;
Invalidate;
end;
end;
{$IFDEF SYN_CLX}
function TSynHotKey.EventFilter(Sender: QObjectH; Event: QEventH): Boolean;
begin
Result := inherited EventFilter(Sender, Event);
case QEvent_type(Event) of
QEventType_FocusIn:
begin
Canvas.Font := Font;
CreateCaret(Self, 0, 1, Canvas.TextHeight('x') + 2);
SetCaretPos(BorderWidth + 1 + Canvas.TextWidth(Text), BorderWidth + 1);
ShowCaret(Self);
end;
QEventType_FocusOut:
begin
DestroyCaret;
end;
end;
end;
{$ENDIF}
procedure TSynHotKey.KeyDown(var Key: Word; Shift: TShiftState);
var
MaybeInvalidKey: THKInvalidKey;
SavedKey: Word;
{$IFDEF LINUX}
Code: Byte;
{$ENDIF}
begin
{$IFDEF LINUX}
// uniform Keycode: key has the same value wether Shift is pressed or not
if Key <= 255 then
begin
Code := XKeysymToKeycode(Xlib.PDisplay(QtDisplay), Key);
Key := XKeycodeToKeysym(Xlib.PDisplay(QtDisplay), Code, 0);
if Char(Key) in ['a'..'z'] then Key := Ord(UpCase(Char(Key)));
end;
{$ENDIF}
SavedKey := Key;
FPressedOnlyModifiers := KeySameAsShiftState(Key, Shift);
MaybeInvalidKey := ShiftStateToTHKInvalidKey(Shift);
if MaybeInvalidKey in FInvalidKeys then
Shift := ModifiersToShiftState(FModifiers);
if not FPressedOnlyModifiers then
begin
{$IFDEF SYN_CLX}
if Lo(Key) > Ord('Z') then
Key := Lo(Key);
{$ENDIF}
FHotKey := ShortCut(Key, Shift)
end
else
begin
FHotKey := 0;
Key := 0;
end;
if Text <> ShortCutToTextEx(Key, Shift) then
begin
Text := ShortCutToTextEx(Key, Shift);
Invalidate;
SetCaretPos(BorderWidth + 1 + Canvas.TextWidth(Text), BorderWidth + 1);
end;
Key := SavedKey;
end;
procedure TSynHotKey.KeyUp(var Key: Word; Shift: TShiftState);
{$IFDEF LINUX}
var
Code: Byte;
{$ENDIF}
begin
{$IFDEF LINUX}
// uniform Keycode: key has the same value wether Shift is pressed or not
if Key <= 255 then
begin
Code := XKeysymToKeycode(Xlib.PDisplay(QtDisplay), Key);
Key := XKeycodeToKeysym(Xlib.PDisplay(QtDisplay), Code, 0);
if Char(Key) in ['a'..'z'] then Key := Ord(UpCase(Char(Key)));
end;
{$ENDIF}
if FPressedOnlyModifiers then
begin
Text := srNone;
Invalidate;
SetCaretPos(BorderWidth + 1 + Canvas.TextWidth(Text), BorderWidth + 1);
end;
end;
procedure TSynHotKey.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
inherited;
SetFocus;
end;
procedure TSynHotKey.Paint;
var
r: TRect;
begin
r := ClientRect;
{$IFDEF SYN_CLX}
QClxDrawUtil_DrawWinPanel(Canvas.Handle, @r, Palette.ColorGroup(cgActive), True,
QBrushH(0));
{$ENDIF}
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := Color;
InflateRect(r, -BorderWidth, -BorderWidth);
Canvas.FillRect(r);
Canvas.TextRect(r, BorderWidth + 1, BorderWidth + 1, Text);
end;
procedure TSynHotKey.SetBorderStyle(const Value: TSynBorderStyle);
begin
if FBorderStyle <> Value then
begin
FBorderStyle := Value;
{$IFDEF SYN_CLX}
Resize;
Invalidate;
{$ELSE}
RecreateWnd;
{$ENDIF}
end;
end;
procedure TSynHotKey.SetHotKey(const Value: TShortCut);
var
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -