Bricscad V17 IME Off (2016/12/24-2017/08/19)

 2017/08/19
  Bricscadに追従して終了する時に、エラーが出て終了できないことがあるのを対策しました。

 2017/01/30
  監視状態が分かるようにランプを付けました。

 2017/01/29
  IME 停止の条件に、IsWindowEnabled(hWndMain) を追加しました。
  「IME Off Auto」 のチェックボックスを追加しました。

■コマンドラインの文字列が、": " の時、IME を OFF にします。(V13 では動きません)
 Bricscad の Support フォルダに、on_start.lsp をメモ帳などで作成(すでにある場合は、下記一行を追加)すると、自動で起動されます。
 (startapp "C:\\xxxx\\yyyy\\Bcad17ImeOff.exe")
 フォルダ(パス)の区切りは、\\ です。
 Bricscad が終了すると、追従して終了します。
 
 ※プロパティーウィンドウには、対応していません。「IME Off Auto」 のチェックを外して下さい。



■ダウンロード
 Bcad17ImeOff.zip (EXE本体のみ)


unit BcadImeOffUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Imm;

type
  TForm3 = class(TForm)
    Timer1: TTimer;
    Edit1: TEdit;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form3: TForm3;

  // BcadV17 が見つかるとON
  bRunFlag : boolean;

implementation

{$R *.dfm}

//******************************************
// 他のプロセス内のコントロールの文字列を得る
//******************************************
function GetWindowString(h : HWND) : string;
var
  p : PChar;
  len : LongInt;
begin
  result := '';
  //ウィンドウの文字列のバイト数を取得
  //終端のNULL文字を含まない文字列の長さ(バイト数)
  len := SendMessage(h, WM_GETTEXTLENGTH, 0, 0);

  if len > 0 then begin
    //終端のNULL文字を含むサイズを確保
    GetMem(p, (len + 1) * 2);
    //格納するバッファの最大サイズ(終端のNULL文字を含む長さ)
    //文字列バッファ
    SendMessage(h, WM_GETTEXT, (len + 1) * 2, LongInt(p));
    //文字列がバッファサイズより長いとき、後部がカットされる
    result := string(p);
    FreeMem(p);
  end;
end;

function BcadActive: boolean;
var
  h : HWND;
begin
  result := False;
  h := FindWindow('BricscadMainWindow', nil);
  if IsWindow(h) then begin
    SetForegroundWindow(h);
    result := True;
  end;
end;

function GetBcadCmdLineWindow: HWND;
var
  h, hMain : HWND;
  hCmdBar  : HWND;
  hCmdLine : HWND;
  i : integer;
begin
  hMain := FindWindow('BricscadMainWindow', nil);
  // 子ウィンドウを探す
  hCmdBar := FindWindowEx(hMain, 0, nil, 'コマンドライン');
  h := hCmdBar;
  for i := 1 to 4 do h := GetWindow(h, GW_CHILD);
  // コマンドライン
  hCmdLine := GetWindow(h, GW_HWNDNEXT);
  if hCmdLine = 0 then begin
    // トップレベルのウィンドウを探す
    hCmdBar := FindWindow(nil, 'コマンドライン');
    h := hCmdBar;
    for i := 1 to 5 do h := GetWindow(h, GW_CHILD);
    // コマンドライン
    hCmdLine := GetWindow(h, GW_HWNDNEXT);
  end;
  result := hCmdLine;
end;

function GetBcadCmdLineText: string;
var
  hCmdLine : HWND;
begin
  hCmdLine := GetBcadCmdLineWindow;
  result := GetWindowString(hCmdLine);
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  // スクリーンの右下隅に表示
  Left := Screen.Width - Width - 10;
  Top := Screen.Height - Height - 70;
end;

procedure TForm3.Timer1Timer(Sender: TObject);
var
  hWndMain : HWND;
  hCmdLine : HWND;
  IME: HWND; // uses Imm
  s : string;
begin
  hWndMain := FindWindow('BricscadMainWindow', nil);
  if IsWindow(hWndMain) then begin
    if not bRunFlag then
      bRunFlag := True;
    // コマンドラインウィンドウ
    hCmdLine := GetBcadCmdLineWindow;
    if IsWindowEnabled(hWndMain) and IsWindowEnabled(hCmdLine) then begin
      // コマンド文字列
      s := GetWindowString(hCmdLine);
      Edit1.Text := s;
      if s = ': ' then begin
        IME := ImmGetDefaultIMEWnd(hCmdLine);
        // ONであればOFFにする
        if Boolean(SendMessage(IME, WM_IME_CONTROL, $0005, 0)) then begin
           SendMessage(IME, WM_IME_CONTROL, $0006, 0);
        end;
      end;
    end;
  end
  else begin
    // 終了
    if bRunFlag then Close;
  end;
end;

end.