初心者です
複数のアプリで共用したいダイアログがあるのでリソースを使わないでプログラムを作成
したいのです。
コントロール類はすべてコードで配置しています。
(OK,CANCELボタンのほかいくつかのコントロールが配置され指定された時間で自動的に閉
じるダイアログです。リソースIDを使った場合には正常に表示されます)
環境は
Windows XP SP3, Visual Studio 2008 MFC
です
http://www.cycleof5th.com/tips/index.php?date=2007-05-16/1
を参考にして記述したのですが
digcore.cppの311行の
hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
pParentWnd->GetSafeHwnd(), AfxDlgProc);
(BOOL CWnd::CreateDlgIndirect内)
でhWndがNULLになり生成に失敗しているようです。
関連する部分のコード
messageBox.h
typedef struct _ty_dtp{
DLGTEMPLATE dtp;
WORD parm[4];
_ty_dtp(){
dtp.x = 0;
dtp.y = 0;
dtp.cx = 200;
dtp.cy = 100;
dtp.cdit = 2;
dtp.style = 2160591040; //リソースで作成したときの値
dtp.dwExtendedStyle = 0;
}
} ty_DLGTEMPLATE;
messageBox.cpp
Cmessagebox::Cmessagebox(CWnd* pParent /*=NULL*/)
//: CDialog(Cmessagebox::IDD, pParent) //リソース使用の場合はコメントアウトしな
い
{
swo = SW_SHOW;
swc = SW_SHOW;
killtime = 10000;
}
呼び出し部分
ty_DLGTEMPLATE dtp;
memset( dtp.parm, 0, sizeof( WORD ) * 4 );
msg = new Cmessagebox;
msg->setMessage( tmp0, 300, 40, 500000 );
msg->InitModalIndirect( &dtp.dtp, NULL );
stsd = msg->DoModal();
delete msg;
msg = NULL;
初心者かつ質問も初めてですので情報が足りないかもしれませんがよろしくお願いしま
す。
コントロール類をコードで配置しただけなら、
コントロールが1つも載っていない枠だけのダイアログリソースを作成し、
普通にモーダルダイアログとしてDoModal()すれば良いのでは?
その後、InitDialogで、各コントロールをCreateしていけば良いだけです。
bunさん
早速の回答ありがとうございます。
確かにそのとおりなのですが,
複数のアプリでダイアログを共用しようとするとIDが重複しないように注意して設定しな
ければならないと思います。
リソース使わなければIDの重複を気にすることなくプログラミングができると思い質問さ
せていただきました。
背景の説明が不足して申し訳ありません。
>複数のアプリでダイアログを共用しようとするとIDが重複しないように注意して
>設定しな>ければならないと思います。
>リソース使わなければIDの重複を気にすることなくプログラミングができると思い
>質問さ>せていただきました。
ん??? 全く意味がわかりませんねぇ。
複数の別々のアプリケーションで共有するDLGなら、
DLLにリソースとコードを分離すれば十分ですよね。
コモンダイアログ(ファイルオープンなど)と同じ仕組みじゃ
だめな理由が聞きたいところです。
そもそも、IDが違うということは、そのコントロールの
意味自体が異なるということです。意味の異なるコントロールを
配置したDLGは意味の異なるDLGであるのであって、
そもそも別に実装しなければいけません。
ん?
> 複数のアプリで共用したいダイアログがあるのでリソースを使わないでプログラムを
> 作成したいのです。
それは無理かな?と思います。
何か方法があるなら僕も知りたいですね。
> コントロール類はすべてコードで配置しています。
> リソース使わなければIDの重複を気にすることなくプログラミングができると思い
> 質問させていただきました。
IDってダイアログ上で使うコントロールIDですよね?
IDの重複を避けるのもリソースを使う目的のひとつだと思います。
コンパイルした時にエラーで知らせてくれます。
とりあえず
>dtp.cdit = 2;
コントロールが1つもないのに2を指定しているのはおかしいでしょう。
#ダイアログテンプレートを組み立てるのは面倒なので
#一旦リソースから読み込んでそのバイナリの内容を確認し、
#コード側に静的な配列として保持するというのもありかも。
中澤@失業者さま
厳しいご指摘ありがとうございます
当方初心者につきDLLについてはよくわからないのでCDialogの派生クラス(Cmessagebox)
を作りそのクラスを共用できないかと考えました。
Cmessagebox.hで
#define IDD_MESSAGEBOX 199
のように設定した場合
それを呼び出す方(メイン側)で同じ番号の空のリソースを作成すればダイアログを作成で
きるのですが,すでに同じ番号のダイアログが作成されていた場合に問題があるように思
われました。(認識が間違っているかも知れません)
そこで,ネットで検索してリソースを使わずにダイアログを作成する方法を見つけたので
試してみたところダイアログが表示できなかったので質問することにしました。
ITOさま
>> コントロール類はすべてコードで配置しています。
>> リソース使わなければIDの重複を気にすることなくプログラミングができると思い
>> 質問させていただきました。
>IDってダイアログ上で使うコントロールIDですよね?
>IDの重複を避けるのもリソースを使う目的のひとつだと思います。
>コンパイルした時にエラーで知らせてくれます。
ダイアログのID(Resource.hに記述されるもの)です
コードを見て思いつくのは、
* cdit=2なのにDLGITEMTEMPLATEがない
* style(0x80c800c0)にDS_SETFONT(0x40)が指定されているのにフォント情報がない
です。
ty_DLGTEMPLATEのメモリーダンプと
正常なリソースをLoadResourceしたdlgtemplateのダンプを比較してみてください。
(VS2008でどうやれば簡単にダンプが出るのかは私には分かりませんが)
subaruさま
dtp.cdit = 0;
にするとCmessageBoxのOnInitDialog()まで行き着くことができました。
ありがとうございます。
CmessageBoxはDialogの挿入で作ったクラスでリソースはOKとCancelボタンがある状態で
す。そのDLGTEMPLATEをみていたためdtp.cdit = 2 になったものと思います。
OnInitDialog()ではOKボタンCancelボタンを移動しているのでそのところでエラーが出ま
すが一歩進んだと思います。
Dialogの挿入で作成したリソースにはOKとCancelボタンがあるのでそのDLGTEMPLATEを使
えばOKボタンCancelボタンの情報もあると思ったのですが足りないようですね。
みなさま
質問の仕方が悪くて申し訳ありませんでした。
dtp.cdit = 0;
として
CmessageBoxのOnInitDialog()内にボタンコントロール(OKボタンCancelボタン相当)をコ
ードで書く
ことにより目的(リソースを使うことなくダイアログ作成する)が達成できました。
どうもありがとうございました。
>Cmessagebox.hで
>#define IDD_MESSAGEBOX 199
>のように設定した場合
>それを呼び出す方(メイン側)で同じ番号の空のリソースを作成すればダイアログを
>作成できるのですが,すでに同じ番号のダイアログが作成されていた場合に問題が
>あるように思われました。(認識が間違っているかも知れません)
残念ならがら間違っていると思います。
この問題が起きるのは、DLGのリソース dlg.rcを複数のexeの*.rcで
#includeして「*.rc」単位で共用しようとしているの場合などです。
この方法は、もはや誰もやらなくなった危険な賭けであると言っておきましょう。
いまは、共用のDLGは共用のDLLに収めるのがごく普通の方法です。
きれいにカプセル化されたDLL上のDLGは、そのIDがいくつであるかなど、
知る必要さえありません。
多くのプログラマが、おそらく一生使うことのないであろう、
CreateDialogIndirect()を勉強するより、DLLの活用方法を学ぶのを優先
させたほうが自分のためだと考えます。
まぁ、外野席の人はおもしろいかもしれませんが(vv;)。
中澤@失業者さま
今後DLLについて勉強していきたいと思います。
どうもありがとうございました
自作MessageBox程度のものみたいなのでリソースなしで作るのもありかとは思うけど
多言語対応が必要になったらDLLに分離せざるを得ないでしょうね。
> 多くのプログラマが、おそらく一生使うことのないであろう、
> CreateDialogIndirect()を勉強するより、DLLの活用方法を学ぶのを優先
> させたほうが自分のためだと考えます。
これには同意いたしますが、
> この問題が起きるのは、DLGのリソース dlg.rcを複数のexeの*.rcで
> #includeして「*.rc」単位で共用しようとしているの場合などです。
> この方法は、もはや誰もやらなくなった危険な賭けであると言っておきましょう。
残念ながら正しい記述とは言えないでしょう。マイクロソフトがやっています。
Visual Studioが作成したリソースの一部を抜粋。
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
LANGUAGE 17, 1
#pragma code_page(932)
#include res\\MFC_MDI.rc2 // Microsoft Visual C++ 以外で編集されたリソース
#include l.JPN\\afxres.rc // 標準コンポーネント
#include l.JPN\\afxprint.rc // 印刷/印刷プレビュー リソース
#if !defined(_AFXDLL)
#include l.JPN\\afxribbon.rc // MFC のリボン リソースとコントロ
ール バー リソース
#endif
#endif
既存のアプリケーションにリソースを追加するならいざ知らず、新規にアプリケーショ
ンを作成するのであれば、そのIDを避けて使用すればいいだけの話。要は使い方次第。
複数のそういうリソースがあってそのIDが衝突している場合は問題ですが。