トップ回答者
activexにリソースを含めることは可能でしょうか?

質問
-
やりたいことの条件は以下のとおりです。
IEのブラウザ上動作するFLASHやAcrobatReaderのような独自のビューアを作りたい。表示するデータはTIFFファイルを分割して表示するマルチビューアです。独自の機能を実装するためにすでにWin32 APIのみでWindowsプログラムとして動作するプログラムは作ってあります。
MFCのActiveXプロジェクトにTIFFビューアを移植しました。
テスト用のMFCWindowsプログラムのダイアログリソースにMFC-ActiveX版TIFFビューアを貼り付け動作することを確認しました。
問題はどうもMFC-ActiveXの出力ファイル「*.ocx」ファイルにリソースが含まれないらしくリソース用の画像、アイコンを取得することができません。もとのWin32 APIのEXE版は画像リソースが含まれているので「*.exe」ファイルサイズが大きいのですが「*.ocx」のサイズが小さく、デバッガで確認してもリソースハンドルが0x00000000(NULL)となり取得できていないようです。
ActiveXプロジェクトによるコンパイル後のバイナリーイメージはocxファイルのことだと思っていますがこの中にリソースは入れれないのでしょうか?
回答
-
和和和 さんからの引用 以下のようにコードを書き換えましたMFC_ActiveX2.cppBOOL CMFC_ActiveX2App::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();
if (bInit)
{
TCHAR mes[1000];
HBITMAP h=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDB_MFC_ACTIVEX2),IMAGE_BITMAP,0,0,LR_DEFAULTCOLOR);
wsprintf(mes,L"bitmap %d",h);
::MessageBox(0,mes,mes,MB_OK);
// TODO: この位置にモジュールの初期化処理コードを追加してください。
}
return bInit;
}GetModuleHandleの引数にNULLを渡したときに何が起きるか、調べてみてください。
そのハンドルが指し示すものは、ocxのハンドルではありませんので、求めるリソースが存在しません。
http://msdn.microsoft.com/en-us/library/ms683199(VS.85).aspx
和和和 さんからの引用 ocxファイルサイズから考えてリソースがocxに入っていないような気がします。
なぜ、そのように判断できるのでしょうか?
その画像ファイルが100MBみたいに特徴的なサイズなのでしょうか?
ちなみに、ocxやdllがリソースを持っているかどうかは、Visual Studioのファイル - 開く - ファイルからocxファイルを開くと、持っているリソースを表示してくれます。これで確認ができますので見てみて下さい。
すべての返信
-
和和和 さんからの引用
ActiveXプロジェクトによるコンパイル後のバイナリーイメージはocxファイルのことだと思っていますがこの中にリソースは入れれないのでしょうか?入りますよ。
ocxファイルにはバージョン情報とかつきますので。
和和和 さんからの引用
問題はどうもMFC-ActiveXの出力ファイル「*.ocx」ファイルにリソースが含まれないらしくリソース用の画像、アイコンを取得することができません。もとのWin32 APIのEXE版は画像リソースが含まれているので「*.exe」ファイルサイズが大きいのですが「*.ocx」のサイズが小さく、デバッガで確認してもリソースハンドルが0x00000000(NULL)となり取得できていないようです。「リソース用の画像、アイコン」とは何ですか?独自に作成したものですか?
そのリソースハンドルの取得方法とは何ですか?
もしかして、ActiveXコントロールのプロジェクトにリソースを追加していないだけですか?
そうであれば、新規作成等でリソースファイルを作成して、そのリソースファイルに必要な画像ファイルやアイコンを追加する必要がありますよ。
-
Code Snippet
「リソース用の画像、アイコン」とは何ですか?独自に作成したものですか?
そのリソースハンドルの取得方法とは何ですか?
MFCのActiveXプロジェクト名「MFC_ActiveX2」としてウィザードで作成すると「MFC_ActiveX2.rc」というリソースファイルができます。
そのファイルのテキストに以下の文がありました。既定のリソースですね。
MFC_ActiveX2.rc/////////////////////////////////////////////////////////////////////////////
//
// ビットマップ
//
IDB_MFC_ACTIVEX2 BITMAP "MFC_ActiveX2Ctrl.bmp"
MFC_ActiveX2.cppBOOL CMFC_ActiveX2App::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();
if (bInit)
{
TCHAR mes[1000];
HBITMAP h=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDB_MFC_ACTIVEX2),IMAGE_BITMAP,0,0,LR_DEFAULTCOLOR);
wsprintf(mes,L"bitmap %d",h);
::MessageBox(0,mes,mes,MB_OK);
// TODO: この位置にモジュールの初期化処理コードを追加してください。
}
return bInit;
}これにより作成したMFC_ActiveX2のため参照する「MFC_ActiveXテスト」というMFCプロジェクトをダイアログベースで作成しました。
2つのプロジェクトは同一のソリューションに存在するようにして「MFC_ActiveXテスト」プロジェクトは共通プロパティ→Frameworkと参照で新しい参照の追加で「MFC_ActiveX2」プロジェクトを参照しました。
ダイアログリソースにMFC_ActiveX2コントロールを貼り付け、デバッグ実行しました。
メッセージボックスは0以外の値が表示されることを期待しますが、リソースが取得されていないため0が表示されます。
ocxファイルサイズから考えてリソースがocxに入っていないような気がします。
なにか問題があるでしょうか?
-
和和和 さんからの引用 以下のようにコードを書き換えましたMFC_ActiveX2.cppBOOL CMFC_ActiveX2App::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();
if (bInit)
{
TCHAR mes[1000];
HBITMAP h=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDB_MFC_ACTIVEX2),IMAGE_BITMAP,0,0,LR_DEFAULTCOLOR);
wsprintf(mes,L"bitmap %d",h);
::MessageBox(0,mes,mes,MB_OK);
// TODO: この位置にモジュールの初期化処理コードを追加してください。
}
return bInit;
}GetModuleHandleの引数にNULLを渡したときに何が起きるか、調べてみてください。
そのハンドルが指し示すものは、ocxのハンドルではありませんので、求めるリソースが存在しません。
http://msdn.microsoft.com/en-us/library/ms683199(VS.85).aspx
和和和 さんからの引用 ocxファイルサイズから考えてリソースがocxに入っていないような気がします。
なぜ、そのように判断できるのでしょうか?
その画像ファイルが100MBみたいに特徴的なサイズなのでしょうか?
ちなみに、ocxやdllがリソースを持っているかどうかは、Visual Studioのファイル - 開く - ファイルからocxファイルを開くと、持っているリソースを表示してくれます。これで確認ができますので見てみて下さい。
-
Azuleanさん、大変助けになりました
VSでocxを開いたところリソースは含まれていました。
サイズで勘違いしたのはたまたま巨大な画像ファイルだけが設定ミスで入っていなかっただけでした。
GetModuleHandle(NULL)とは自身のプロセス、つまりテストプロジェクトのインスタンスハンドルが取得できるとのことでした。
引数にはEXEかDLLのパスを入れることで戻り値をLoadResourceなどで使うことでリソースを取得できることを調べました。
しかしocxには対応していないようです。調べたところLoadLibraryとGetModuleHandleの戻り値は同じようにリソース取得に使える値らしいので、
HINSTANCE h=LoadLibrary(L"MFC_ActiveX.ocx");
とし、このハンドルを介してリソースを取得することに成功しました。
理想的にはocxのプロジェクトのソースで自身が格納されているパスが取得できればいいのですがこれはとりあえず呼び出し元プロジェクトからパスはわかるのでそれを引数に渡すことにします。
-
和和和 さんからの引用 GetModuleHandle(NULL)とは自身のプロセス、つまりテストプロジェクトのインスタンスハンドルが取得できるとのことでした。
引数にはEXEかDLLのパスを入れることで戻り値をLoadResourceなどで使うことでリソースを取得できることを調べました。
しかしocxには対応していないようです。調べたところLoadLibraryとGetModuleHandleの戻り値は同じようにリソース取得に使える値らしいので、
HINSTANCE h=LoadLibrary(L"MFC_ActiveX.ocx");
とし、このハンドルを介してリソースを取得することに成功しました。
理想的にはocxのプロジェクトのソースで自身が格納されているパスが取得できればいいのですがこれはとりあえず呼び出し元プロジェクトからパスはわかるのでそれを引数に渡すことにします。
リソースを使いたいのは、OCXの中でですか?それとも、OCXを使う側ですか?
前者であれば、OCXのプロジェクトにある CWinApp の派生クラス(CMFC_ActiveXAppかな?) のメンバーの m_hInstance を使えば、OCX自身のインスタンスハンドルを取得できます。
後者の場合は、そのような仕組みがないので、OCXで画像をロードして、その画像ハンドルを返すのが、仕組み的にはスマートじゃないかな?と思います。
ちなみに、コードを張り付けていた InitInstance の中でやってる分には、GetModuleHandle(...)の代わりに、this->m_hInstance でもいけますよ。それから、MFCなので、AfxGetInstanceHandle()とかも使えます。<お作法守ってる限りは。。。w
このあたりは、MFCでDLL(OCXに限らない)を作る場合の基礎知識となりますので、古い書籍でも何でもいいので、一度勉強しておくことをお勧めします。
VC6時代からはだいぶ変わっているところもありますが(ソースレベルのx64対応や、IDEの違いなどなど)、MFCの基本思想が変わっているわけではありませんので。