開発環境XPSP3 VC6です。
いろいろ検索してみたのですが、みつからず、質問させてください。
プラグインのような機構を実現しようとしています。
ExeとDLLを作成して、DLL側のリソースエディタで定義したツールバーを
CReBarに登録して表示しました。
Exe側で定義済みのツールバーもリバーに登録してあり、DLL側で定義したツールバーを追
加登録しています。
ON_COMMANDでツールバーを押したイベントはハンドリングできます。
でも、ON_UPDATE_COMMAND_UIには、飛んできません。
ツールチップは表示されません。ステータスバーの文字も表示されません。
Exe側で、LoadLibraryでDLLを呼び出して、DLL側のリソースハンドルに一時的に切り替え
て、DLL側で定義したツールバーIDを取得して、CreateとLoadToolBarで作成しています。
メニューも同様にしていますが、そちらは、正常に動作しています。
ツールバーボタンIDとメニュー項目のIDは同じにしてあります。
実験段階なので、本体のリソース文字列に同じIDでTest1\nTest2を記述してあるのです
が、メニューでは、ステータスバーにTest1と表示され、メニューを押すとチェック
マークも入ります。
コードは以下のようになっています。
BOOL CExeApp::InitInstance()
{
hPlugin = LoadLibrary(Plugin.DLL);
以下省略。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
中略
::AfxSetResourceHandle( hPlugin );
m_ToolBar.Create(this);
m_ToolBar.LoadToolBar(ID_TOOLBAR1);
m_Menu.LoadMenu(ID_MENU1);
CMenu* pMenu = GetMenu();
pMenu->AppendMenu( MF_POPUP|MF_STRING, (UINT_PTR)hMenu, プラグインメ
ニュー );
ReBar.AddBar( &m_ToolBar );
m_ToolBar.SetBarStyle( rToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY );
ShowControlBar( &m_ToolBar, TRUE, FALSE );
::AfxSetResourceHandle( ::AfxGetInstanceHandle() );
};
最終的にはボタンIDやメニューIDを
DLLで定義したものでなく、Exe側で再定義しなおしたものに替えたいと考えていますが、
その段階に至っていません。
よろしくおねがします。長文失礼しました。
HMENU hMenu = pMenu->GetSafeHmenu();
が質問で抜けてました。
m_ToolBar.SetBarStyle( m_ToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY );
が質問でrToolBarに打ち間違えました。
バースタイルは、CreateExでツールバー作成時にも行ってみましたが、同じ症状でし
た。
差支えなければ、DLLを「拡張DLL」で作ってみましょう。
EXEとDLLとでリソースを共有できるようになるので、
AfxSetResourceHandle()でインスタンスハンドルを差し替える
必要がなくなります。
EXE側でリソースやコマンドのIDだけ定義しておいて、
DLL側でそのIDを使ってリソースやコマンドを作れば良いです。
Kerryさん、ありがとございます。ためしてみます。
ん~。拡張DLLを作成してみました。
CWinApp派生のオブジェクトがなくなるのですね;
そのクラスでかなりExeとDLLでやりとりしていたので、
実験するのに、すこしかかります。
あと、コマンドの大半がプラグイン形式なので、
プラグインもかなり作っていたので、大幅な変更で、かなり、かかりそうです。
ツールバーだけを実現する方が簡単なようであれば、そちらで実現したいのです。
平行して、拡張DLLで実現も模索してみますが、
ツールバーの問題を直接解決する方法があれば、よろしくおねがいします。
拡張DLLで実験してみました。
ステータスバーにプロンプトが表示されるようになりました。
ツールチップはでませんでした。
イベントがハンドリングできなくなりました。
DLL側でしか、ハンドリングできないのでしょうか?
ちなみに、ハンドリングはドキュメントで、
ON_COMMAND_RANGEとON_COMMAND_UPDATE_UI_RANGEを使用して行っています。
最初の質問のツールバーの動的に生成する手法での実現方法もよろしくお願いします。
コマンドをプラグイン形式で、動的に登録していきたいので、
ツールバーボタンIDなどは、
バッティングしないように後から変更したいのですが、
拡張DLLでは、そういった問題も発生しないのでしょうか?
逆に、IDを変更する必要がある場合は、
ID自体の変更は、m_ToolBar.SetButtons( puiArrayID, nButtons );
で可能なようなのですが、その場合でも、
イベントハンドリングやUPDATE_UIやツールチップや
ステータスバーに表示するプロンプトなどは実現可能でしょうか?
問題が一度に沢山出過ぎなので、全部一気に解決するのは困難です。
とりあえず整理して一つずつ解決していきましょうか。
まず、最初の拡張DLLを使わない方法(共有DLL)でのツールチップ
およびステータス文字列の問題ですが、これは、フレームワークが
ツールチップ文字列やステータス文字列を取得するときに、リソースの
インスタンスハンドルを切り替えていないのが原因かと思われます。
ツールチップ文字列とステータス文字列の取得は、それぞれ
CFrameWnd::OnToolTipText()とCFrameWnd::GetMessageString()で
行っていますので、これをオーバーライドして、コマンドIDが
プラグインコマンドのものであれば、リソースハンドルをDLLに
差し替えるようにしましょう。
以下、SDIの場合の例です。
class CMainFrame : public CFrameWnd
{
public:
afx_msg BOOL OnToolTipText(UINT nID, NMHDR* pNMHDR, LRESULT* pResult);
virtual void GetMessageString(UINT nID, CString& rMessage) const;
};
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
BOOL CMainFrame::OnToolTipText(UINT nID, NMHDR* pNMHDR, LRESULT* pResult)
{
HINSTANCE hinst;
if (pNMHDR->idFrom >= ID_PLUGIN_COMMAND_FIRST &&
pNMHDR->idFrom <= ID_PLUGIN_COMMAND_LAST)
{
hinst = AfxGetResourceHandle();
AfxSetResourceHandle(プラグインのHINSTANCE);
}
BOOL result = CFrameWnd::OnToolTipText(nID, pNMHDR, pResult);
if (pNMHDR->idFrom >= ID_PLUGIN_COMMAND_FIRST &&
pNMHDR->idFrom <= ID_PLUGIN_COMMAND_LAST)
{
AfxSetResourceHandle(hinst);
}
return result;
}
void CMainFrame::GetMessageString(UINT nID, CString& rMessage) const
{
HINSTANCE hinst;
if (nID >= ID_PLUGIN_COMMAND_FIRST &&
nID <= ID_PLUGIN_COMMAND_LAST)
{
hinst = AfxGetResourceHandle();
AfxSetResourceHandle(プラグインのHINSTANCE);
}
CFrameWnd::GetMessageString(nID, rMessage);
if (nID >= ID_PLUGIN_COMMAND_FIRST &&
nID <= ID_PLUGIN_COMMAND_LAST)
{
AfxSetResourceHandle(hinst);
}
}
ありがとございます。
こんな関数があったのですか。
実装してみます。
おせわになっております。
メニューはステータスバーの表示も
プラグインコマンドの起動も正常にできました。
ただ、ツールバーでは、コマンドの起動はできましたが、
ツールチップもステータスバーの表示もされませんでした。
メニューでは、GetMessageStringに入ってきますが、
ツールバーでは、GetMessageStringにもOnToolTipTextにも入ってきません。
コマンドは起動できるので、
ツールバーでもメニューからでも、ON_COMMAND_EX_RANGEには入ってきますが、
ツールバーでは、ON_UPDATE_COMMAND_UI_RANGEに入ってきません。メニューからは
ON_UPDATE_COMMAND_UI_RANGEにも入ってきます。
ツールバーの部分のコードは、以下のようになっています。
pToolBar->CreateEx(this,TBSTYLE_FLAT,WS_VISIBLE|CBRS_TOOLTIPS|CBRS_FLYBY );
pToolBar->LoadToolBar( プラグイン側ツールバーID );
int nButtons = pToolBar->GetCount();
if ( nButtons > 0 ) {
UINT *puiArray = new UINT[nButtons];
for ( int i = 0; i < nButtons; i ++ ) {
UINT nIDonDLL = 0;
UINT nStyle = 0;
int nImage = 0;
// オリジナルのボタンIDを取得
pToolBar->GetButtonInfo( i, nIDonDLL, nStyle, nImage );
// 新しいボタンIDを登録
if ( ID_SEPARATOR == nIDonDLL ) {
puiArray[i] = ID_SEPARATOR; // セパレータの場合
} else if ( nIDonDLL > 0 ) {
int nID_mapped = 0;
puiArray[i] = 本体側ツールバーボタンID;
} else {
ASSERT(0);
return;
};
// 新しいボタンIDの登録
pToolBar->SetButtons( puiArray, nButtons );
delete []puiArray;
};
// リバーに追加
m_wndReBar.AddBar( pToolBar );
// スタイル設定
pToolBar->SetBarStyle( pToolBar->GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY );
// ツールバー表示
ShowControlBar( pToolBar, TRUE, FALSE );
デバッグしてみて、「プラグイン側ツールバーID」「本体側ツールバーボタンID」
は、正常に設定されています。特に不正な動きはしていないように思えました。
「本体側ツールバーボタンID」はメニューで設定したコマンドのIDと同じものです。
テスト用プラグインでは、ツールバーボタンは単純に1つだけ設定しています。
おてすうをおかけしますが、よろしくおねがいいたします。
おせわになります。
テスト的にツールバーボタンIDを本体側のIDとあらかじめ一緒にしておいて、
ボタンIDを変更しない状態でテストしてみました。
他の本体リソースを使ったツールバーとコードは同じになりましたが、
症状は同じで、ツールバーから、コマンド起動のみできる状態でした。
ちなみに、ツールバーボタンを押したときも、GetMessageStringには入ってきませんでし
た。
以下は、試してみたコードです。
pToolBar->CreateEx(this,TBSTYLE_FLAT,WS_VISIBLE|CBRS_TOOLTIPS|CBRS_FLYBY );
pToolBar->LoadToolBar( プラグイン側ツールバーID );
// リバーに追加
m_wndReBar.AddBar( pToolBar );
// スタイル設定
pToolBar->SetBarStyle( pToolBar->GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY );
// ツールバー表示
ShowControlBar( pToolBar, TRUE, FALSE );
よろしくおねがいします。
おせわになります。
ほぼ同じコードを拡張DLLでもテストしてみました。
拡張DLLのコマンドでは、
コマンド起動はできます。
ステータスバーにメッセージプロンプトは表示されます。
COMMAND_UIにも入り、SetCheckすることができました。
ただ、ツールチップは表示されませんでした。
よろしくおながいいたします。
おせわになっています。
さらにじっけんしてみました。
AppWizardで吐き出しただけのExeと拡張DLLをつくってためしてみました。
DLL側リソースエディタで定義したツールバーを
EXE側でツールバーを作成して、
オリジナルのEXEとDLLインターフェイス周りをコピーして、
教えてもらった関数をオーバーライドおよびハンドリングしてみましたところ、
なんと!ステータスバーの表示・ON_COMMAND・ON_COMMAND_UI・ツールチップ表示と
全てうまく動いてます。
とゆうことですので、この質問は解決ということにいたします。
Kerryさんアドバイスありがとうございました。
みなさま、ありがとございました。
でも、これで、もんだいが更にやっかいやことに・・。むぎゅぅ~。;_;