一括表示

外部アプリケーションからHAMLOGにデータを渡せることを,つい最近知りました.

そこで,
>○ Turbo HAMLOG/Win とのデータのやりとりについて(Ver5.21以上)

> WM_COPYDATA というウインドウメッセージを使って、あなたの作成するアプリケー
>ションからTurbo HAMLOG/Winの入力ウインドウに文字列を送ったり、逆に入力ウイン
>ドウの文字列を得ることができます。

ということで,サンプルプログラムをもとにVB6で作ってみました.
HAMLOGにデータを渡すsub ルーチン(渡す文字列の引数はMessage)で,

cds.dwData = 1 Or THW_ENTER Or THW_FOCUS 'コールサインに文字列を送ってデータを送信後ENTERキーを押し,フォーカスを移す。

Hwnd1 = FindWindow("TThwin", 0)
If Hwnd1 < 1 Then ' ハムログが起動していない
Exit Sub
End If

cbuff = Message ' コールサイン文字列を引数からコピー
cds.cbData = Len(Message)
cds.lpData = Message
X = SendMessage(Hwnd1, WM_COPYDATA, hwnd, cds)

データを送るのはうまくいくのですが,

フォーカス・アクティブが Hamlog(の入力ウィンドウ)に移らず,当然前面に出てきません.

いろいろネットで調べてみるとXP(以上?)では,何やら制限がありそう.
そこで,直接,

X = SetForegroundWindow(Hwnd1)

を記述してみたところ,X の値は 0,すなわち不成功でした.

さらに,おまじないをしてからでないとダメだという記述もあったのですが,もっとシンプルに,VB6の組み込みステートメントの AppActivate を使う方法がありました.

Call AppActivate("Turbo HAMLOG", 0)

引数は,タイトルバーの文字列を渡す必要があるようです.

なんと?この記述で,きちんと制御できるようになりました.

なお,サンプルプログラム中の SendMessageの引数の定義ですが,
Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
lParam As Any) As Long

と,lParam の形式は,Longではなく,Anyでないとエラーになりました.

あと,サンプルプログラム中,

SendMessage(Hwnd1, WM_COPYDATA, hwnd, cds)

は,関数なので,

X = SendMessage(Hwnd1, WM_COPYDATA, hwnd, cds)

と,戻り値を変数で受けないとエラーになりました.

ちなみに,組み込んだプログラムは,HAMLOGを使い出した2年くらい前に,手書きでリストを取っていたのを電子化するのに,HAMLOGにコールサイン・メモというのがあるのも知らなかったこともあって,紙同様にタイムスタンプを付けてログファイルに記録する機能を付けたものです.
テキストボックスそのものの単純なラインエディタの結果を,エンターが押された時に,大文字変換してテキストボックスに戻し,クリップボードにコピーして,リストボックスとタイムスタンプを付けてファイルに書き出すだけの単純なプログラムです.ミスコピーやミスタイプをチェックするためです.

ハムログとのやり取りは,ALT+TABでハムログに切り替えて,ペースト,というものでした.
今回ハムログのAPIが使えることがわかって,API経由でフォーカスの移動+ペースト(+エンター/CTL+エンター)を自動化しようと思った訳です.

ということで,無事できました.

あと,Windowsの仕様なのか,CTL+Enterをテキストボックスで入力すると,KeyDownもKeyPressもKeyUpも,CTL+Enterとして渡ってしまうようですね.

私のプログラムでは,ノートパソコンのキーの位置関係から,
Enterのみだとハムログにデータを渡さない,
CTL+Enterでハムログにデータを渡してエンターを押したのと同等,
Shit+Enterでハムログにデータを渡してCTL+エンターを押したのと同等,
にしたかったのですが,どのタイミングで渡しても,CTL+Enterが働いてしまうので,仕方なくShift+Enterでエンターを押したのと同等にしています.

2014/02/08(Sat) 20:16:43  [No.395]


WM_COPYDATAでVB製のアプリにデータを渡す方法は、私もよくわからない
ところがあります。Basicは苦手でして・・・。
JA2BQX太田さんが詳しいかも。

> CTL+Enterでハムログにデータを渡してエンターを押したのと同等,
> Shit+Enterでハムログにデータを渡してCTL+エンターを押したのと同等,

キーが押されたときのイベントハンドラの中でこんなようなこと使ってます。(C言語で書いた場合)

if (GetKeyState(VK_CONTROL) & 0x8000)
Ctrlキーが押されていた;

if (GetKeyState(VK_SHIFT) & 0x8000)
Shiftキーが押されていた;

2014/02/08(Sat) 23:02:36  [No.396]


こんにちは。

> 外部アプリケーションからHAMLOGにデータを渡せることを,つい最近知りました.

この逆の
HAMLOGにから自作アプリケーションにデータを渡すことも出来ます。
Hamlogからコールサインを受け取りEntity解析をしてHamlogに、そのEntityのCodeを送る...や
WKD/CFM状況を表示するなどの自作ソフトで利用させていただいていました。


> cds.dwData = 1 Or THW_ENTER Or THW_FOCUS 'コールサインに文字列を送ってデータを送信後ENTERキーを押し,フォーカスを移す。
> データを送るのはうまくいくのですが,
> フォーカス・アクティブが Hamlog(の入力ウィンドウ)に移らず,当然前面に出てきません.

こちらではサンプルの記述で上手く動作しています。
下記に一部を抜粋します。

Module1 の中に記述

Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As String
End Type

Public Const THW_ENTER = &H10000 ' データ送信後、ENTERキーを押したのと同じ
Public Const THW_FOCUS = &H20000 ' データ送信後、編集ボックスにフォーカス
Public Const THW_SAVEBOX_ON = &H40000 ' データ保存時、確認MessageBox表示あり
Public Const THW_SAVEBOX_OFF = &H80000 ' データ保存時、確認MessageBox表示なし
Public Const THW_APPLIhWnd = &H100000 ' メインウインドウのハンドルを返す

Public Const WM_COPYDATA = &H4A
Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal wnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As COPYDATASTRUCT) As Long



送るコマンドにて
cmmd = 15 Or THW_ENTER Or THW_FOCUS
cds.dwData = cmmd
cds.cbData = LenB(Trim(cbuff)) / 2 ' 文字列の長さ
cds.lpData = cbuff
hHwnd2 = SendMessage(HamloghWnd, WM_COPYDATA, DX_chk_hwnd, cds)

lRet = SetWindowPos(hHwnd2, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)

2014/02/09(Sun) 08:31:55  [No.397]


太田さん,初めまして.

> HAMLOGにから自作アプリケーションにデータを渡すことも出来ます。
> Hamlogからコールサインを受け取りEntity解析をしてHamlogに、そのEntityのCodeを送る...や
> WKD/CFM状況を表示するなどの自作ソフトで利用させていただいていました。

なるほど,逆も出来るのですね.Hamlogから取得して,何らかに変換して,Hamlogに戻すことが出来るのですね.

> こちらではサンプルの記述で上手く動作しています。
> 下記に一部を抜粋します。
>
> Module1 の中に記述

> Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal wnd As Long, _
> ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As COPYDATASTRUCT) As Long

正しくは,ByRef lParam As COPYDATASTRUCT ですか.
私の場合は,Iparam As Any で動作しちゃいました.

> cmmd = 15 Or THW_ENTER Or THW_FOCUS
> cds.dwData = cmmd
> cds.cbData = LenB(Trim(cbuff)) / 2 ' 文字列の長さ
> cds.lpData = cbuff
> hHwnd2 = SendMessage(HamloghWnd, WM_COPYDATA, DX_chk_hwnd, cds)

ここまでは,THW_FOCUSを除いて,うまくいったのですが...

> lRet = SetWindowPos(hHwnd2, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)

なるほど,こういう手もあるのですね.

それと,ウィンドウのハンドルですが,使用する関数の直近の値を使わないとダメなんですね?
私の場合,SendMessageの後,SetForegroundWindow でやろうとしましたが,対象のウィンドウのハンドルを,最初に取得した,Hwnd1 = FindWindow("TThwin", 0)の値を使っていました.しかし,今やってみたところ,ハンドルを戻り値にしてやっても,うまくいきませんでした(SetForegroundWindow の戻り値が0).

それで,
Call AppActivate("Turbo HAMLOG", 0)
にしてみたら,うまくいったわけです.
うまくいったと思ったら,対象ウィンドウが最小化されている状態ではエラーになることがわかりました.最小化を含め,ハムログが起動されていなければ一連の操作には続かない(最初のハンドルの取得で無ければお終い)わけで,AppActivateで使うのなら,エラー割り込みで,エラーコードと合せて,”最小化されているHamlogを開いて下さい”等のメッセージを出すか,太田さんの方法に変えるか...

サジェッションありがとうございました.

2014/02/09(Sun) 16:29:05  [No.398]