デフォルトボタンの判別方法

[戻る]
める 2007/06/12(火) 19:41:41
またまたお世話になります。

ボタンを押すと点線(フォーカス)と
影(デフォルトボタンの意?)がボタンに付きますが、
この「影」があるボタンがどれか?と言うのを判別
するにはどのようにすれば良いのでしょうか?
判別により、GotoDlgCtrl()で移動するボタンを
決定したいのですが・・・

自分で調べて当たりが付いたのがCDialog::GetDefID()
と言う関数なのですが・・・
---------------------------------------------------------
<<MSDN一部引用>>
デフォルトのプッシュ ボタンが ID 値を持つ場合は、
上位ワードに DC_HASDEFID を、下位ワードに ID 値を設定します。
---------------------------------------------------------
実行すると、0x534b0001となり下位ワードが0001となってます。
実際に影がついているボタンのIDは1024なので、基本的な部分が
間違っていると思うのですが、解決方法がわかりません。

その他関係するんじゃないかと思えるところだと・・・
現在VC6SP5、MFC、Win2Kでダイアログベースで組んでますが、
最初から付いてるボタン(「OK」ボタンと「キャンセル」ボタン)は
削除しており、CDialog::OnOK()とCDialog::OnCancel()は
コメントアウトにしてあります。

ちょっと文章が支離滅裂気味ですが、宜しくお願い致します。

subaru 2007/06/12(火) 20:51:58
スタイルにBS_DEFPUSHBUTTONを含むボタンが
そうではないかと思います。

める 2007/06/12(火) 20:55:18
>>subaruさん
レスありがとうございます。

BS_DEFPUSHBUTTONって所謂プロパティで
「標準のボタン」の事ですよね?
現在作成している画面上のどのボタンにも
そのチェックは付いていません。

subaru 2007/06/12(火) 21:17:52
>BS_DEFPUSHBUTTONって所謂プロパティで
>「標準のボタン」の事ですよね?
標準のボタンだとDEFPUSHBUTTONで定義されませんか?
BS_DEFPUSHBUTTONは実行時に自動的に設定されます。

める 2007/06/12(火) 21:24:20
>BS_DEFPUSHBUTTONは実行時に自動的に設定されます。

これはダイアログベースのプロジェクトを最初に
開いた際にある「OKボタン」にはついてますが、
私は↑にも書いた通りボタンを削除しました。

それでも内部的には残ってたりするものなんでしょうか?

ITO 2007/06/12(火) 21:49:16
> BS_DEFPUSHBUTTONって所謂プロパティで
>「標準のボタン」の事ですよね?
> 現在作成している画面上のどのボタンにも
> そのチェックは付いていません。

そのチェックを付ければ「デフォルトのプッシュ ボタン」なると思います。
subaruさんもそう言いたいのだと思います。

subaru 2007/06/12(火) 22:16:37
えと、標準のボタンは関係ないです。
各ボタンのスタイルを調べてみればわかると思いますが
ボタンが影付きになったときにBS_DEFPUSHBUTTONが自動的に設定されるのです。
逆にBS_DEFPUSHBUTTONを設定してやることで1つのダイアログ内で
複数のボタンを影付きにすることもできます。

める 2007/06/13(水) 00:20:37
遅くなりました。
ちと整理しますが、

>ボタンが影付きになったときにBS_DEFPUSHBUTTONが自動的に設定されるのです。

と、言うことは・・・
例えばボタンA、B、Cがあったとして、
Aを押した場合、AにBS_DEFPUSHBUTTONが設定されると言う
認識で宜しいですか?

それならば、私が知りたいのはどうすれば
AにBS_DEFPUSHBUTTONが設定されている事を知るか?
という事なんですが・・・。

如何でしょうか?

subaru 2007/06/13(水) 09:49:33
>Aを押した場合、AにBS_DEFPUSHBUTTONが設定されると言う
>認識で宜しいですか?
普通はフォーカスが移動するだけで影が設定されたり消えたりするみたいですけど。

>それならば、私が知りたいのはどうすれば
>AにBS_DEFPUSHBUTTONが設定されている事を知るか?
>という事なんですが・・・。
スタイルはボタンのGetStyle()が返す値に&演算子を適用すれば取り出せます。

そもそもなぜこんなことをしたいのかわからないのですが、
もしかして何かボタンを押した後で他のコントロールにSetFocus()して
影だけが残ってしまうってことなんでしょうか?
影が気になるならModifyStyle()で消すこともできますよ。

める 2007/06/13(水) 09:49:57
こちらにも質問投げさせて頂きました。
解決の際は双方に書き込みさせて頂きます。

http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?new

宜しくお願い致します。

ITO 2007/06/13(水) 10:07:41
>こちらにも質問投げさせて頂きました。
まずぬるさんがやりたいことを整理して質問をしないと他のところに
投げても同じだと思います。
「CButton::GetButtonStyle」を調べてみたらどうでしょうか。

める 2007/06/13(水) 10:26:51
レスありがとうございます。
あぅ。マルチさせて貰った瞬間に書き込まれてる事が判明orz。

>スタイルはボタンのGetStyle()が返す値に&演算子を適用すれば取り出せます。
試したのですが、戻り値が0のままなんですよ。

>そもそもなぜこんなことをしたいのかわからないのですが、
ちょっと文章上では、うまく説明が出来ないのですが、
GUIの構成上コントロール数が多い&条件によるコントロールの
有効・無効が多いので、ある自作の関数を呼ぶことで一元して管理しているのです。
処理をする度にこの関数を呼ぶため、フォーカス(及び影)を強制的に特定のボタン
に移してしまうと、スムーズな動作にならないので今回の質問に至った訳です。

またその管理している関数内でも、ボタンの状態に応じてフォーカスの移動を
したいのです・・・って作りが悪いんですかねぇ・・・orz。

>もしかして何かボタンを押した後で他のコントロールにSetFocus()して
>影だけが残ってしまうってことなんでしょうか?
明示的にSetFocus()を呼んでいる訳ではありませんが、
結果的にそういうことになってしまっている・・・のだと思います。
実際影は残ったままで他のコントロール(ラジオボタン等)は
使えるので。。

>影が気になるならModifyStyle()で消すこともできますよ。
「影を消す」=デフォルトボタン解除って事でいいのかな・・・
ちょっとやってみます。

める 2007/06/13(水) 10:30:22
>>スタイルはボタンのGetStyle()が返す値に&演算子を適用すれば取り出せます。
>試したのですが、戻り値が0のままなんですよ。

あ。嘘です。ごめんなさい。
試したのはGetDefID()でその戻り値が0でした。
今から、GetStyle()とModifyStyle()を試してみます。

める 2007/06/13(水) 11:16:43
[[解決]]
もうちょっと端的にまとめてみました。
@対象Aと対象Bをラジオボタンで表示を切り替えます。
 違いは表示内容のみで、ボタン等は同じ物を流用。
 表示内容の条件に応じて『コントロールの有効・無効も
 切り替わる』。

Aファイル削除ボタン押下で削除対象が無くなると『無効化』
 にして『ファイル追加ボタンにフォーカス&影を移動』。

この『』の部分を同一の関数でやりたい。最初にAの場合、
GotoDlgCtrl()で追加ボタンにフォーカス&影を飛ばしました。
その後@のラジオボタンで切り替えた瞬間に追加ボタンに
フォーカスがいってしまう(当たり前ですが)

// 『ファイル削除』ボタンの有効/無効
if (m_SendFileList.GetCount() > 0)
{
 GetDlgItem(IDC_BTN_DEL)->EnableWindow(TRUE);
}
else
{
 // ファイル数0
 GetDlgItem(IDC_BTN_DEL)->EnableWindow(FALSE);

  GotoDlgCtrl(IDC_BTN_ADD)・・・←問答無用で飛んでしまうので×
-----------------------------------------------------------
 "☆"
    ここにファイル削除ボタンがデフォルトボタンだったら、
  ファイル追加ボタンにフォーカスをセット。と書きたい。
-----------------------------------------------------------
}
で、"☆"の部分に下記のソースを入れたら動きました!!!

DWORD aaa = GetDlgItem(IDC_BTN_DEL)->GetStyle();
if ((aaa & BS_DEFPUSHBUTTON) != 0){
 GotoDlgCtrl(GetDlgItem(IDC_BTN_ADD));
}
これでいいんでしょうか??

今回のようなパターンって多々あると思うのですが、
コントロール有効無効の制御を一元管理するってのは
作り的にはあまり良くないのでしょうか・・・?

私のやりたかった事と出来た事ってこれで伝わりました
でしょうか?
subaruさん、ITOさん長々とお付き合いください
ありがとうございましたm(__)m

一応解決とさせて頂きますね。
突っ込み等あれば・・・。

subaru 2007/06/13(水) 12:22:19
押されたボタンによって動作を切り替えたいだけで
ボタンの影とか関係ないような。。。

if(GetFocus() == GetDlgItem(IDC_BTN_DEL)) {
  :
といった判断でも十分な気がします。

あるいはコントロールの制御を行っている関数に
イベントを受け取ったコントロールを渡してやるとか。

める 2007/06/13(水) 12:28:04
ちょっと試して見ましたが、
無効ボタンだとフォーカスは外れてませんか?
無理なようです。

>あるいはコントロールの制御を行っている関数に
>イベントを受け取ったコントロールを渡してやるとか。

そういう手もありましたね・・・。
今後詰まるようならそうしてみます。
ありがとうございました。

ITO 2007/06/13(水) 13:14:04
僕がやっていた方法で参考になればですが、

1. 削除・変更などに使うすべてのコントロールを連番にします。
(「RESOURCE.Hを直接変更するので必ずRESOURCE.Hのバックアップをして下さい。)
2. 実際の実行画面を印刷して番号を記入しておく。
この2点をやっておくと便利です。

 GetDlgItemを使った操作もまとめて出来ます。
僕は、「DoDataExchange(CDataExchange* pDX)」の部分で
DDX_Control、DDX_Text連番で配列変数に登録させてしまいます。
ID番号が解ってますからFor文で出来ますよね。

何か糸口が見つかるといいですね。

#「CButton::GetButtonStyle」のほうが楽な気がするのですが......

古いスレッドには追加発言できません。