ボタンのオーナードローについて

このQ&Aのポイント
  • 既存のプログラムにあるボタンをオーナードローに変更しようとしています。
  • MainFrame-CDialogBar((1))-CWnd((2))のような重なりになっています。開発環境は、VC++6.0です。
  • 変更後のOnDrawItem()にイベントが飛んでこない場合、どこを調べれば良いか教えてください。
回答を見る
  • ベストアンサー

ボタンのオーナードローについて

既存のプログラムにあるボタンをオーナードローに変更しようとしています。 概要としては、以下のとおりです。 ・MainFrame-CDialogBar((1))-CWnd((2))のような重なりになっています。 ・上記(2)のクラスにてオーナードローできるようにしたいのです。 ・開発環境は、VC++6.0です。 変更点は以下のとおりです。 ・(2)にメッセージマップの追加(ON_WM_DRAWITEM()) ・(2)にメッセージハンドラの追加(OnDrawItem()) ・(1)メソッド内で、(2)をCreate後、(2)にModifyStyle()にて、BS_OWNERDRAWを付加 ところが、変更後のOnDrawItem()にイベントが飛んできません。 自分で調べたことは、以下のとおりです。 ・SPY++でメッセージの確認(→飛んできていません) ・GetWindowLong()にて、ボタンスタイルの確認(→追加スタイルが付加されてました) このような場合、他にどこを調べて良いか教えて頂きたいのです。 拙い文章ですが、何卒、よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

解決方法としては2種類考えられます (1)のCDialogBarの派生クラスを作成し、こちらでWM_DRAWITEMもメッセージマップとOnDrawItemをオーバーライドする方法 (2)のCWnd派生クラスに DrawItemメソッドと仮想関数のOnChaildNotifyを実装する 仮想関数の中身はMFCのソースのCButton::OnChaildNotifyを参考にすればいいでしょう OnChaildNotifyの中でWM_DRAWITEM以外は CWnd::OnChaildNotifyを呼び出してリターン WM_DRAWITEMの場合はlParamを LPDRAWITEMSTRUCTにキャストして呼び出せばいいようですよ 今回の構成ではCMainFrmaeまでオーナー描画が通知されません 通知されるのは (2)の親の CDialogBarまでのようです CMainFrameの子ウィンドウとしてオーナー描画のコントロールを追加した場合にはCMainFrame::OnDrawItemが呼ばれるようです

zep750c03
質問者

お礼

ご回答ありがとうございました。 その後、色々調べていくと、(2)のCWnd派生クラスの中のCreate()メソッドからコールされているのが、CretaeControlメソッドであることに気づきました。 OleControlを作成していることが問題のようで、通常のCWnd、CButton等のクラスをCreateすると、問題なくWM_DRAWITEMメッセージが飛んできました。 # 他人が作ったソースで読みきれておらず、ご迷惑をおかけしました。 よって、原因としては、「OleControlではオーナードローできない」ことだろうと推測しております。 実施したいことについては、別手段を検討いたします。 redfox63様> 丁寧なご対応に誠に感謝しております。この度は、色々とありがとうございました。

その他の回答 (2)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

(2)って CButtonの派生クラスなのでしょうか? それとも 単なるCWndの派生クラスですか … (1)のダイアログリソースのボタンを配置してボタンのプロパティのスタイルタブの『オーナー描画』にチェックを入れて検証してみてください CDialogBarの派生クラスまたは親のCFrameWnd(CMainFrm)のOnDrawItemがコールされるはずですよ これらで処理されない場合 CButtonの派生クラスなら CButton::DrawItemが呼び出されて アサートが発生するはずです

zep750c03
質問者

補足

何度も申し訳ありません。 こちらのクラスですが、CWndの派生クラスになります。 ダイアログリソースで作成せずに、ソースのメソッド内でCreateした後で、ModifyStyle()にて、BS_OWNERDRAWを付加しております。 ご回答をヒントにCWndの派生からCButtonの派生クラスとしてみましたが、やはり結果は同じでした。 SPY++にて、プロセスレベルでWM_DRAWITEMが来ていないかの確認を行いましたが、やはり飛んできていません。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

オナードローは 読んで字のごとくそのコントロールを所有するウィンドウが描画処理を担うといったことになります WM_DRAWITEMメッセージの処理ハンドラ(OnDrawItewm)およびメッセージマップはON_WM_DRAWITEMは (1)のCDialogBarの派生クラスに実装する必要がありますよ

zep750c03
質問者

お礼

ご回答ありがとうございます。 早速、試してみました。 ですが、OnDrawItem()がコールされません。 親子関係も正しく設定されているため、飛んでくるかと期待したのですが・・・

関連するQ&A

  • ClistBoxでオーナードローがよくわかりません。

    CListBoxを派生させて オーナードローをしたのですが、(違うような気がするのですが) AddStringしても項目が追加できず 選択できるセルがありません。 ただ、描画がされているだけのようです。 また、AddStringの文字はどうやって表示するのでしょうか? 最終的には、以下のようなことがしたいと思っています。 左にアイコンがあり、ディレクトリごとに 段があるリストボックスです。 もうひとつ、 セルを透過させて背景にBitmapの表示。 こちらのほうで、オーナー描画が必要かなと思い 今に至ります。 ただ、オーナー描画のこととかよくわかっていません。 よろしくお願いします。 ------------------------------------------------ void CzListDlg::OnBnClickedButton1() { static int Cnt=6587; char Str[128]; itoa(Cnt,Str,10); List.AddString(Str); Cnt++; } BOOL CzListDlg::OnInitDialog() { *** List.Create(LBS_OWNERDRAWFIXED|LBS_HASSTRINGS|WS_VISIBLE,CRect(0,0,120,200),this,5000); *** } ------------------------------------------------ void mList::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC *pDC=CDC::FromHandle(lpDrawItemStruct->hDC); pDC->TextOut(0,0,"Hello World");//←本当は、AddStringした文字がほしい pDC->TextOut(0,0,(char *)lpDrawItemStruct->itemData); } void mList::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { lpMeasureItemStruct->itemHeight=30; lpMeasureItemStruct->itemWidth=120; // TODO : ここにメッセージ ハンドラ コードを追加します。 }

  • 動的に追加したポップアップメニューのオーナードロー

    WindowsXp/BCC5.5の環境でアプリ作りを勉強しています。 「mi.fType = MFT_STRING」として、あらかじめ用意したポップアップメニューに動的にメニューを追加できるのですが、その追加したメニューにビットマップを付加するために、「mi.fType = MFT_OWNERDRAW」で追加したいのです。 しかし、これがうまくいきません。 追加じたいは出来るのですが、メニューIDがWM_MEASUREITEMのところに届いていないみたいで そのため、オーナードローできずにいます。 つまり、「WM_MEASUREITEM」は飛んできますが、メニューID((UINT) wp)はゼロのままです。 本当は「mi.wID = 1200」を取得したいんです。 そのため、ウインドウメッセージ、WM_MEASUREITEM、WM_DRAWITEMは 飛んできますが、オーナードローができず、困っております。 ポップアップメニュー追加のためのコード(以下抜粋)を記載しています。 どなたか、ご教授できないでしょうか。 宜しくお願いします。 <メニュー追加のためのコード> memset(&mi, 0, sizeof(MENUITEMINFO)); mi.cbSize=sizeof(MENUITEMINFO); mi.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; mi.fType = MFT_OWNERDRAW; mi.wID = 1200; InsertMenuItem(hSubMenu,0,TRUE,&mi ); 以上

  • CLRでのListBoxのオーナードローのやり方。

    Visual C++のCLRでフォームアプリケーションを作っていて、ListBoxのオーナードローの方法がわからないので質問させてもらいました。 CLRでプログラミングしたことが無く書籍などを読んだこともなく見よう見まねで作っています。 やりたいことはとりあえず http://dobon.net/vb/dotnet/control/lbownerdraw.html にあることです。 サンプルプログラムはVBとC#でC++がありません。 MSDN(http://msdn.microsoft.com/ja-jp/library/system.windows.forms.listbox.drawitem.aspx)も同様でVBとC#のサンプルプログラムでC++がありませんでした。 とりあえず。 C#のサンプル----------------------------------------------- //DrawItemイベントハンドラ //項目を描画する private void ListBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e) { //背景を描画する //項目が選択されている時は強調表示される e.DrawBackground(); //文字を描画する色の選択 Brush b = null; if ((e.State & DrawItemState.Selected) != DrawItemState.Selected) { //選択されていない時 switch (e.Index % 3) { case 0: b = new SolidBrush(Color.Red); break; case 1: b = new SolidBrush(Color.Blue); break; case 2: b = new SolidBrush(Color.Green); break; } } else { //選択されている時はそのままの前景色を使う b = new SolidBrush(e.ForeColor); } //描画する文字列の取得 string txt = ((ListBox) sender).Items[e.Index].ToString(); //文字列の描画 e.Graphics.DrawString(txt, e.Font, b, e.Bounds); //後始末 b.Dispose(); //フォーカスを示す四角形を描画 e.DrawFocusRectangle(); } ----------------------------------------------- を参考にしてForm1に private: System::Void ListBox1_DrawItem(System::Object^ sender, System::Windows::Forms::DrawItemEventArgs^ e) { //背景を描画する //項目が選択されている時は強調表示される e->DrawBackground(); //文字を描画する色の選択 } と書いてみたのですが、そのあとどうすればよいかわかりません。 わかる方、回答お願いします。

  • ボタンの表示を改行表示したい

    ボタンの表示を改行表示したい Windows CE上で動作するソフトを作成中で、ダイアログ上に5個のボタンを置き、押されたボタンにより、それぞれのボタンの表示を変更しようとしています。 中には1行では表示しきれないものがあり、改行したいのですが、「**・・・」と表示されます。他のボタンとのバランスを考えると、横幅を広げる事は出来ません。 ボタンの色を変える為、Owner DrawをTRUEにしているせいだろと推測は出来るのですが、どうやれば改行出来るのでしょうか? ※Owner DrawをFALSEに戻し、MultilineをTRUEにし、Owner DrawをTRUEにし、プロパティのCaptionに\nを入れると改行はされますが...。 環境は以下の通りです。 ・Windows CE 5.0 ・Visual C++ 2005 ・MFCスマートデバイス 以上、よろしくお願いします。

  • ボタンの色(WINAPI)

    環境:Windows XP Home、Visual C++ WINAPIにてボタンの色を変更したいと思っております。 ですので、オーナードローで作成しようと思ったのですが、 色だけ変更したいだけなのに文字列やその他といった、 全てを自分で書かなくちゃいけなくなりました。 他に簡単に出来る方法は無いのでしょうか? 以下に一応、したい事を記述します。 ボタンをクリックした時に、 ChooseColorダイアログを表示して、選択させる。 もしOKでダイアログを閉じた場合、 ボタンはそこで選択した色に変更させる。 よろしくお願いします。

  • リストボックスのオーナードローでInsertStringした文字列の取得

    ダイアログボックスの上にリストボックスを貼り付け、そのリストボックスを各行ごとに色を変て表示させることにトライしています。 なんとかかんとか調べて、 1.リストボックスのリソースで「Owner Draw=固定」に設定変更した。 2.そのリストボックスを持つクラスのウィンドウメッセージ    WM_DRAWITEM    WM_MEASUREITEM   にハンドラを追加した。 3.以下の様にハンドラを記述した。   void COwnerTestDlg::OnMeasureItem(int nIDCtl,       LPMEASUREITEMSTRUCT lpMeasureItemStruct)   {     lpMeasureItemStruct->itemHeight = 10/*1行の高さを設定*/;     CDialog::OnMeasureItem(nIDCtl, lpMeasureItemStruct);   }   void COwnerTestDlg::OnDrawItem(int nIDCtl,        LPDRAWITEMSTRUCT lpDrawItemStruct)   {     CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);     pDC->FillSolidRect(&lpDrawItemStruct->rcItem, RGB(0,0,0)/*背景の色*/);     pDC->SetBkColor(RGB(0,0,0)/*文字の後ろの色*/);     pDC->SetTextColor(RGB(255,255,255)/*文字の色*/);     pDC->TextOut(lpDrawItemStruct->rcItem.left,        lpDrawItemStruct->rcItem.top,        (char*)lpDrawItemStruct->itemData/*行に書かれた文字列*/);   } 4. CListBox* wp = (CListBox*)GetDlgItem(IDC_LIST1);     wp->InsertString(-1,"ADDED"); とやり、うまく表示されました。 ここまでは良かったのですが、 次に、4.のところを     char wbuf[256];     strcpy(wbuf,"ADDED");     wp->InsertString(-1,wbuf); とやったら文字化け(?)の様な、ちゃんと表示してくれなくなってしまいました。何がいけないのでしょうか?

  • MFC - ボタンの処理について

    現在MFCを用いてWebカメラからのキャプチャを行うソフトを作成しています。 環境はVisual Studio 2005です。 ソフトウェアはダイアログ形式で、”Capture"と"停止"のボタン、そして1つPictureControlを配置し、"Capture"ボタンが押されたらWebカメラからの映像をPictureControlに表示し、"停止"ボタンが押されたらキャプチャを終了するというものです。 少し長くなってしまうのですがよろしくお願いします。 開発当初、ダイアログクラスのメンバ変数にbool型の Cap_Flag を追加し、コンストラクタにより初期値を false に設定するようプログラムを組みました。 そして "Capture"ボタンが押され、そのイベントハンドラが呼び出された時に、 Cap_Flag を true に設定しキャプチャを行う関数を実行するようにしました。 キャプチャを行う関数の中では、 Cap_Flag をチェックし true に設定されている間キャプチャを行うよう while( Cap_Flag == true ) としてキャプチャを行います。 その後 "停止"ボタン が押されれば、そのボタンに対するイベントハンドラ内で Cap_Flag に false を設定し、キャプチャを終了しようと考えました。 この設計では確かに "Capture"ボタンが押されればキャプチャが行われ、PictureControlに映像が表示されるのですが、これらのキャプチャ処理は "Capture"ボタン のイベントハンドラ内で実行しているため、キャプチャを行っている間、つまり while( Cap_Flag == true ) となっている間は永遠に実行状態になっているため "Capture"ボタン が押されっぱなしの状態になり、"停止"ボタンを押すことが出来なくなってしまいます。また無理に "停止"ボタン を押そうとすると固まってしまうため、うまく"Capture"と"停止"を行うことが出来ない状況です。 改善策として、オリジナルのメッセージを作成しメッセージマップでそのオリジナルの命令に対してキャプチャを行う関数が呼び出されるよう設定しました。よって、 "Capture"ボタンが押されたときに呼び出されるイベントハンドラ内で Cap_Flag を true に設定し、オリジナルのメッセージを送信して、そのメッセージに対応するキャプチャを行う関数を呼び出すようプログラムを組みなおしました。 このように組みなおした理由は、"Capture"ボタンが押されたときに呼び出されるイベントハンドラ内の処理は、Cap_Flag を true に設定することと、オリジナルのメッセージを送信することのみで、イベントハンドラ内ではキャプチャを行う関数は実行されず、 実際に "Capture"ボタン が押されたとしても、押された状態ではなくすぐに基の状態(表示)にもどるだろうと考えたためです。 ですが、このように変更しても "Capture"ボタンのイベントハンドラ内でキャプチャ処理を行っていることと同様に "Capture"ボタンが押されっぱなしの状態になり、"停止"ボタンを押すことが出来ません。 どのようにプログラムを組めば、実際にキャプチャを行っている間でも、"Capture"ボタンが押された状態にならず "停止"ボタン を押すことができるようになるでしょうか? 参考になるアドバイス、またはウェブページをご紹介いただけれたらと思います。 よろしくお願い致します。

  • デスクトップ上の表示を「owner」に戻したい。

    パソコン初心者です。 あまりパソコン用語等に詳しくないのですが、よろしくお願いいたします。 デスクトップ上で新しいフォルダを作成し、「ABC」(仮称)に名前を変更したところ、 気が付いたら、 元からデスクトップにあったアイコン「owner」の名称が「ABC」になっていました。 名称が変わった原因は解りません。(申し訳ございません。) Windowsボタンで立ちあがるメニューの表示も「owner」から「ABC」に変わっています。 元ownerの「ABC」のアイコンを右クリックしても、「名前の変更」がありません。 この、元ownerの「ABC」の名称を元の「owner」に戻したいのですが、 どうすればよろしいでしょうか。 必要と思われる情報を下に列記します。 足りない情報等がございましたらお尋ねください。解る範囲で調べてお答えしたいと思います。 デスクトップには作成したフォルダ「ABC」も存在します。 中身もフォルダ「ABC」の作成時のままです。 元ownerの「ABC」の中身(アドレス帳、ピクチャ、お気に入り等)をざっと確認したところ、 「owner」のときのまま、 保存していた画像ファイル、お気に入り(ブックマーク)等に変更はないようです。 コンピュータからC:ユーザーに入ってみたところ、 「owner」と「パブリック」のフォルダがあり、 この「owner」の中身と 元ownerの「ABC」(デスクトップ上)の中身は同じ(連動している)ようです。 (試しに、新たにお気に入りを追加したところ、どちらにもお気に入りが追加されていました。削除も同様でした。) また、ユーザーアカウントを調べたところ、「owner」のままでした。 パソコンはVistaです。 個人のノートパソコンなので、ログイン名等の設定はせず「owner」のまま使用しております。 よろしくお願いいたします。

  • C言語とWin32APIで作成したボタンのデザインをXPの様に

    いつも、お世話になっております。 小生、只今C言語とWin32APIでアプリを開発中です。 そこで質問なのですが、親ウィンドウにCreateWindow関数を使用し、 ボタンを作成したところ、クラシックな角があるボタンが表示されました。 小生としては以下の条件でXPスタイルのボタンを作成したいのです。 ・オーナードローは使いたくないです(猫でもわかる~のWebサイトを閲覧したところ、アルゴリズムの改変をしないと処理に時間がかかると書いてありました。) サンプルコードが掲載されているWebサイト等はないでしょうか?? 出来れば、サンプルコードの方、宜しくお願い致します。 面倒な質問で申し訳ございません。 諸先輩方、ご教授の方、宜しくお願いします。

  • オーナードローボタンでのバグ

    オーナードローボタンでのバグについて質問です。 ボタンの更新(再描画)を何度も繰り返すと、 再描画をしてもうまく表示(再描画)されなくなるのですが、 何が原因なのでしょうか? さらに、ボタンの再描画がうまく行かなくなった後に、 プロパティシートを開くとおかしくなります(ウィンドウの枠しか表示されない)。 ちなみに、ボタンの再描画処理をしないようにしてみた所、 こういう現象はありませんでした。 開発環境 XP Visual Studio 2005 C、C++でWindowsAPIを使用しています。

専門家に質問してみよう