From 3d557036f953229cb4db9dc22a46c916b96fcf41 Mon Sep 17 00:00:00 2001 From: Mike Brashler Date: Mon, 15 Jan 2024 16:26:57 -0800 Subject: [PATCH] CW Speed can be editted using keyboard and updated with Enter or move focus to another field. Two conditions were fixed: - when CW Speed control has focus, user can edit. However, some values are invalid for MR. To fix this, CWSpeedDirty flag was added to all deferred validation. - When CW Speed control has focus, user can hit Enter key or a function key to send the next message. This action was not setting the final CW Speed value.` --- Main.dfm | 1 + Main.pas | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/Main.dfm b/Main.dfm index 02cb8d4..ac9b96e 100644 --- a/Main.dfm +++ b/Main.dfm @@ -790,6 +790,7 @@ object MainForm: TMainForm TabOrder = 2 Value = 25 OnChange = SpinEdit1Change + OnExit = SpinEdit1Exit end object CheckBox1: TCheckBox Left = 140 diff --git a/Main.pas b/Main.pas index 56d2393..6bb2d0c 100644 --- a/Main.pas +++ b/Main.pas @@ -350,10 +350,12 @@ TMainForm = class(TForm) procedure SimContestComboPopulate; procedure ExchangeEditExit(Sender: TObject); procedure Edit4Exit(Sender: TObject); + procedure SpinEdit1Exit(Sender: TObject); private - MustAdvance: boolean; + MustAdvance: boolean; // Controls when Exchange fields advance UserCallsignDirty: boolean; // SetMyCall is called after callsign edits + CWSpeedDirty: boolean; // SetWpm is called after CW Speed edits function CreateContest(AContestId : TSimContest) : TContest; procedure ConfigureExchangeFields; procedure SetMyExch1(const AExchType: TExchange1Type; const Avalue: string); @@ -532,8 +534,16 @@ procedure TMainForm.SendClick(Sender: TObject); end; +{ + SendMsg() is called whenever MyStation sends a new CW Message. +} procedure TMainForm.SendMsg(AMsg: TStationMessage); begin + // special case for CW Speed control having focus and user presses + // a key or function key (which do not cause a leave-focus event). + if SpinEdit1.Focused then + SpinEdit1Exit(SpinEdit1); + if AMsg = msgHisCall then begin // retain current callsign, including ''. if empty, return. Tst.Me.HisCall := Edit1.Text; @@ -707,9 +717,7 @@ procedure TMainForm.FormKeyPress(Sender: TObject; var Key: Char); end; ' ': // advance to next exchange field - if (ActiveControl = Edit1) or - (ActiveControl = Edit2) or - (ActiveControl = Edit3) then + if ActiveControl <> ExchangeEdit then ProcessSpace else Exit; @@ -788,6 +796,16 @@ procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word; end; +{ + Advance cursor to next exchange field. This procedure is called whenever + the Spacebar is pressed. Its purpose is to move the cursor to the next + Exchange field. + + If the current contest has an RST field: + - the RST field value is set if currently empty + - the RST field is skipped (cursor is moved to the third exchange field). + Note that TAB key will select the middle digit of the RST field. +} procedure TMainForm.ProcessSpace; begin MustAdvance := false; @@ -825,20 +843,39 @@ procedure TMainForm.ProcessSpace; end; +{ + Called when the Enter key is pressed. + In setup-mode: + - passes Enter key to either the Exchange setup field or callsign field. + In Run-mode: + - moves the cursor between QSO exchange fields following the QSO state. + - if either CW Speed and Active Spin Controls are active, cursor is moved + to the appropriate QSO exchange field. + - for some contests, the status bar is updated with Dx Station information. +} procedure TMainForm.ProcessEnter; var C, N, R, Q: boolean; begin if ActiveControl = ExchangeEdit then begin + // exit Exchange field ExchangeEditExit(ActiveControl); Exit; end; if ActiveControl = Edit4 then begin + // exit callsign field Edit4Exit(ActiveControl); Exit; end; + if ActiveControl = SpinEdit1 then + begin + // exit CW Speed Control + SpinEdit1Exit(ActiveControl); + if RunMode = rmStop then + Exit; + end; MustAdvance := false; if (GetKeyState(VK_CONTROL) or GetKeyState(VK_SHIFT) or GetKeyState(VK_MENU)) < 0 then @@ -857,6 +894,11 @@ procedure TMainForm.ProcessEnter; if Edit1.Text = '' then begin SendMsg(msgCq); + // special case - Cursor is in either CW Speed or Activity Spin Control + // when Enter key is pushed. Move cursor to the next QSO Exchange field. + if (RunMode <> rmStop) and + ((ActiveControl = SpinEdit1) or (ActiveControl = SpinEdit3)) then + MustAdvance := true; Exit; end; @@ -1348,7 +1390,25 @@ procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); procedure TMainForm.SpinEdit1Change(Sender: TObject); begin - SetWpm(SpinEdit1.Value); + if SpinEdit1.Focused then + begin + // CW Speed edit has occurred while focus is within the spin edit control. + // Mark this value as dirty and defer the call to SetWpm until edit is + // completed by user. + CWSpeedDirty := True + end + else + SetWpm(SpinEdit1.Value); +end; + +{ + Called when user leaves CW Speed Control or user presses Enter key. +} +procedure TMainForm.SpinEdit1Exit(Sender: TObject); +begin + // call SetWpm if the CW Speed has been edited + if CWSpeedDirty then + SetWpm(SpinEdit1.Value); end; procedure TMainForm.CheckBox1Click(Sender: TObject); @@ -1902,7 +1962,8 @@ procedure TMainForm.Advance; if Edit2IsRST and (Edit2.Text = '') then Edit2.Text := '599'; - if Pos('?', Edit1.Text) > 0 then + if (Edit1.Text = '') or + (Pos('?', Edit1.Text) > 0) then begin { stay in callsign field if callsign has a '?' } if ActiveControl = Edit1 then @@ -2033,6 +2094,8 @@ procedure TMainForm.SetWpm(AWpm : integer); Wpm := Max(10, Min(120, AWpm)); SpinEdit1.Value := Wpm; Tst.Me.SetWpm(Wpm); + + CWSpeedDirty := False; end;