環境 Win2K VC++6.0
以前、メッセージの返送について質問させていただいたのですが、
そのボタンクラスを拡張して
・マウスのLボタン押しっぱなしのときにBN_CLICKを連続で送る(自身と親に)
・マウスのLボタン押しっぱなしのときにマウスポインタがボタン領域から出るか
LボタンUPで終了
としたいのですが、実装方法がわかりません。
SendMessage(WM_COMMAND, BN_CLICKED, (long)GetSafeHwnd());
で自分には送れるのですが親に送れません。また
GetParent()->SendMessage(WM_COMMAND, BN_CLICKED, (long)GetSafeHwnd());
では親側では受け取れないようです。
ご教授くだされば幸いです。
以下コードの一部
void CButton_AutoClick::xxxx()
{ //初期化
DWORD dwParam;
if(0 != ::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &dwParam, 0))
m_dwWaitingTime = dwParam;
if(0 != ::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &dwParam, 0))
m_dwRepeatTime = dwParam;
}
void CButton_AutoClick::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bClicked = true;
SetTimer(1, 250*(m_dwWaitingTime+1), NULL);
CButton::OnLButtonDown(nFlags, point);
}
void CButton_AutoClick::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bClicked = false;
KillTimer(1);
CButton::OnLButtonUp(nFlags, point);
}
void CButton_AutoClick::OnTimer(UINT nIDEvent)
{
switch(nIDEvent)
{
case 1: // ボタンが押され続けている
KillTimer(1);
SetTimer(2, 1000 / (m_dwRepeatTime+2) , NULL);
break;
case 2:
if(m_bClicked == true)
{
//この部分の実装がわかりません
}
else
KillTimer(2);
break;
}
}
マウスのキャプチャと言うキーワードで探してみては?
これって割と常套手段だと思うのですぐ引っかかると思うんですが。
あと、SendMessageを使うよりPostMessageの方が安全ではないかな。
私的にはSendMessageを使う必然が無ければ、PostMessageを使います。
両者の違いを考えるとどうしてなのかわかると思います。
少なくとも私がやっていた実装では、GetParent()->PostMessageで
送れていたと思います。
SendMessageはやってませんのでわかりませんけど。
もしかしてButton側でON_CONTROL_REFLECTしていたりして。
Button側でBN_CLICKEDをON_CONTROL_REFLECTしていたら
親に行かないのは不思議ではないと思いますけれど。
返信ありがとうございます。
マウスのキャプチャですが、
自身のクライアント領域をポインタが離れた場合のメッセージが取りたいのですけど
ボタンクラスでOnMouseMoveをオーバーライドしても取れないようなのでなにかよい
メッセージや方法があれば教えて欲しいです。
>ON_CONTROL_REFLECT
しています。ただマクロはON_CONTROL_REFLECT_EXで親に送るように書き換えています。
この状態でボタンクリックすると自身、親にメッセージが来ますが、
SendMessage(PostMessage)で送った場合、自身にはメッセージが来るのですが親には
来ないようです。
> この状態でボタンクリックすると自身、親にメッセージが来ますが、
> SendMessage(PostMessage)で送った場合、自身にはメッセージが来るのですが親には
> 来ないようです。
WM_COMMANDは、
HIWORD(wParam)が通知コード、LOWORD(wParam)がコントロールIDです。
BN_CLICKEDは0なので、偶然上手く動いているのでしょうけど。
>dairygoods さん
SendMessage(WM_COMMAND, BN_CLICKED, (long)GetSafeHwnd());
を具体的にはどうすればいいのでしょう?今家なので手元でヘルプがみれないので
調べられません(><
マウスをキャプチャできていれば、OnMouseMoveで取れるはずです。
よくやるのはボタンダウンでマウスのキャプチャを開始します。
OnMouseMoveで通知されたポイントがクライアント領域内かを
判定し、領域外に出たらマウスのキャプチャを解除します。
また、ボタンアップでもキャプチャの解除が必要ですね。
MAKEWPARAMというのがあるはずなので調べてみてください。
使い方もHELPを見ればわかると思います。
あと、ネットワークにつなげるのであれば、
マイクロソフトのホームページにいけば、HELPを同様の内容が
参照できますよ。
覚えておいた方がいいです。
http://www.microsoft.com/japan/msdn/library/
MAKEWPARAMで検索し
::PostMessage( ダイアログのhWnd, WM_COMMAND, MAKEWPARAM(ボタンID,BN_CLICKED), ボ
タンのhWnd );
の過去ログを発見し解決いたしました。
なお、マウスのキャプチャのほうですが、SetCapture()は使っていないのですが
void CButton_AutoClick::OnMouseMove(UINT nFlags, CPoint point)
{
CRect r;
GetClientRect(r);
if(PtInRect(r, point) == 0) // 領域外
{
//処理
}
CButton::OnMouseMove(nFlags, point);
}
で出来ました。むしろLBUTTON_UP & DOWNでSetCapture()&ReleaceCapture()した場合
次のボタン(OKボタンなど)を押したときに1回効かない?状態になったりOnClick()
にメッセージが来なくなったり・・・。
自分の環境だけかもしれませんがもしよかったら今後のために解説お願いします。
多分、やり方が間違っていると思います。
ボタンダウンでキャプチャ開始です。
ボタンアップでキャプチャ終了。
あとは、領域外に出た時もキャプチャの終了が必要です。
クリックはボタンアップのタイミングで発生していると思いますが、
ちゃんとデフォルトの処理を呼ぶようにしていますか?
ルートによってデフォルトの処理が呼ばれないパターンがあるのでは?
少なくとも処理のつじつまが合っていれば、言われているような現象は
おきないと思うので書いたコードの方に原因があると思います。