Один щелчок — одно действие; кнопки внизу приведены в порядок

Главное. Каждый щелчок по нашей кнопке срабатывал дважды. Click вызывает
сама LCL при отпускании внутри кнопки — TControl.WMLButtonUp, с той же
проверкой «внутри», какую я написал руками в MouseUp. Мой вызов
оказывался вторым. На кнопке-переключателе это значит «ничего не
произошло»: первое срабатывание меняло состояние, второе возвращало
обратно. Свой вызов убран.

Найдено на невидимом экране: на один щелчок мышью в журнал легли две
записи об одном обработчике, тогда как то же действие с клавиатуры давало
одну. После правки три щелчка дают три переключения, а магнит послушно
меняет цвет туда и обратно.

Второе. Журнал, спрятанный до первого показа окна, не получал своего
виджета вовсе, и вернуть его было нечем: свойство переключалось, а на
экране ничего не менялось. Теперь состояние применяется на показе окна,
когда дескриптор уже есть.

Третье. Правка файла формы не сработала молча — строка не совпала, а я
это не проверил. Кнопка прилипания осталась широкой, с надписью, и
наехала на соседние. Исправлено. Заодно выяснилось, что файл формы
пересобирается только вместе со своим модулем: правки одного лишь lfm в
двоичный файл не попадают.

Значок прилипания переделан в подкову магнита: линия со стрелками смысла
не передавала.

Переключение журнала добавлено в меню «Вид» и на Ctrl+L.
This commit is contained in:
4aiman 2026-08-22 01:40:43 +03:00
commit 41ea1b80de
4 changed files with 59 additions and 30 deletions

View file

@ -1,14 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<!-- Прилипание: два края притягиваются к общей линии.
Линия посередине — граница, к которой прилипает край клипа;
треугольники по бокам показывают притяжение с обеих сторон. -->
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square">
<line x1="12" y1="2" x2="12" y2="22"/>
<line x1="2" y1="6" x2="2" y2="18"/>
<line x1="22" y1="6" x2="22" y2="18"/>
</g>
<g fill="currentColor">
<polygon points="9,12 5,8 5,16"/>
<polygon points="15,12 19,8 19,16"/>
</g>
<!-- Прилипание: подкова магнита. Полюса внизу закрашены сплошным —
так подкова не читается как перевёрнутая буква U. -->
<path d="M5 19 V13 a7 7 0 0 1 14 0 V19" fill="none"
stroke="currentColor" stroke-width="4"/>
<rect x="3" y="18" width="4" height="4" fill="currentColor"/>
<rect x="17" y="18" width="4" height="4" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 755 B

After

Width:  |  Height:  |  Size: 548 B

Before After
Before After

View file

@ -49,11 +49,12 @@ object MainForm: TMainForm
Left = 290
Height = 28
Top = 6
Width = 170
Width = 28
Down = True
Caption = 'Прилипание: вкл'
Icon = tiSnap
OnClick = btnSnapClick
ShowHint = True
TabStop = False
end
object btnRipple: TThemedButton
Left = 326
@ -63,6 +64,7 @@ object MainForm: TMainForm
Icon = tiRipple
OnClick = btnRippleClick
ShowHint = True
TabStop = False
end
object btnRippleMenu: TThemedButton
Left = 356
@ -71,6 +73,7 @@ object MainForm: TMainForm
Width = 22
Arrow = True
OnClick = btnRippleMenuClick
TabStop = False
end
object lblStatus: TLabel
Left = 428

View file

@ -211,6 +211,7 @@ type
procedure JobTimerTick(Sender: TObject);
procedure AdvanceJobBar;
procedure LogButtonClick(Sender: TObject);
procedure MenuToggleLog(Sender: TObject);
procedure ApplyLogVisible(AVisible: Boolean);
procedure BuildTimeline;
procedure StartPlayer;
@ -461,7 +462,6 @@ begin
pnlVideo.Height := FSettings.VideoPanelHeight;
FTimeline.TrackHeight := FSettings.TrackHeight;
FTimeline.WaveGain := FSettings.WaveGain;
ApplyLogVisible(FSettings.LogVisible);
{ Режим схлопывания и его состояние переживают перезапуск. }
if FSettings.RippleAllTracks then
@ -626,6 +626,8 @@ begin
AddItem(MView, 'Вписать весь проект', @MenuZoomFit, ShortCut(VK_0, [ssCtrl]));
AddItem(MView, 'Приблизить', @MenuZoomIn, ShortCut(VK_ADD, [ssCtrl]));
AddItem(MView, 'Отдалить', @MenuZoomOut, ShortCut(VK_SUBTRACT, [ssCtrl]));
AddSep(MView);
AddItem(MView, 'Журнал сообщений', @MenuToggleLog, ShortCut(VK_L, [ssCtrl]));
MProject := AddTop('Проект');
AddItem(MProject, 'Сведения о проекте...', @MenuProjectInfo);
@ -686,6 +688,9 @@ begin
один набор, а не как случайно разбросанные значки. }
FLogButton.SetBounds(LogButtonLeft, 6, LogButtonWidth, 28);
FLogButton.Icon := tiLog;
{ Фокус переключателям не нужен: по ним щёлкают, а обходить их клавишей
Tab при работе с монтажом только мешает. }
FLogButton.TabStop := False;
FLogButton.Down := True;
FLogButton.OnClick := @LogButtonClick;
FLogButton.ShowHint := True;
@ -719,6 +724,11 @@ begin
ApplyLogVisible(not memoLog.Visible);
end;
procedure TMainForm.MenuToggleLog(Sender: TObject);
begin
ApplyLogVisible(not memoLog.Visible);
end;
procedure TMainForm.ApplyLogVisible(AVisible: Boolean);
begin
memoLog.Visible := AVisible;
@ -874,6 +884,19 @@ begin
Exit;
FStarted := True;
{ Журнал прячется здесь, а не при чтении настроек.
Спрятанный до первого показа окна, он не получает своего виджета
вовсе, и вернуть его потом уже нечем: свойство переключается,
а на экране ничего не меняется. Проверено на невидимом экране:
щелчок по кнопке журнала не менял ни пикселя, при том что запись в
журнале показывала Visible=True, высоту 135 и верх 743.
HandleNeeded — на случай, если до этого места дескриптор всё же не
создан: прятать можно только то, что уже существует. }
memoLog.HandleNeeded;
ApplyLogVisible(FSettings.LogVisible);
{ Подложка полосы меню задаётся здесь, а не при создании формы.
Она задаётся через SetMenuInfo по дескриптору меню, а тот появляется

View file

@ -441,13 +441,18 @@ begin
case FIcon of
tiSnap:
begin
{ Средняя линия — граница, к которой прилипает край; по бокам
края, притягивающиеся к ней. }
Line(12, 2, 12, 22);
Line(2, 6, 2, 18);
Line(22, 6, 22, 18);
Tri(9, 5, 12, 4);
Tri(15, 19, 12, 4);
{ Подкова магнита: дуга сверху, две ноги вниз, полюса закрашены.
Без закрашенных полюсов подкова читается как перевёрнутая
буква U и смысла не передаёт. }
Canvas.Pen.Width := Max(2, Side div 6);
Canvas.Brush.Style := bsClear;
{ Дуга по верхней половине окружности с центром в (12,13). }
Canvas.Arc(PX(5), PY(6), PX(19), PY(20), 0, 180 * 16);
Line(5, 13, 5, 19);
Line(19, 13, 19, 19);
Canvas.Pen.Width := 1;
Box(3, 18, 8, 23, True);
Box(16, 18, 21, 23, True);
end;
tiRipple:
begin
@ -651,18 +656,22 @@ end;
procedure TThemedButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
WasPressed: Boolean;
begin
WasPressed := FPressed;
FPressed := False;
Invalidate;
inherited MouseUp(Button, Shift, X, Y);
{ Щелчком считается только отпускание внутри кнопки: увёл курсор в
сторону — значит передумал. }
if WasPressed and (Button = mbLeft) and
PtInRect(ClientRect, Point(X, Y)) then
Click;
{ Click отсюда не вызывается.
Его вызывает сама LCL при отпускании внутри кнопки — TControl.
WMLButtonUp, с той же проверкой «внутри», какая напрашивается здесь.
Написанный руками вызов оказывался вторым, и каждый щелчок срабатывал
дважды. На кнопке-переключателе это значит «ничего не произошло»:
первое срабатывание меняло состояние, второе возвращало обратно.
Найдено на невидимом экране: в журнал легли две записи «обработчик
кнопки журнала вызван» на один щелчок мышью, тогда как то же действие
с клавиатуры давало одну. }
end;
procedure TThemedButton.KeyDown(var Key: Word; Shift: TShiftState);