http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi?print+200907/09070034.txt
上記の質問をさせていただいたものです。
なぜか一覧から消えてしまっているので、新規に追記させていただきます
(ご意見自体はいただけなかったようで、自前で調べた報告のみですが)。
書き込み自体は残っているようですし、特に変なこと書いていないはずですが、
もしなんらかの違反をしているのでしたら大変失礼しました。
その際にはお手数ですがこれも削除していただければと思います。
自前でVS2008SP1を導入し、CMFCFontComboBoxを使ってみました。
OnInitDialogで
m_combo.m_bDrawUsingFont = TRUE;
m_combo.Setup();
と書いてたところ、コンボボックスにフォント名一覧が自動で挿入され、
各項目はそのフォントで描画されますが、
親クラス(CComboBox)のメンバ関数を使って
m_combo.InsertString(0, _T("ああああああああ"));
m_combo.SetItemData(0, 0x12345678);
などと自前で項目を入れてみたところ、
CMFCFontComboBox::DrawItemで落ちてしまいました。
ItemData値にCMFCFontInfoのポインタが入っているという前提で、
勝手にItemData値を入れられたりすることは想定していないようです。
また、
m_combo.DeleteString(0);
と項目を直接削除してみたところ、
その項目に対応するCMFCFontInfoが削除されずに残り、
終了時にダンプしてしまいました。
MFC自体が、「newで確保した情報のポインタをItemDataに入れて」
「基本クラスにキャストせずに用意された関数だけ呼んでもらう」
という手抜き(?)になっているようです。
最初に書かせていただいた疑問は、深く考えすぎていたのかもしれません。
みなさんありがとうございました。
・・・でしょうね(vv;)。
ですが、もう一歩踏み込んで考えると、さらに明確に理解できます。
CMFCFontComboBox が、CComboBox を public に継承したがための
問題なんだよね、protectedに継承すればいいじゃん、
と思うかも知れませんが、それでは理解が足りません。
SetItemData()は結局SendMessage()を使用しているため、
メンバ関数の使用を制限してもSendMessage()を使用した
ユーザーデータの設定を禁止することはできません。
レドモンドの連中は「ど〜せ止められないならpublicでいいじゃん」
「そもそもフォントの一覧だと言ってるでしょう。関係ないものを
挿入したり削除したりしようとする人は好きなだけハマればぁ」
と考えたに違いありません(笑)。
> CMFCFontComboBox が、CComboBox を public に継承したがための
> 問題なんだよね、protectedに継承すればいいじゃん、
> と思うかも知れませんが、それでは理解が足りません。
自分が昔フォント名選択コンボボックスを作ったときも、
同じようにCComboBoxをprotected継承することをやってみたのですが、
MoveWindowやShowWindowなどのCWnd関数も外から使えなくなってしまう上に、
APIでSendMessageされたら意味無いとも感じ、結局はpublic継承にしました。
そしてその際に、今回のような疑問を感じていました。
当初仲澤@失業者さんが言われていた
> リストコントロールに実体を管理させてはならないのです
ということももっともだと思いますし、subaruさんなどの言われるように、
> アプリ内でルールを決めて使う分にはいいでしょうが、
> ライブラリーとして作成するのであればおすすめできません
と自分も思っていましたし、カスタムコントロールとして
CListCtrlやCComboboxを内部で持って仲介するCWnd派生クラスを作る方法も
いろいろ試行錯誤していたのですが、
MFCというライブラリ自身がやってしまっている以上、
そういうものなのかなと感じました。
ツイート | ![]() |