Bricscad V19 MouseMove 1.09 2019/01/09
2019/01/09 根本的な不具合(コマンドラインの文字列取得)を修正 (Ver.1.09)
2019/01/07 終了処理を修正 (Ver.1.07)
2019/01/06 終了処理を修正 (Ver.1.06)
2019/01/06 2 重起動の防止を追加、終了処理を修正 (Ver.1.01)
マウス移動により [Enter] を発行、コマンド入力待ちの時、IME をオフにするツールです。Bricscad V19 専用です。
OneKey2,3 の不具合が特定できなかったので、新たに作り直しました。エラー除けの小細工、キーボードフックは削除しました。
コマンド入力中は右上方向のみ、コマンドオプション入力中は全方向のマウス移動で [Enter] を発行します。
コマンドオプション文字が優先され、一時オブジェクトスナップの省略文字に合う場合は、一時Oスナップに置き換え、[Enter] を発行します。
それ以外では、何もしません。
※入力文字は、大文字・小文字を問いません。
■一時オブジェクトスナップの省略文字 (OneKey と同じ)
M, MI, MD, MM : mid (中点)
C, CE, CN, CC : cen (中心)
Q, QU, QA, QQ : qua (四半円点)
I, IT, I I : int (交点)
E, EN, ED, EE : end(端点)
T, TA, TN, TT : tan (接線)
N, NE, NA : nea (近接点)
P, PE, PR, PP : per (垂線)
S, IN, IS : ins (挿入基点)
O, D, ND : nod (点)
NN, NO : non (解除)
V, M2, MT, MP, MMM : m2p (2点間中点)
EX, ET : ext (延長)
F, FR, FM : from (基点設定)
A, AP : app (仮想交点)
PA : par (平行)
X, XX : [ESC]キー
G, GC : gce (図心)
※コマンドオプションが優先されます。
■著作権、免責事項等
・本ツールの著作権は、作者 f.izawa が所有し、これを主張します。
・本ツールを使用したことによる事故、損害等の一切について作者はその責を負いません。
■開発環境
・Delphi 10.2.3 Tokyo Community Edition
・Bricscad V19 Pro
・Windows 10 64bit
■作者連絡先
e-mail: f.izawa@dream.com
URL: http://www.izawa-web.com/
■ダウンロード
・BC19MMV.zip (Ver.1.09 EXE 本体のみ)
・BcadCtrl19.zip (ソースコード 2019/01/09 BcadCtrl19.pas ※実行には不要です)
■ソースコード
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, BcadCtrl19, Vcl.StdCtrls, Vcl.ExtCtrls, IMM, IniFiles; type TForm1 = class(TForm) Timer1: TTimer; Edit6: TEdit; CheckBox1: TCheckBox; CheckBox2: TCheckBox; procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); private { Private 宣言 } public { Public 宣言 } // 基準カーソル位置とマウス移動の判断の閾値 curX, curY, dXY : integer; // Bricscad が起動中 ON bcadFlag : boolean; end; var Form1: TForm1; implementation {$R *.dfm} procedure HwndSendKeys(h: HWND; const keystr: string); { Hwnd をアクティブにして、Keyを押す} var i : integer; s: string; begin if IsWindowEnabled(h) then begin SetForegroundWindow(h); s := UpperCase(keystr); for i := 1 to Length(s) do begin keybd_event(Byte(s[i]), 0, 0, 0); keybd_event(Byte(s[i]), 0, KEYEVENTF_KEYUP, 0); Sleep(1); end; end; end; function makeObjectSnapStr(const cmdo: string; const optstr: string): string; begin result := ''; // オプションリストに存在 if (optstr = '') or (cmdo.IndexOf(',' + optstr + ',') < 0) then begin // 一時オブジェクトスナップ // 中点:MID if optstr = 'M' then result := 'id' + #13 else if optstr = 'MI' then result := 'd' + #13 else if optstr = 'MD' then result := #08 + 'id' + #13 else if optstr = 'MM' then result := #08 + 'id' + #13 // 中心:CEN else if optstr = 'C' then result := 'en' + #13 else if optstr = 'CE' then result := 'n' + #13 else if optstr = 'CN' then result := #08+'en' + #13 else if optstr = 'CC' then result := #08+'en' + #13 // 四半円点:QUA else if optstr = 'Q' then result := 'ua' + #13 else if optstr = 'QU' then result := 'a' + #13 else if optstr = 'QA' then result := #08 + 'ua' + #13 else if optstr = 'QQ' then result := #08 + 'ua' + #13 // 端点:END else if optstr = 'E' then result := 'nd' + #13 else if optstr = 'EN' then result := 'd' + #13 else if optstr = 'ED' then result := #08 + 'nd' + #13 else if optstr = 'EE' then result := #08 + 'nd' + #13 // 交点:INT else if optstr = 'I' then result := 'nt' + #13 else if optstr = 'IT' then result := #08 + 'nt' + #13 else if optstr = 'II' then result := #08 + 'nt' + #13 // 接線:TAN else if optstr = 'T' then result := 'an' + #13 else if optstr = 'TA' then result := 'n' + #13 else if optstr = 'TN' then result := #08 + 'an' + #13 else if optstr = 'TT' then result := #08 + 'an' + #13 // 近接点:NEA else if optstr = 'N' then result := 'ea' + #13 else if optstr = 'NE' then result := 'a' + #13 else if optstr = 'NA' then result := #08 + 'ea' + #13 // 垂線:PER else if optstr = 'P' then result := 'er' + #13 else if optstr = 'PE' then result := 'r' + #13 else if optstr = 'PR' then result := #08 + 'er' + #13 else if optstr = 'PP' then result := #08 + 'er' + #13 // 挿入基点:INS else if optstr = 'S' then result := #08 + 'ins' + #13 else if optstr = 'IS' then result := #08 + 'ns' + #13 else if optstr = 'IN' then result := 's' + #13 // 点:NOD else if optstr = 'D' then result := #08 + 'nod' + #13 else if optstr = 'O' then result := #08 + 'nod' + #13 else if optstr = 'ND' then result := #08 + 'od' + #13 // 解除:NON else if optstr = 'NN' then result := #08 + 'on' + #13 else if optstr = 'NO' then result := 'n' + #13 // 2点間中点:M2P else if optstr = 'V' then result := #08 + 'm2p' + #13 else if optstr = 'MT' then result := #08 + 'tp' + #13 else if optstr = 'M2' then result := #08 + '2p' + #13 else if optstr = 'MP' then result := #08 + '2p' + #13 else if optstr = 'MMM' then result := #08#08 + '2p' + #13 // 延長:EXT //else if optstr = 'E' then result := 'xt' + #13 else if optstr = 'EX' then result := 't' + #13 else if optstr = 'ET' then result := #08 + 'xt' + #13 // 基点設定:FROM else if optstr = 'F' then result := 'rom' + #13 else if optstr = 'FR' then result := 'om' + #13 else if optstr = 'FM' then result := #08 + 'rom' + #13 // 仮想交点:APP else if optstr = 'A' then result := 'pp' + #13 else if optstr = 'AP' then result := 'p' + #13 // 平行:PAR else if optstr = 'PA' then result := 'r' + #13 //else if optstr = 'PR' then result := #08 + 'ar' + #13 // [ESC] else if optstr = 'X' then result := #27 else if optstr = 'XX' then result := #27 // 図心 : GCE else if optstr = 'G' then result := 'ce'+#13 else if optstr = 'GC' then result := 'e'+#13; end; end; function makeCmdOptionList(const cmds: string): string; var n, m : integer; s, s2 : string; begin result := ''; s := cmds; if (s.IndexOf('(') > 0) and (s.IndexOf(')') > 0) then begin m := Pos('[', s); n := Pos(']', s); if (m > 0) and (n > m) then s := Copy(s, m + 1, n-m-1); if s <> '' then begin while True do begin m := Pos('(', s); n := Pos(')', s); if (m > 0) and (n > m) then begin s2 := Copy(s, m + 1, n - m -1); if (s2.Length > 0) and (s2.Length <= 5) then result := result + s2 + ','; Delete(s, 1, n); end else break; end; end; end else if (s.IndexOf('選択:') > 0) then begin result := 'W,L,C,BOX,ALL,F,WP,CP,G,CL,A,R,M,P,U,AU,SI,'; end; // OPT の始まりと終わりは、','で囲まれている状態にする if result <> '' then result := ',' + result; end; procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var ini : TIniFile; begin ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); try ini.WriteInteger('OneKey', 'MouseMove', dXY); ini.WriteBool('OneKey','ImeOff', CheckBox1.Checked); ini.WriteBool('OneKey','OneKey', CheckBox2.Checked); finally ini.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); var ini : TIniFile; begin Edit6.Text := ''; dXY := 40; // スクリーンの右下隅に表示 Left := Screen.Width - Width - 10; Top := Screen.Height - Height - 130; ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini')); try dXY := ini.ReadInteger('OneKey','MouseMove', dXY); CheckBox1.Checked := ini.ReadBool('OneKey','ImeOff', True); CheckBox2.Checked := ini.ReadBool('OneKey','OneKey', True); finally ini.Free; end; end; procedure TForm1.Timer1Timer(Sender: TObject); var PT: TPoint; cmdline, cmdstr, cmdopt, optstr, kbstr : string; n : integer; dX, dY :double; optFlag, cmdFlag : boolean; IME : HWND; termFlag : boolean; begin termFlag := False; Timer1.Enabled := False; try cmdline := GetBcadCmdLine; except cmdline := ''; Caption := 'ERR1'; end; // IME Off if CheckBox1.Checked and (cmdLine = ': ') then begin IME := ImmGetDefaultIMEWnd(BcadCmdLineHandle); if IME <> 0 then begin // ON であれば OFF にする if Boolean(SendMessage(IME, WM_IME_CONTROL, $0005, 0)) then SendMessage(IME, WM_IME_CONTROL, $0006, 0); end; end; // MouseMove if CheckBox2.Checked and IsWindowEnabled(BcadMainWinHandle) and GetCursorPos(PT) then begin // 前回との偏差(CAD 座標と同じ方向) dx := PT.X -curX; dy := curY -PT.Y; Edit6.Text := dX.ToString + ',' + dY.ToString; // コマンドオプションリスト cmdopt := makeCmdOptionList(cmdline); n := LastDelimiter(':', cmdline); // コマンド入力中 if n = 1 then cmdstr := Trim(Copy(cmdline, 2)) // コマンドオプション待ち else if n > 1 then optstr := Trim(Copy(cmdline, n + 1)) else optstr := ''; // コマンド入力中 cmdFlag := cmdstr <> ''; // コマンドオプション入力中 if optstr <> '' then begin optstr := UpperCase(optStr); // オプションリストに存在 optFlag := Pos(',' + optStr + ',', cmdopt) > 0; end else optFlag := False; // コマンド入力中は、右上方向のみ if cmdFlag and (dX > dXY) and (dY > dXY) then begin HwndSendKeys(BcadMainWinHandle, #13); Sleep(500); end // オプションの場合は全方向 else if optFlag and (abs(dX) > dXY) and (abs(dY) > dXY) then begin HwndSendKeys(BcadMainWinHandle, #13); Sleep(500); end // 一時オブジェクトスナップに変換できる時は、全方向 else if (optstr <> '') and (abs(dX) > dXY) and (abs(dY) > dXY) then begin kbstr := makeObjectSnapStr('', optstr); if kbstr <> '' then begin HwndSendKeys(BcadMainWinHandle, kbstr); Sleep(500); end; end; // 基準座標を更新 curX := PT.X; curY := PT.Y; end; // 追従して終了 if not bcadflag then begin if IsWindow(BcadMainWinHandle) then begin bcadflag := True; SetForegroundWindow(BcadMainWinHandle); end; end else begin if not IsWindow(BcadMainWinHandle) then begin termFlag := True; Close; end; end; if not termFlag then Timer1.Enabled := True; end; end.