📄 hexedit.pas
字号:
if (X >= X1) and (X <= X2) then
begin
Col := I;
CurInHex := False;
CurInHigh := False;
Break;
end;
end;
Result := (OffRow <> -1) and (Col <> -1) and
(GetDLen(FTopRow + OffRow, Col, CurInHigh) <= GetDataSize * 2);
end;
procedure TCustomHexEdit.MoveCaret(DLenOffset: Integer; Force: Boolean);
var
OldDLen, DLen, AbsRow, OffRow, Col: Integer;
OldTopRow: Integer;
CurInHigh: Boolean;
begin
OldTopRow := FTopRow;
PosToDLen(DLen, FCurRow, FCurCol, FCurInHigh);
OldDLen := DLen;
DLen := DLen + DLenOffset;
if DLen < 1 then DLen := 1
else if DLen > GetDataSize * 2 then DLen := GetDataSize * 2;
if (DLen = OldDLen) and not Force then Exit;
DLenToPos(AbsRow, Col, CurInHigh, DLen);
OffRow := AbsRow - FTopRow;
DrawCurItemHighlight(False);
DrawCurItem(False);
FCurRow := AbsRow;
FCurCol := Col;
FCurInHigh := CurInHigh;
if OffRow < 0 then
begin
FTopRow := AbsRow;
end
else if OffRow >= FVisRowCount then
begin
FTopRow := AbsRow - FVisRowCount + 1;
end;
DrawCurItem(True);
DrawCurItemHighlight(True);
if FTopRow <> OldTopRow then DrawAllRow;
UpdateScrollPos(skVertical, FTopRow);
DoOnCaretMove;
end;
procedure TCustomHexEdit.MoveCaretTo(DLen: Integer; Force: Boolean);
var
CurDLen: Integer;
begin
if DLen < 1 then DLen := 1;
if DLen > GetDataSize * 2 then DLen := GetDataSize * 2;
CurDLen := GetDLen;
MoveCaret(DLen - CurDLen, Force);
end;
procedure TCustomHexEdit.RestrictCaret;
var
DLen, AbsRow, Col: Integer;
CurInHigh: Boolean;
begin
if GetOffset > GetDataSize - 1 then
begin
DLen := OffsetToDLen(GetDataSize - 1);
DLenToPos(AbsRow, Col, CurInHigh, DLen);
FCurRow := AbsRow;
FCurCol := Col;
end;
end;
function TCustomHexEdit.CheckCaretInWindow: Boolean;
begin
Result := (FCurRow >= FTopRow) and (FCurRow <= FTopRow + FVisRowCount - 1);
end;
procedure TCustomHexEdit.AdjustSelectionA(Offset1, Offset2: Integer);
begin
if not (hoAllowSelect in FOptions) or
not (hoShowCaret in FOptions) then Exit;
if not FSelection.Active then
begin
SetSelection(Offset1, Offset2, False);
end else
begin
if FSelection.StartOffset = Offset1 then
SetSelectionStart(Offset2, False)
else if FSelection.EndOffset = Offset1 then
SetSelectionEnd(Offset2, False)
else if Offset2 >= 0 then
SetSelection(Offset2, Offset1, False);
end;
end;
procedure TCustomHexEdit.AdjustSelectionB(Offset1, Offset2: Integer);
begin
if not (hoAllowSelect in FOptions) or
not (hoShowCaret in FOptions) then Exit;
if not FSelection.Active then
begin
SetSelection(Offset1, Offset2, False);
end else
begin
if FSelection.EndOffset = Offset1 then
SetSelectionEnd(Offset2, False)
else if FSelection.StartOffset = Offset1 then
SetSelectionStart(Offset2, False)
else if Offset2 < GetDataSize then
SetSelection(Offset1, Offset2, False);
end;
end;
procedure TCustomHexEdit.SetSelection(StartOffset, EndOffset: Integer; Redraw: Boolean);
var
OldSelection: TSelection;
begin
OldSelection := FSelection;
FSelection.Active := True;
FSelection.StartOffset := StartOffset;
FSelection.EndOffset := EndOffset;
RestrictSelection;
if Redraw then DoPaint;
if not CompareMem(Pointer(@OldSelection), Pointer(@FSelection), SizeOf(TSelection)) then
DoOnSelectionChange;
end;
procedure TCustomHexEdit.SetSelectionStart(StartOffset: Integer; Redraw: Boolean);
begin
if StartOffset < 0 then StartOffset := 0;
if StartOffset > GetDataSize - 1 then StartOffset := GetDataSize - 1;
FSelection.StartOffset := StartOffset;
if FSelection.StartOffset > FSelection.EndOffset then
FSelection.Active := False
else
FSelection.Active := True;
if Redraw then DoPaint;
DoOnSelectionChange;
end;
procedure TCustomHexEdit.SetSelectionEnd(EndOffset: Integer; Redraw: Boolean);
begin
if EndOffset < 0 then EndOffset := 0;
if EndOffset > GetDataSize - 1 then EndOffset := GetDataSize - 1;
FSelection.EndOffset := EndOffset;
if FSelection.StartOffset > FSelection.EndOffset then
FSelection.Active := False
else
FSelection.Active := True;
if Redraw then DoPaint;
DoOnSelectionChange;
end;
procedure TCustomHexEdit.SetSelectionVisible(Value: Boolean);
begin
if FSelection.Active <> Value then
begin
FSelection.Active := Value;
RestrictSelection;
DoPaint;
DoOnSelectionChange;
end;
end;
procedure TCustomHexEdit.CancelSelection(Redraw: Boolean);
begin
if FSelection.Active then
begin
FSelection.Active := False;
if Redraw then DoPaint;
DoOnSelectionChange;
end;
end;
procedure TCustomHexEdit.CancelSelByUser(Redraw: Boolean);
begin
if hoAutoHideSelection in FOptions then
CancelSelection(Redraw);
end;
procedure TCustomHexEdit.RestrictSelection;
begin
if FSelection.Active then
begin
if FSelection.StartOffset > FSelection.EndOffset then
SwapInt(FSelection.StartOffset, FSelection.EndOffset);
if FSelection.StartOffset < 0 then
FSelection.StartOffset := 0;
if FSelection.EndOffset > GetDataSize - 1 then
FSelection.EndOffset := GetDataSize - 1;
if FSelection.StartOffset > FSelection.EndOffset then
FSelection.Active := False;
end;
end;
function TCustomHexEdit.CheckInSelection(Offset: Integer): Boolean;
begin
Result := FSelection.Active;
if Result then
Result := (Offset >= FSelection.StartOffset) and (Offset <= FSelection.EndOffset);
end;
procedure TCustomHexEdit.GetOffsetRange(var StartOffset, EndOffset: Integer;
OnlyBlock, FromCursor: Boolean);
var
CurOffset: Integer;
begin
CurOffset := GetOffset;
if OnlyBlock then
begin
if FSelection.Active then
begin
if FromCursor then
begin
if (CurOffset >= FSelection.StartOffset) and
(CurOffset <= FSelection.EndOffset) then
begin
StartOffset := CurOffset + 1;
EndOffset := FSelection.EndOffset;
end else
begin
StartOffset := FSelection.StartOffset;
EndOffset := FSelection.EndOffset;
end;
end else
begin
StartOffset := FSelection.StartOffset;
EndOffset := FSelection.EndOffset;
end;
end else
begin
StartOffset := 0;
EndOffset := -1;
end;
end else
begin
if FromCursor then
StartOffset := CurOffset + 1
else
StartOffset := 0;
EndOffset := GetDataSize - 1;
end;
end;
procedure TCustomHexEdit.UpdateVertScrollBar;
var
Max, Page: Integer;
begin
if (ScrollBars in [ssNone, ssHorizontal]) or
not HandleAllocated or not Showing then Exit;
if csDesigning in ComponentState then
begin
UpdateScrollMax(skVertical, 1);
UpdateScrollPage(skVertical, 0);
end else
begin
Max := FRowCount - 2;
if Max < 1 then Max := 1;
UpdateScrollMax(skVertical, Max);
Page := FVisRowCount - 1;
if Page < 1 then Page := 1;
UpdateScrollPage(skVertical, Page);
end;
end;
procedure TCustomHexEdit.UpdateHorzScrollBar;
var
Max: Integer;
begin
if (ScrollBars in [ssNone, ssVertical]) or
not HandleAllocated or not Showing then Exit;
if csDesigning in ComponentState then
begin
UpdateScrollMax(skHorizontal, 1);
UpdateScrollPage(skHorizontal, 0);
end else
begin
if ClientWidth < GetRowTotalWidth then
Max := GetRowTotalWidth div FCharWidth - 1
else
Max := 0;
UpdateScrollMax(skHorizontal, Max);
UpdateScrollPage(skHorizontal, ClientWidth div FCharWidth - 1);
end;
end;
procedure TCustomHexEdit.UpdateScrollPage(AScrollKind: TScrollKind; APage: Integer);
var
ScrInfo: TScrollInfo;
BarFlag: Integer;
begin
if AScrollKind = skHorizontal then
BarFlag := SB_HORZ
else
BarFlag := SB_VERT;
if APage < 0 then APage := 0;
FillChar(ScrInfo, SizeOf(ScrInfo), 0);
ScrInfo.cbSize := SizeOf(ScrInfo);
ScrInfo.fMask := SIF_DISABLENOSCROLL or SIF_PAGE;
ScrInfo.nPage := APage;
SetScrollInfo(Handle, BarFlag, ScrInfo, True);
end;
procedure TCustomHexEdit.UpdateScrollMax(AScrollKind: TScrollKind; AMax: Integer);
var
BarFlag: Integer;
begin
if AScrollKind = skHorizontal then
BarFlag := SB_HORZ
else
BarFlag := SB_VERT;
if AMax < 0 then AMax := 0;
SetScrollRange(Handle, BarFlag, 0, AMax, True);
end;
procedure TCustomHexEdit.UpdateScrollPos(AScrollKind: TScrollKind; APos: Integer);
var
BarFlag: Integer;
begin
if AScrollKind = skHorizontal then
BarFlag := SB_HORZ
else
BarFlag := SB_VERT;
if APos < 0 then APos := 0;
SetScrollPos(Handle, BarFlag, APos, True);
end;
procedure TCustomHexEdit.DrawText(X, Y: Integer; S: string; CharAttr: TCharAttr);
begin
Canvas.Brush.Color := CharAttr.BColor;
Canvas.Font.Color := CharAttr.FColor;
Canvas.TextOut(X - FCharWidth * FLeftCol, Y, S);
end;
procedure TCustomHexEdit.DrawAddrRow(OffRow, AbsRow: Integer);
var
S: string;
X, Y: Integer;
begin
X := GetAddrAreaLeft;
Y := OffRow * FCharHeight;
Canvas.Brush.Color := FColors.AddressColor.BColor;
Canvas.FillRect(Rect(0, Y, FMargin, Y + FCharHeight));
S := IntToHex(AbsRow * 16, 8) + ': ';
DrawText(X, Y, S, FColors.AddressColor);
end;
procedure TCustomHexEdit.DrawHexRow(OffRow, AbsRow: Integer);
var
S, S1: string;
X, Y: Integer;
I, Offset: Integer;
CharAttr: TCharAttr;
begin
X := GetHexAreaLeft;
Y := OffRow * FCharHeight;
S := GetHexAreaStr(AbsRow);
for I := 0 to 15 do
begin
Offset := GetOffset(AbsRow, I);
CharAttr := GetCharAttrByRowCol(AbsRow, I, True);
if (Offset <> FSelection.EndOffset) and (I <> 15) then
begin
S1 := Copy(S, I*3+1, 3);
DrawText(X+I*FCharWidth*3, Y, S1, CharAttr);
end else
begin
S1 := Copy(S, I*3+1, 2);
DrawText(X+I*FCharWidth*3, Y, S1, CharAttr);
S1 := Copy(S, I*3+3, 1);
DrawText(X+I*FCharWidth*3+FCharWidth*2, Y, S1, FColors.HexColor);
end;
end;
end;
procedure TCustomHexEdit.DrawChrRow(OffRow, AbsRow: Integer);
var
S: string;
S1: array[1..3] of string;
I, J, Offset: Integer;
DrawSelection, InSelection: Boolean;
CharAttr: TCharAttr;
begin
S := GetChrAreaStr(AbsRow);
//画右边的空白区域
Canvas.Brush.Color := FColors.CharColor.BColor;
Canvas.FillRect(Rect(GetChrAreaLeft + FCharWidth * (Length(S) - FLeftCol),
OffRow * FCharHeight, ClientWidth, (OffRow+1) * FCharHeight));
if not FSelection.Active then DrawSelection := False
else
begin
if (GetOffset(AbsRow, 0) <= FSelection.EndOffset) and
(GetOffset(AbsRow, 15) >= FSelection.StartOffset) then
DrawSelection := True
else
DrawSelection := False;
end;
if DrawSelection then
begin
J := 1;
S1[1] := ''; S1[2] := ''; S1[3] := '';
for I := 0 to 15 do
begin
Offset := GetOffset(AbsRow, I);
InSelection := (Offset <= FSelection.EndOffset) and (Offset >= FSelection.StartOffset);
if InSelection then J := 2;
if Offset > FSelection.EndOffset then J := 3;
S1[J] := S1[J] + S[I + 1];
end;
J := 0;
for I := 1 to 3 do
begin
if I = 2 then CharAttr := FColors.SelectionColor
else CharAttr := FColors.CharColor;
DrawStrForChrRow(S1[I], OffRow, J, CharAttr);
J := J + Length(S1[I]);
end;
end else
DrawStrForChrRow(S, OffRow, 0, FColors.CharColor);
end;
procedure TCustomHexEdit.DrawStrForChrRow(S: string; OffRow, Col: Integer; CharAttr: TCharAttr);
var
I, J, X, Y: Integer;
S1: string;
begin
if S = '' then Exit;
X := GetChrAreaLeft + FCharWidth * Col;
Y := OffRow * FCharHeight;
case FDrawCharStyle of
dcGeneral:
for I := 1 to Length(S) do
begin
DrawText(X+FCharWidth*(I-1), Y, S[I], CharAttr);
end;
dcDotForSpec:
for I := 1 to Length(S) do
begin
if IsSpecChar(S[I]) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -