2020年9月10日木曜日

Delphi Fmx Edit+SpinEditButtonで長押しが効かない問題対応

こんにちは、

おひさしぶり。

やましょうです。

Delphi Fmx Edit+SpinEditButtonで長押しが効かない

 久々にWindowsでDelphiのお仕事があったのですが、

仕様書ちょっとボタンの色 が青だったので、いいやFmxでって作って

SpinEdit痛い目にあったので、対応方法含めまとめてみました。

1.VCLでの動作

まずVclで確認です。 

ってVCLでまぁ長押しで連続UP/DOWNはできているのですが、なぜ、押してすぐに±1しないってバグ?というか仕様といかという部分はありますが、動画のように連続UP/DOWNできます。

2.FMXでの確認

FMXで動かすSpinEditButtonのイベントはOnUpClickかOnDownClickしかありません。
しかも、離した時に動作します。
(これでは外から押されたときに処理を開始、
離されたらやめるということもできません。)
以下動画


 変更のタイミング、この長押し(連続押し)対応言われたの
ほぼユーザーの確認が終わって最後の変更時に言われたので超絶焦りました。
ってかC#だと簡単にできているので、Delphiでもできると思い込んでいた(笑)。
(やっぱ事前確認は必要だね。)

2.対応策の検討

ひとつ前の動画をみればわかりますが、現状離されたら処理になっています。
 
こんな感じで処理がされています。

希望のタイミング
押されたとき+1、500ms以上の長押し時 100ms/stepでup/downする。

対応するとこうなります。

ってことでめでたしめでたしでした。

 

 対応コード

FMX.Edit.pasを以下の赤色の部分を追加もしくは変更してください。

  TSpinEditButton = class(TStyledControl, IEditControl)
  strict private
    FUpButton: TCustomButton;
    FDownButton: TCustomButton;
    { Events }
    FOnUpClick: TNotifyEvent;
    FOnDownClick: TNotifyEvent;
    FLongPushTimer: TTimer;
  protected
    { Style }
    procedure ApplyStyle; override;
    procedure FreeStyle; override;
    function GetDefaultStyleLookupName: string; override;
    function GetDefaultSize: TSizeF; override;
    { Events }
//  procedure DoUpButtonClick(Sender: TObject);
//  procedure DoDownButtonClick(Sender: TObject);
    procedure LongPushTimerFired(Sender: TObject);
    procedure DoUpMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    procedure DoDownMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    procedure DoUpMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    procedure DoDownMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);

    { IEditControl }
 

{ TSpinEditButton }

procedure TSpinEditButton.ApplyStyle;
begin
  inherited ApplyStyle;

   FLongPushTimer := TTimer.Create(Self);
   FLongPushTimer.Interval := 100;
   FLongPushTimer.OnTimer  := LongPushTimerFired;
   FLongPushTimer.Enabled  := False;
   FLongPushTimer.Tag      := 0;


  if FindStyleResource<TCustomButton>('upbutton', FUpButton) then
  begin
    FUpButton.TouchTargetExpansion.Bottom := 0;
//    FUpButton.OnClick     := DoUpButtonClick;
    FUpButton.OnMouseDown := DoUpMousedown;
    FUpButton.OnMouseUp   := DoUpMouseUp;

  end;
  if FindStyleResource<TCustomButton>('downbutton', FDownButton) then
  begin
    FDownButton.TouchTargetExpansion.Top := 0;
///     FDownButton.OnClick     := DoDownButtonClick;
    FDownButton.OnMouseDown := DoDownMousedown;
    FDownButton.OnMouseUp   := DoDownMouseUp
;
  end;
end;

procedure TSpinEditButton.LongPushTimerFired(Sender: TObject);
begin
  if( FLongPushTimer.tag = $10) then
  begin {up 方向連続押し}
   if Assigned(FOnUpClick) then
      FOnUpClick(Self);
  end
  else
  if( FLongPushTimer.tag = $20) then
  begin {up 方向連続押し}
   if Assigned(FOnDownClick) then
      FOnDownClick(Self);
  end
  else
  if( FLongPushTimer.tag and $0f <> 0) then
  begin
    FLongPushTimer.tag := Round(FLongPushTimer.tag.ToSingle-1);
  end;
end;


procedure TSpinEditButton.DoUpMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
 FLongPushTimer.Enabled  := true;
 FLongPushTimer.Tag      := $15;
 if Assigned(FOnUpClick) then
    FOnUpClick(Self);
end;

procedure TSpinEditButton.DoDownMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  FLongPushTimer.Enabled  := true;
  FLongPushTimer.Tag      := $25;
  if Assigned(FOnDownClick) then
    FOnDownClick(Self);
end;



procedure TSpinEditButton.DoUpMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  FLongPushTimer.Enabled  := false;
  FLongPushTimer.Tag      := $00;
end;

procedure TSpinEditButton.DoDownMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  FLongPushTimer.Enabled  := false;
  FLongPushTimer.Tag      := $00
end;


procedure TSpinEditButton.FreeStyle;
begin
  if(FUpButton <> nil ) then  FUpButton.OnMouseDown := Nil;
  if(FUpButton <> nil ) then  FUpButton.OnMouseUp   := Nil;
  if(FDownButton <> nil ) then  FDownButton.OnMouseDown := Nil;
  if(FDownButton <> nil ) then  FDownButton.OnMouseUp   := Nil;
  if(FLongPushTimer <> Nil) then FLongPushTimer.DisposeOf();

  if FUpButton <> nil then
    FUpButton.OnClick := nil;
  FUpButton := nil;
  if FDownButton <> nil then
    FDownButton.OnClick := nil;
  FDownButton := nil;

  FOnUpClick  := nil;
  FOnDownClick:= nil;
  inherited FreeStyle;
end;
 

以上

 やましょうでした。


 


2020年7月4日土曜日

Delphiでバイナリーファイルをexe内に内包する方法

こんにちは

やましょうです。

今回は、電子工作+winのexe系のネタです。

Delphiではバイナリーファイルをリソースとして簡単にexe内に内包できます。

 1.プロジェクト=>リソースと画像を選択
追加でファイルを選択
リソースの識別子にuniq名称割り当て(BinData)



 

 2.あとは読むコード追加

var
  RS: TResourceStream;
begin
  RS := TResourceStream.Create(HInstance, 'BinData', RT_RCDATA);
  Rs.Read(Buf,sizeof(Buf));
  RS.DisposeOf;
end;

これだけで、バイナリーデータを読めます。
あとはmbedドライブ見つけてコピーするもよし、
デバッガ起動してロードさせるもよし、
232cでarduinoに送ってもよしです。

以上
やましょうでした。




2020年4月26日日曜日

Kicad 表面/裏面だけ(部品や配線)が見たい。

こんにちは、
やましょうです。

KI-CADで他人の作ったファイルをみるのですが、部品多すぎで、よくわらかんとなったりする。
表面部品だけ、裏面部品だけが知りたいのですが、
画面に表示するときに両面に自動でなる。非常にうざい、本当にうざい。
表面部品(配線込み)、裏面部品(配線込み)をファイル毎に別けるEXEをつくりました。
(塗り潰しは対応していません。)


...のところを押してファイルを指定してください。
 ダウンロードはここから拾ってください。
指定したファイル名の.Kicad_pcbから
例:


表面部品ファイル:指定したファイル名_Front.Kicad_pcb
 

裏面部品ファイル:指定したファイル名_Rear.Kicad_pcb

という2つのファイルに分離します。


ということでやましょうでした。


2020年3月18日水曜日

秋月製 STM32F303K8 使用マイコンボードの使用例

こんにちは、 STM32の本を前書きしか書いていない。
やましょうです。

2020/3/4に突如して秋月電子通商さんから発売された
STM32F303K8使用マイコンボードの使用方法についてレポートしていきたいと思います。

まず、外見みて思うのなんでデバッグポートを14PINにしたの。。。ってことです。


ARM系のマイコンは最近10PIN 5x2の1.27mmピッチですよね。
ってことで右端の2本、と左端の2本を曲げます。


そしてデバッガをつなげて完成です。

これで動きました。






2020年2月18日火曜日

Windowsで作成したフォルダー、データファイル、更新ファイルだけ消える事件の対応

こんにちは、システム移行中のやましょうです。

実は、私の環境あまりにも開発ツールが多すぎてシステムディスクを入れ替えで
現在、移行中なのですが、お客様の要望で一端、古いシステムディスクに戻す場合があります。
その時に別のシステムで作成したファイルが全部消える事件が発生したので、
その経緯および対応をまとめておきます。

図解:

旧SYSTEM-SSD(a-system)           ---------   データDISK ここにデータは保存.
WINDOWS-10.          D:ドライブ
SSD C:ドライブ


新SYSTEM-SSD(b-system).              ---------   データDISK ここにデータは保存.
WINDOWS-10.                              D:ドライブ
SSD C:ドライブ


すべてデータはDドライブに保存していたのです。

新システム、もしくは、旧システムで起動SSDを変更した際に
以前のシステムで作成したDドライブのファイルやフォルダーが消える事件が発生しました。

旧SYSTEM-SSD(a-system)              ---------   データDISK ここにデータは保存.
WINDOWS-10.          D:ドライブ
SSD C:ドライブ           ここにWORKFOLDERをつくりファイルA.Cをつくります。

その後、システムSSDのSATAを入れ替えて。
新SYSTEM-SSD(b-system). で起動
そして旧SYSTEM-SSD(a-system)に戻ります。

すると
旧SYSTEM-SSD.              ---------   データDISK ここにデータは保存.
WINDOWS-10.          D:ドライブ
SSD C:ドライブ           WORKFOLDERふくめファイルA.Cがない。

ちなみに本当は約1ヶ月分の作業ファイル全部無くなっていました。
(バックアップは大切だね。バックアップからは無事復旧したから良いけど面倒だよね)

当初はMSさんがファイル監視を。。。なんて思ったりしたのですが、
MSさんがそんなことするはずない。と思い、いろいろ調べたところ。
下記のファイルが原因っぽい?思われる事がわかりました。

それは
”Chromeクリーンアップ”
そうです。両方のシステムにChromeを入れていたのです。

ここからは私の想像、
新SYSTEM-SSD(b-system)SSDに入っているクリーンアップが、
旧SYSTEM-SSD(a-system)SSD起動した際に作成したファイルをリストと比較し、増えているファイルや変更ファイルを不審なファイルとして認識し、問答無用で消すってことなのかな?とおもっています。(拡張子みているっぽくpstファイルは無事)
詳細は面倒なので調査していないです。

そして、私の行った解決策、
”Chromeクリーンアップ”の停止でした。

方法は下記にありました。
https://1-notes.com/windows10-software-reporter-tool/

そしてクリーンアップを停止してからファイルが消える事件は発生していません。
ファイルやフォルダーが消えたら、上記の対応を試してみてください。

以上
やましょうした。