MFC タブコントロールのOwner Draw Fixedについて
MFC タブコントロールのOwner Draw Fixedについて
Windows7 Visual Studio 2008で、MFCのSDIでダイアログを作成しています。
MFC編 - タブコントロールの基本1を参考にタブコントロールを使っています。
表示は問題なくでき、タブコントロールのプロパティーの表示部分をいじってどうなるのか試してみました。
Owner Draw Fixedをtureにしたときのデザインがいいと思い、そのまま実行させてみました。
[album]698[/album]
すると、そのダイアログを表示させようとするとDebug Assertion Faildが出てしまいました。
[album]700[/album]
ダイアログのほうを見てみると、中身は表示されていますがタブが表示されていませんでした。
[album]699[/album]
そもそもOwner Draw Fixedの説明にある「親ウィンドウがタブを表示するようにします」の意味はわかっておらず、ただデザインが気に入っただけです。
ネットで調べてみようと思いましたが、読んでもよくわかりませんでした。
falseのままにすれば問題はないのですが、Owner Draw Fixedはtrueにすべきではないのでしょうか?
どのようにすればあのようなデザインが使えるようになるでしょうか?
MFC編 - タブコントロールの基本1を参考にタブコントロールを使っています。
表示は問題なくでき、タブコントロールのプロパティーの表示部分をいじってどうなるのか試してみました。
Owner Draw Fixedをtureにしたときのデザインがいいと思い、そのまま実行させてみました。
[album]698[/album]
すると、そのダイアログを表示させようとするとDebug Assertion Faildが出てしまいました。
[album]700[/album]
ダイアログのほうを見てみると、中身は表示されていますがタブが表示されていませんでした。
[album]699[/album]
そもそもOwner Draw Fixedの説明にある「親ウィンドウがタブを表示するようにします」の意味はわかっておらず、ただデザインが気に入っただけです。
ネットで調べてみようと思いましたが、読んでもよくわかりませんでした。
falseのままにすれば問題はないのですが、Owner Draw Fixedはtrueにすべきではないのでしょうか?
どのようにすればあのようなデザインが使えるようになるでしょうか?
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。
本当に行き詰ったら、考え直すのも1つの手かな。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: MFC タブコントロールのOwner Draw Fixedについて
画像が小さすぎて見えませんので、お願いします。
Owner Draw FixedはtrueはOSやMFCに任せずに自分で親ウィンドウが描画を担当するという意味です。
デザインが気に入られたみたいですが、あれは何もしていない状態ですね。
ただ、Owner Draw FixedはtrueにしただけだとDebug Assertion Faildしないので原因は別にあるのでは?
Owner Draw FixedはtrueはOSやMFCに任せずに自分で親ウィンドウが描画を担当するという意味です。
デザインが気に入られたみたいですが、あれは何もしていない状態ですね。
ただ、Owner Draw FixedはtrueにしただけだとDebug Assertion Faildしないので原因は別にあるのでは?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: MFC タブコントロールのOwner Draw Fixedについて
確かに画像小さいですね・・・すいません。softya(ソフト屋) さんが書きました:画像が小さすぎて見えませんので、お願いします。
画像はフォーラムのアルバムにアップロードしたものです。
「File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\winctrl2.cpp
Line: 1219」
などと書かれていました。
そうだったんですか。softya(ソフト屋) さんが書きました:Owner Draw FixedはtrueはOSやMFCに任せずに自分で親ウィンドウが描画を担当するという意味です。
デザインが気に入られたみたいですが、あれは何もしていない状態ですね。
VBAのユーザフォームにあるタブみたいでいいと思いました。
無事タブコントロールを表示できることを確認した後、あれこれプロパティーの表示部分をいじったりしましたが、どれも変えては戻しの繰り返しです。softya(ソフト屋) さんが書きました:ただ、Owner Draw FixedはtrueにしただけだとDebug Assertion Faildしないので原因は別にあるのでは?
なので、今回はうまくいっていた状態からOwner Draw Fixedをtrueにしただけです。
本当はあったけど隠れていたバグがOwner Draw Fixedをtrueにしたのをきっかけに出てきたのでしょうか?
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。
本当に行き詰ったら、考え直すのも1つの手かな。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: MFC タブコントロールのOwner Draw Fixedについて
その行にはどういう命令が有るんでしょうか?かなたん さんが書きました:画像が小さすぎて見えませんので、お願いします。
確かに画像小さいですね・・・すいません。
画像はフォーラムのアルバムにアップロードしたものです。
「File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\winctrl2.cpp
Line: 1219」
などと書かれていました。
これだけの情報だとなんとも言えないんですが、試しに新規でダイアログを作ってタブコントロールを置いてOwner Draw Fixedをtrueとして見ましたが問題は発生しませんでした。かなたん さんが書きました:無事タブコントロールを表示できることを確認した後、あれこれプロパティーの表示部分をいじったりしましたが、どれも変えては戻しの繰り返しです。softya(ソフト屋) さんが書きました:ただ、Owner Draw FixedはtrueにしただけだとDebug Assertion Faildしないので原因は別にあるのでは?
なので、今回はうまくいっていた状態からOwner Draw Fixedをtrueにしただけです。
本当はあったけど隠れていたバグがOwner Draw Fixedをtrueにしたのをきっかけに出てきたのでしょうか?
【補足】
トラブルが合った場合、問題を切り分けるために私はよく新規でプロジェクトを作って、その機能だけを実験します。
その上でトラブルを潰して本来のプロジェクトに反映させれば他のバグが原因で悩まされる心配がないからです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: MFC タブコントロールのOwner Draw Fixedについて
softya(ソフト屋) さんが書きました:その行にはどういう命令が有るんでしょうか?
void CTabCtrl::DrawItem(LPDRAWITEMSTRUCT)
{
ASSERT(FALSE); // must override for self draw tab controls
}
ということは、タブコントロールの描画部分が原因なのでしょうか?
マインスイーパー.rcにあるダイアログ部分とメニューの一部・Resorce.hにある#defineの一部を新規プロジェクトにコピペしてみました。softya(ソフト屋) さんが書きました:これだけの情報だとなんとも言えないんですが、試しに新規でダイアログを作ってタブコントロールを置いてOwner Draw Fixedをtrueとして見ましたが問題は発生しませんでした。
【補足】
トラブルが合った場合、問題を切り分けるために私はよく新規でプロジェクトを作って、その機能だけを実験します。
その上でトラブルを潰して本来のプロジェクトに反映させれば他のバグが原因で悩まされる心配がないからです。
クラスウィザードでコピーしてきたダイアログのクラスを作り、中身は元のプロジェクトからコピペしました。
そして、新規プロジェクトのview.cppにメニューのメッセージハンドラを作り実行させてみると、なぜかダイアログが出ませんでした。
void CダイアログテストView::OnShowRecord()
{
// TODO: ここにコマンド ハンドラ コードを追加します。
CShowRecord ShowRecord_dlg;
INT_PTR ShowRecord_Show;
ShowRecord_Show = ShowRecord_dlg.DoModal();
if(ShowRecord_Show==IDOK){
}
}
リソースビューでダイアログなどを開いてみると元の通り表示されますし、Owner Draw Fixedなどの設定も元のままですが・・・
Owner Draw Fixedをfalseにしても変わりませんでした。
ShowRecord.cpp
// ShowRecord.cpp : 実装ファイル
//
#include "stdafx.h"
#include "ダイアログテスト.h"
#include "ShowRecord.h"
// ShowRecord ダイアログ
IMPLEMENT_DYNAMIC(CShowRecord, CDialog)
CShowRecord::CShowRecord(CWnd* pParent /*=NULL*/)
: CDialog(CShowRecord::IDD, pParent)
{
}
CShowRecord::~CShowRecord()
{
}
void CShowRecord::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_Record, record_tab);
}
BEGIN_MESSAGE_MAP(CShowRecord, CDialog)
ON_NOTIFY(TCN_SELCHANGE, IDC_Record, &CShowRecord::OnTcnSelchangeRecord)
END_MESSAGE_MAP()
// ShowRecord メッセージ ハンドラ
BOOL CShowRecord::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: ここに初期化を追加してください
CRect rect;
record.Create(CRecord::IDD, this);
record.GetClientRect(&rect);
rect.OffsetRect(1, 21);
record.MoveWindow(&rect, FALSE);
record_tab.InsertItem(0, _T("初級"));
record_tab.InsertItem(1, _T("中級"));
record_tab.InsertItem(2, _T("上級"));
OnTcnSelchangeRecord(0, 0);
record.ShowWindow(SW_SHOW);
return TRUE; // return TRUE unless you set the focus to a control
// 例外 : OCX プロパティ ページは必ず FALSE を返します。
}
void CShowRecord::OnTcnSelchangeRecord(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: ここにコントロール通知ハンドラ コードを追加します。
int select = record_tab.GetCurSel();
//*pResult = 0; //こっちだと「動作を停止しました」といわれるので、
if (pResult) *pResult = 0; //参考にしているサイトのようにこのようにするとエラーは出なかった。
}
// First.cpp : 実装ファイル
//
#include "stdafx.h"
#include "ダイアログテスト.h"
#include "Record.h"
// First ダイアログ
IMPLEMENT_DYNAMIC(CRecord, CDialog)
CRecord::CRecord(CWnd* pParent /*=NULL*/)
: CDialog(CRecord::IDD, pParent)
{
}
CRecord::~CRecord()
{
}
void CRecord::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CRecord, CDialog)
ON_BN_CLICKED(IDC_Reset, &CRecord::OnBnClickedReset)
ON_NOTIFY(TCN_SELCHANGE, IDC_Record, &CRecord::OnTcnSelchangeRecord)
END_MESSAGE_MAP()
// First メッセージ ハンドラ
void CRecord::OnBnClickedReset()
{
// TODO: ここにコントロール通知ハンドラ コードを追加します。
}
void CRecord::OnTcnSelchangeRecord(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: ここにコントロール通知ハンドラ コードを追加します。
*pResult = 0;
}
それでも元のプロジェクトではDebug Assertion Faildですし、新しいプロジェクトではダイアログが出ませんでした。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。
本当に行き詰ったら、考え直すのも1つの手かな。
Re: MFC タブコントロールのOwner Draw Fixedについて
>ASSERT(FALSE);
本当にあなたのコードにこれが書かれているのであれば,
Debug実行した際には,ここに到達した時点で
Debug Assertion Failed と言われるのは当たり前です.そうしろと書いたのだから.
本当にあなたのコードにこれが書かれているのであれば,
Debug実行した際には,ここに到達した時点で
Debug Assertion Failed と言われるのは当たり前です.そうしろと書いたのだから.
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: MFC タブコントロールのOwner Draw Fixedについて
>ASSERT(FALSE);
これはウィザードが自動生成したコードである可能性が高いですね。自動生成時のコメントが有るはずです。
オーナードローを選択したのだから自分で描画コードを書くはずだから、書いてないのは忘れているミスって解釈なのでしょう。
【補足】
// must override for self draw tab controls
ってウィザードのコメントこれだけ?
まぁ、mustなので書け!って事だけど。
これはウィザードが自動生成したコードである可能性が高いですね。自動生成時のコメントが有るはずです。
オーナードローを選択したのだから自分で描画コードを書くはずだから、書いてないのは忘れているミスって解釈なのでしょう。
【補足】
// must override for self draw tab controls
ってウィザードのコメントこれだけ?
まぁ、mustなので書け!って事だけど。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: MFC タブコントロールのOwner Draw Fixedについて
あっ、クラスのコピペですがリソース問題とか色々ややこしいので詳しくないうちは止めたほうが良いです。
※ これだけの情報だと何とも言えないので。
※ これだけの情報だと何とも言えないので。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: MFC タブコントロールのOwner Draw Fixedについて
CTabCtrl::DrawItemというのはMFCのソースコードなのでは?
クラスウィザードで新規にクラスを作るとそのクラスにオーバーライドされたメンバ関数が自動生成されるのではないかと。
クラスウィザードで新規にクラスを作るとそのクラスにオーバーライドされたメンバ関数が自動生成されるのではないかと。
Re: MFC タブコントロールのOwner Draw Fixedについて
usao さんが書きました:>ASSERT(FALSE);
本当にあなたのコードにこれが書かれているのであれば,
Debug実行した際には,ここに到達した時点で
Debug Assertion Failed と言われるのは当たり前です.そうしろと書いたのだから.
Assertionに書かれていたファイルは私が作ったものではなく、ファイルパスもf:\から始まっていることからどこにあるのかさえわかっていませんでした。softya(ソフト屋) さんが書きました:>ASSERT(FALSE);
これはウィザードが自動生成したコードである可能性が高いですね。自動生成時のコメントが有るはずです。
オーナードローを選択したのだから自分で描画コードを書くはずだから、書いてないのは忘れているミスって解釈なのでしょう。
【補足】
// must override for self draw tab controls
ってウィザードのコメントこれだけ?
まぁ、mustなので書け!って事だけど。
ですが、デバッグ中に出たときに中止でなく再試行をしてみると、winctrl2.cppというファイルが開かれ矢印があの位置にありました。
なのでそこのことなんだろうなと思いそのまま引用しました。
自分で描画コードを書く―今回はあのデザインのままにしたいからクラスをオーバーライドして描画用関数の中身は何も書かないようにするのだと思い、とりあえずCShowRecordクラスにCTabCtrlクラスも継承させるようにしてみました。 すると、以下のようなエラーが出てきてしまいました。
1>省略\showrecord.cpp(31) : error C2594: 'static_cast' : 'void (__thiscall CShowRecord::* )(NMHDR *,LRESULT *)' から 'void (__thiscall CCmdTarget::* )(NMHDR *,LRESULT *)' への変換はあいまいです。
1>省略\showrecord.cpp(43) : error C2594: '引数' : 'CShowRecord *const ' から 'CWnd *' への変換はあいまいです。
改めてクラスを作れば自動でオーバーライドされるのでしょうか?ISLe さんが書きました:CTabCtrl::DrawItemというのはMFCのソースコードで、クラスウィザードで新規にクラスを作るとオーバーライドしたコードが自動生成されるのでは?
そもそもC++やMFCでクラスのオーバーライドをしたことがなく、どのようにすればいいのかよくわかっていません。
中身を同じにさせるためにコピペでいいかななんて思っていました。softya(ソフト屋) さんが書きました:あっ、クラスのコピペですがリソース問題とか色々ややこしいので詳しくないうちは止めたほうが良いです。
※ これだけの情報だと何とも言えないので。
それによって何か問題が起こることは考えていませんでした。
その可能性を知らなかったので。
名前さえ合わせればエラーにならないからいいかななんて思っていましたが、そういう問題ではないようですね。
せめて全部ではなく関数の中身などの必要最小限にすることにします。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。
本当に行き詰ったら、考え直すのも1つの手かな。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: MFC タブコントロールのOwner Draw Fixedについて
なるほどMFC側の基礎クラスのDrawItem()でアサートしていたんですね。
詳しくないと分からないと思いますが、MFCは基本的に継承してクラスを利用しています。
なので、いつの間にかオーバーライドを使っている所が多数あります。
なんだろう、C++の勉強も必要ですが、各クラスの継承関係も把握しないと多重継承なんてしてはいけません。
「MFC 階層図」
http://msdn.microsoft.com/ja-jp/library ... x#feedback
階層的に違う物は「混ぜるな危険!」です。
詳しくない人がやるべきことでは無いですね。
管理しているコントロールリソースも違うので、混ぜられる筈がないのです。
とりあえず、変な事はせず(高度なオーナードローは使わない)普通にタブコントロールを実装してみてください。
それが出来たらステップアップとして将来的に挑戦スべきだと思います。
詳しくないと分からないと思いますが、MFCは基本的に継承してクラスを利用しています。
なので、いつの間にかオーバーライドを使っている所が多数あります。
それと適当に継承しても上手く行かなって当たり前です。Assertionに書かれていたファイルは私が作ったものではなく、ファイルパスもf:\から始まっていることからどこにあるのかさえわかっていませんでした。
ですが、デバッグ中に出たときに中止でなく再試行をしてみると、winctrl2.cppというファイルが開かれ矢印があの位置にありました。
なのでそこのことなんだろうなと思いそのまま引用しました。
自分で描画コードを書く―今回はあのデザインのままにしたいからクラスをオーバーライドして描画用関数の中身は何も書かないようにするのだと思い、とりあえずCShowRecordクラスにCTabCtrlクラスも継承させるようにしてみました。
なんだろう、C++の勉強も必要ですが、各クラスの継承関係も把握しないと多重継承なんてしてはいけません。
「MFC 階層図」
http://msdn.microsoft.com/ja-jp/library ... x#feedback
階層的に違う物は「混ぜるな危険!」です。
詳しくない人がやるべきことでは無いですね。
管理しているコントロールリソースも違うので、混ぜられる筈がないのです。
とりあえず、変な事はせず(高度なオーナードローは使わない)普通にタブコントロールを実装してみてください。
それが出来たらステップアップとして将来的に挑戦スべきだと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: MFC タブコントロールのOwner Draw Fixedについて
たとえばMFCで自動で作られるC~ViewクラスがCViewクラスを継承して作られているなどというのは知っていました。softya(ソフト屋) さんが書きました:なるほどMFC側の基礎クラスのDrawItem()でアサートしていたんですね。
詳しくないと分からないと思いますが、MFCは基本的に継承してクラスを利用しています。
なので、いつの間にかオーバーライドを使っている所が多数あります。
C++やMFCで自分でクラスの継承をしたことがないのですが、とりあえずCTabCtrlをオーバーライドしなくてはならないらしいと思って適当にやってしまいました。softya(ソフト屋) さんが書きました:それと適当に継承しても上手く行かなって当たり前です。
なんだろう、C++の勉強も必要ですが、各クラスの継承関係も把握しないと多重継承なんてしてはいけません。
「MFC 階層図」
http://msdn.microsoft.com/ja-jp/library ... x#feedback
階層的に違う物は「混ぜるな危険!」です。
詳しくない人がやるべきことでは無いですね。
管理しているコントロールリソースも違うので、混ぜられる筈がないのです。
とりあえず、CDialogクラスもCTabCtrlクラスもCWndクラスの派生クラスですよね?
「Visual C++6.0[MFC6.0]対応MFCライブラリ標準リファレンス」という本を持っていて、そこでCTabCtrlクラスのメンバであるDrawItemを見て、引数の説明にあるDRAWITEMSTRUCT構造体についても見てみたのですが、その構造体の説明を読んでもあまりよくわかりませんでした。
デフォルト設定のままでタブコントロールを使用することはできてます。softya(ソフト屋) さんが書きました:とりあえず、変な事はせず(高度なオーナードローは使わない)普通にタブコントロールを実装してみてください。
それが出来たらステップアップとして将来的に挑戦スべきだと思います。
ただ、デフォルトのタブコントロールの右側に白い線が出ているのが気になっていました。
あと、選択されたタブが白くなるのも気に入っていません。
そこでプロパティーの表示をあれこれいじったりしてみると、あのOwner Draw Fixedのデザインがいいと思ったのです。
でも、今の私の知識ではこのままのほうがよさそうですかね。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。
本当に行き詰ったら、考え直すのも1つの手かな。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 14年前
- 住所: 東海地方
- 連絡を取る:
Re: MFC タブコントロールのOwner Draw Fixedについて
Vista以降の描画スタイルとかも関係ありそうですね。
ここ直すのはかなり知識を必要とするので、知識を増やしてからのほうがよさそうです。
CTalCtrlは使ったことがないのでサンプル出せなくて申し訳ないです。
※ いつもは私は設定メニューなどでプロパティシートのタブを使っているのですが仕組みが違いすぎて例にならないのです。
ここ直すのはかなり知識を必要とするので、知識を増やしてからのほうがよさそうです。
CTalCtrlは使ったことがないのでサンプル出せなくて申し訳ないです。
※ いつもは私は設定メニューなどでプロパティシートのタブを使っているのですが仕組みが違いすぎて例にならないのです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: MFC タブコントロールのOwner Draw Fixedについて
プロパティーシートとタブコントロールが全くの別物であるのはどこかのサイトで見ました。softya(ソフト屋) さんが書きました:Vista以降の描画スタイルとかも関係ありそうですね。
ここ直すのはかなり知識を必要とするので、知識を増やしてからのほうがよさそうです。
CTalCtrlは使ったことがないのでサンプル出せなくて申し訳ないです。
※ いつもは私は設定メニューなどでプロパティシートのタブを使っているのですが仕組みが違いすぎて例にならないのです。
今回いろいろと質問してみて私にはわからないことだらけだったので、今回はOwner Draw Fixedについてはあきらめることにします。
いつか継承のこととかしっかり勉強してから改めて試すことにします。
ありがとうございました。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。
本当に行き詰ったら、考え直すのも1つの手かな。