トップ回答者
MDI(タブ付きドキュメント)のMFCアプリケーションにおいて、Viewにフォーカスがあるにも関わらず、IMEが無効になってしまう場合がある

質問
-
VC++ 2010 で MFCアプリケーションを開発しております。
タブ付きMDIアプリケーションで、テキストエディタのようなものを作っているのですが、Viewにフォーカスがあるにも関わらずIMEが無効になってしまい、日本語入力をONにすることができない状態が発生する場合があることが判明しました。
その後、調査の結果、MFCアプリケーションウィザードでアプリケーションを作成しただけでも、IMEが無効になることがわかりました。
発生手順は以下の通りです。
- マルチドキュメント(タブ付きドキュメント)でMFCアプリケーションを新規作成。
- 作成したアプリケーションを実行し、2つ以上タブを開く。
- タスクバーに表示されるアプリケーションのアイコンをクリックし、サムネイルをクリックすると、IMEが無効になり、日本語入力をONにすることができなくなる。
ポイント
- タブ付きドキュメントでないときは発生しない。
- タブを1つだけ開いているときは発生しない。
- アプリケーション上のタブをクリックすると、IMEを有効になり、日本語入力をONにすることができるようになる。
- Windows 7, Microsoft Office IME 2010 で実行。
現状ではユーザーの使い勝手を大きく損ねてしまうことから、プログラムの修正によって回避したいと考えております。
もし、回避策がございましたら、教えていただけるとありがたいです。
ご協力のほどよろしくお願い申し上げます。
- 編集済み yoshinor 2016年5月20日 17:30
回答
-
ご連絡ありがとうございます。
VS2013のソースコードを調べたところ、CChildFrame と CMainFrame を次のように修正することで、対処することができましたのでご報告します。
ChildFrame.h
class CChildFrame : public CMDIChildWndEx { DECLARE_DYNCREATE(CChildFrame) public: CChildFrame(); virtual ~CChildFrame(); protected: DECLARE_MESSAGE_MAP() virtual void ActivateTopLevelFrame(); //←追加 };
ChildFrame.cpp
UINT AFX_WM_AFTER_TASKBAR_ACTIVATE = ::RegisterWindowMessage(_T("AFX_WM_AFTER_TASKBAR_ACTIVATE")); void CChildFrame::ActivateTopLevelFrame() { CMDIFrameWndEx* pTopLevel = DYNAMIC_DOWNCAST(CMDIFrameWndEx, GetTopLevelFrame()); if (pTopLevel == NULL) { return; } ActivateFrame(); pTopLevel->SetForegroundWindow(); BOOL bIsMinimized = pTopLevel->IsIconic(); pTopLevel->ShowWindow(bIsMinimized ? SW_RESTORE : SW_SHOW); pTopLevel->PostMessage(AFX_WM_AFTER_TASKBAR_ACTIVATE, (WPARAM)bIsMinimized, (LPARAM)GetSafeHwnd()); }
MainFrame.hclass CMainFrame : public CMDIFrameWndEx { DECLARE_DYNAMIC(CMainFrame) public: CMainFrame(); virtual ~CMainFrame(); protected: DECLARE_MESSAGE_MAP() public: afx_msg LRESULT OnAfterTaskbarActivate(WPARAM wParam, LPARAM lParam); //←追加 };
MainFrame.cpp
extern UINT AFX_WM_AFTER_TASKBAR_ACTIVATE; EGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx) ON_REGISTERED_MESSAGE(AFX_WM_AFTER_TASKBAR_ACTIVATE, &CMainFrame::OnAfterTaskbarActivate) END_MESSAGE_MAP() LRESULT CMainFrame::OnAfterTaskbarActivate(WPARAM, LPARAM lp) { HWND hwndMDIChild = (HWND)lp; if(hwndMDIChild != NULL && ::IsWindow(hwndMDIChild)) { ::SetFocus(hwndMDIChild); } return 0; }
以上の修正により、タスクバーをクリックしてもIMEの切り替えが有効のままになります。
今まで、いろいろとご助言いただきありがとうございました。
- 回答としてマーク 星 睦美 2016年7月6日 8:03
すべての返信
-
れす付きませんね。
ご指摘の症状を確認しました。VS2010 Ver4.5.51029 SP1Rel on Windows7pro(64bit)+SP11.ウィザードコードのまんまビルドしても発生します。
2.VS2013のではウィザードコード発生しませんでした。
3.両ウィザードコードに、本症状に関連しそうな違いは見つかりません。以上を勘案すると、VS2010に同梱されているMFCの瑕疵である疑いが濃厚です。
対策ですが、可能であれば新しいVisual Studioに変更するのが確実だと考えられます。
タブグループ、タブ等の内部コードを追うのは結構ほねがおれます。 -
ご連絡ありがとうございます。
VS2013のソースコードを調べたところ、CChildFrame と CMainFrame を次のように修正することで、対処することができましたのでご報告します。
ChildFrame.h
class CChildFrame : public CMDIChildWndEx { DECLARE_DYNCREATE(CChildFrame) public: CChildFrame(); virtual ~CChildFrame(); protected: DECLARE_MESSAGE_MAP() virtual void ActivateTopLevelFrame(); //←追加 };
ChildFrame.cpp
UINT AFX_WM_AFTER_TASKBAR_ACTIVATE = ::RegisterWindowMessage(_T("AFX_WM_AFTER_TASKBAR_ACTIVATE")); void CChildFrame::ActivateTopLevelFrame() { CMDIFrameWndEx* pTopLevel = DYNAMIC_DOWNCAST(CMDIFrameWndEx, GetTopLevelFrame()); if (pTopLevel == NULL) { return; } ActivateFrame(); pTopLevel->SetForegroundWindow(); BOOL bIsMinimized = pTopLevel->IsIconic(); pTopLevel->ShowWindow(bIsMinimized ? SW_RESTORE : SW_SHOW); pTopLevel->PostMessage(AFX_WM_AFTER_TASKBAR_ACTIVATE, (WPARAM)bIsMinimized, (LPARAM)GetSafeHwnd()); }
MainFrame.hclass CMainFrame : public CMDIFrameWndEx { DECLARE_DYNAMIC(CMainFrame) public: CMainFrame(); virtual ~CMainFrame(); protected: DECLARE_MESSAGE_MAP() public: afx_msg LRESULT OnAfterTaskbarActivate(WPARAM wParam, LPARAM lParam); //←追加 };
MainFrame.cpp
extern UINT AFX_WM_AFTER_TASKBAR_ACTIVATE; EGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx) ON_REGISTERED_MESSAGE(AFX_WM_AFTER_TASKBAR_ACTIVATE, &CMainFrame::OnAfterTaskbarActivate) END_MESSAGE_MAP() LRESULT CMainFrame::OnAfterTaskbarActivate(WPARAM, LPARAM lp) { HWND hwndMDIChild = (HWND)lp; if(hwndMDIChild != NULL && ::IsWindow(hwndMDIChild)) { ::SetFocus(hwndMDIChild); } return 0; }
以上の修正により、タスクバーをクリックしてもIMEの切り替えが有効のままになります。
今まで、いろいろとご助言いただきありがとうございました。
- 回答としてマーク 星 睦美 2016年7月6日 8:03