コンボボックスをドロップダウン不可にしたい

[戻る]
亀山 2016/03/25(金) 10:42:22
Windows7、VS2008、MFCです。

リスト内に選択肢が一つも入っていないコンボボックスで、
ドロップダウンをできないようにする方法はありませんでしょうか。

単語を入力するコンボボックスで、
過去に入力したものが自動で次回の選択肢として入っていくものです。
同じ画面内で履歴の削除を行うこともできます。

このコンボボックスを初めて出したときや、履歴の削除を行った直後だと、
リストはまだ空っぽのため、無駄に大きなドロップダウンが出てしまいます。

ドロップダウンリストではなくドロップダウンなので、
コンボボックス自体を選択不可にするわけにはいきません。

動的にエディットボックスとコンボボックスを置き換える方法以外で、
なにか良い方法はありませんでしょうか。
よろしくお願いいたします。

瀬戸っぷ [E-Mail] 2016/03/25(金) 12:28:39
CBN_DROPDOWNメッセージ、CB_SHOWDROPDOWNメッセージあたりでなんとかできませんかね?
MFCでどうやるのか…についてはちょっと判りませんが。

仲澤@失業者 2016/03/25(金) 16:54:52
比較的簡単にできます。

1.CComboBoxを継承したクラス、例えばXComboクラスを作成する。
2.このクラスでWM_LBUTTONDOWNメッセージをハンドリングする。
 つまりXCombo::OnLButtonDown()関数を作るわけですね。
3.上記関数内で、もし項目数が0ならば派生元の:OnLButtonDown()を呼ばない。
 あれば、派生元の:OnLButtonDown()を呼ぶ。

とし、当然親のDLGのDoDataExchange()で、XComboクラスのメンバをDDX_Control()するわ
けですね。

ちなみに、コンボボックスは「F4」キーでもドロップするので、これを止めるのには、
このXComboにCB_SETEXTENDEDUIメッセージをWPARAM = 1でSendMessage()します。

瀬戸っぷ [E-Mail] 2016/03/25(金) 17:09:14
>ちなみに、コンボボックスは「F4」キーでもドロップするので、これを止めるのには

F4キーは知らなかった…。
Alt+↓でも開きます。

亀山 2016/03/28(月) 18:38:36
[[解決]]
ご意見ありがとうございます。
ドロップダウンを不可にする仕組み自体はWindowsには無く、通常の見た目のまま、
ドロップダウン状態にならないように監視するしかないということになるのですね。

同じような機能を持った他のアプリなどを調べてみても、
項目が無いときは、真っ白で大きいドロップダウンが出てくるようです。

ちなみに、Visual Studio(2008や2010で確認)の「検索と置換」などは、
項目が無いときは、最小の高さ(1行分)のドロップダウンが出てきました。

これどうやっているのでしょうね。
一昔前のOSでは、リソースエディタで高さを広げておかないと、
通常時のドロップダウンリストが小さくなってしまうはずなのですが。

仲澤@失業者 2016/03/28(月) 19:31:14
リストの高さはコンボにSetWindowPos()等で、WM_SIZEしたときの高さになるので、
項目が無いときは高さを小さくしているのではないでしょうか。

最近の傾向としては、(使い勝手の悪い)コンボボックスではなく、
単純エディットとオートコンプリート用のリストを別にポップアップ表示する
というパターンが多いかもしれません。Chromeとか。
ちょっと違いますがインテリセンスなども似たようなものと言えるかもしれませんね。

亀山 2016/03/31(木) 19:47:16
> リストの高さはコンボにSetWindowPos()等で、WM_SIZEしたときの高さになるので、
> 項目が無いときは高さを小さくしているのではないでしょうか。

解説ありがとうございます。
以下のようにしてみたところ、ドロップダウンは小さくなりました。

CRect rect;
m_combo.GetWindowRect(&rect);
m_combo.SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height() * 2, SWP_NOMOVE |
SWP_NOZORDER);

なお、他にもいろいろ試してみたのですが、以下のように、
一度ダミーの文字列を入れてからResetContent()し直してみたところ、
ドロップダウンの高さが1行分になってくれました。

m_combo.ResetContent();
m_combo.AddString(_T(""));
m_combo.ResetContent();

項目が増えたときにドロップダウンの高さを計算して、
それをずっと憶えているような動作なのかもしれません。

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