• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:MFC利用/WinMainCRTStartup)

MFC利用/WinMainCRTStartupのオーバーライド

このQ&Aのポイント
  • MFCを利用してWinMainをカスタマイズしたいが、情報が分からない
  • VC++のダイアログベースでAPIを使う方法を分かりやすく教えてほしい
  • MFCを利用しつつ目的の機能を実装可能か知りたい

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

子ウィンドウに対するハンドラが標準で用意されていないメッセージを処理したい場合は、PreTranslateMessageをし追加ます。 ダイアログの仮想関数追加でPreTranslateMessageを追加して、pMsgの内容から必要なメッセージだと判断した時に処理するようにします。 今回の場合は、 pMsg->message が WM_LBUTTONDOWN pMsg->hwnd が m_xcCombo_OK_BOX.m_hWmd と等しい場合に処理すればいいんじゃないでしょうか。 ただ、WM_LBUTTONDOWNで処理してしまうと、ドラッグで文字を選択した場合などは、問題があると思います。また、コンボボックスがWM_LBUTTONDOWNを処理してからでないと、キャレットの位置も変わっていないでしょうし。 WM_LBUTTONUPで処理を行えばいいような気がします。

psychang
質問者

お礼

(そのままですが・・・) 「ダイアログの仮想関数追加でPreTranslateMessageを追加 コンボボックス」 ・・・で調べました。 貴重なキーワードを頂き、感謝しています。また、最後まで教えて下さり、ありがとうございました。 方向性が定まっていないで、とてつもなく面倒な事をするところでしたυ それとは別に、一つ ミスタイプがありました。正しくは「->m_hWnd」ですね。 自分では思いつかないのに、あげ足取りですみません。 PreTranslateMessageは他にも応用が利きそうです。質問してよかったです。 以下、参考までに・・・ 【KeywordDlg.h】 class KeywordDlg : public CDialogEx {   DECLARE_DYNAMIC(KeywordDlg) public:   KeywordDlg(CWnd* pParent = NULL); // 標準コンストラクター   virtual ~KeywordDlg(); protected:   virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート      // 生成された、メッセージ割り当て関数   virtual BOOL OnInitDialog(); //追加2011.08.17   virtual BOOL PreTranslateMessage(MSG* pMsg); //追加2011.09.02   DECLARE_MESSAGE_MAP() ・・・ }; 【KeywordDlg.cpp】 // PreTranslateMessage BOOL KeywordDlg::PreTranslateMessage (MSG* pMsg) {   switch (pMsg->message)   {   //case WM_LBUTTONDOWN:   //  break;   case WM_LBUTTONUP://コンボボックスの▼が押された時のみ拾ってくれるみたいで、無くても良いみたいですυ     //HWND m_hWnd;     //if(pMsg->hwnd == GetDlgItem(IDC_COMBO_OK_BOX)->m_hWnd ){     //  LastFocus = _T("OK_BOX");     //  DWORD dwSel;     //  if ((dwSel = ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetEditSel()) != CB_ERR){     //    dwSel_OK = dwSel;     //  }     //  //MessageBox(_T("マウスが押されました"));     //}     break;   case WM_MOUSEMOVE://カーソルの移動そのものを拾う //コンボボックスを横切っただけでも、拾われそうですが(?)、問題なしみたいです。     if(pMsg->hwnd == GetDlgItem(IDC_COMBO_OK_BOX)->m_hWnd ){       LastFocus = _T("OK_BOX");                DWORD dwSel;       if ((dwSel = ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetEditSel()) != CB_ERR){         dwSel_OK = dwSel;       }       //MessageBox(_T("カーソルが移動しました"));     }     break;   default:     break;   } return CDialog::PreTranslateMessage (pMsg); } ~ 一部抜粋 ~ void KeywordDlg::OnCbnEditchangeComboOkBox() {   LastFocus = _T("OK_BOX");   DWORD dwSel;   if ((dwSel = ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetEditSel()) != CB_ERR){     dwSel_OK = dwSel;   } } void KeywordDlg::OnCbnSetfocusComboOkBox() {   ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->SetEditSel(-1,-1);//選択なしで、最後の文字位置にカーソルを置く } void KeywordDlg::OnCbnKillfocusComboOkBox() {   LastFocus = _T("OK_BOX"); } void KeywordDlg::OnBnClickedBtnAsterisk() {   InsertStrIntoKeywords(_T("*")); } void KeywordDlg::InsertStrIntoKeywords(CString str){   CString ComboStr = _T("");   DWORD dwSel;   if (LastFocus == _T("OK_BOX")){     ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetWindowText(ComboStr);     dwSel = dwSel_OK;     if (dwSel != CB_ERR){       ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->SetWindowText(const_cast<LPTSTR>(static_cast<LPCTSTR>(ComboStr.Left(LOWORD(dwSel)) + str + ComboStr.Right(ComboStr.GetLength()-LOWORD(dwSel)))));       dwSel_OK++; //連続して文字を挿入する場合を考慮     }   }else if (LastFocus == _T("NG_BOX")){     ((CComboBox*)GetDlgItem(IDC_COMBO_NG_BOX))->GetWindowText(ComboStr);     dwSel = dwSel_NG;     if (dwSel != CB_ERR){       ((CComboBox*)GetDlgItem(IDC_COMBO_NG_BOX))->SetWindowText(const_cast<LPTSTR>(static_cast<LPCTSTR>(ComboStr.Left(LOWORD(dwSel)) + str + ComboStr.Right(ComboStr.GetLength()-LOWORD(dwSel)))));       dwSel_NG++; //連続して文字を挿入する場合を考慮     }   }else{     dwSel = CB_ERR;     return;   } } (変数の追加で、カテゴリを「Control」すればいいと思うのですが、万が一今までの記述で  不具合があるといけないので、今回は DDX_Control で設定した物は使わず、直で指定しています。) ◆Win32 メッセージ一覧 http://wisdom.sakura.ne.jp/system/winapi/windata1.html たった、一文字を挿入したいだけなのに~ぃ と思いましたが、出来て良かったです! 本当にありがとうございましたm(_ _)m しばらくして、締め切ります。

すると、全ての回答が全文表示されます。

その他の回答 (2)

回答No.2

ウィンドウハンドルがNULLってことは、m_xcCombo_OK_BOXがコントロールとうまく結びついていないということです。 DDXを使っているなら、DoDataExchange内のDDX_Controlの記述が正しいか確認してみてください。

psychang
質問者

補足

返事が遅くなってしまい、大変申しわけありません。 色々、思考錯誤したのですが、まだできません。しかし、僕のソフトにとっては 絶対にいる機能ではないです。ただ、勉強のため お付き合いくださるなら、うれしいです。 コンボボックスに文字を入力した直後に 「*」を挿入する機能はできました。 ありがとうございます。しかし、以下のようなケースでは「*」が思った位置に挿入できません。 その為、 ◆コンボボックスで左マウスが押されたか?を拾いたいのですが、 (コンボボックスでWM_LBUTTONDOWNが押されたか?) クリックメッセージハンドラ void 【コンボボックス】.OnLButtonDown(UINT nFlags, CPoint point){}はないので、 コンボボックスの値が変わらず、マウスカーソルだけが動くときに、インデックスを 拾えないです。OnCbnEditchangeComboOkBox()の部分です。 エディットボックスならできるのかもしれませんが。 ◆CComboBox クラス(でも、ちょっと難しいです↓後でやってみます。今は時間切れという感じです) http://msdn.microsoft.com/ja-jp/library/12h9x0ch(v=VS.100).aspx メモ WM_KEYDOWN メッセージと WM_CHAR メッセージを処理する場合は、コンボ ボックスのエディット コントロールとリスト ボックス コントロールをサブクラス化し、CEdit と CListBox からクラスを派生させ、その派生クラスにこれらのメッセージのハンドラーを追加する必要があります。 詳細については、 http://support.microsoft.com/default.aspx?scid=kb;ja-jp;q174667 および「CWnd::SubclassWindow」を参照してください。 //「コンボ ボックスのエディット コントロールとリスト ボックス コントロールをサブクラス化し、CEdit と CListBox からクラスを派生させ、」という所がすぐには出来ません。 【KeywordDlg.h】 #include "afxwin.h" // KeywordDlg ダイアログ class KeywordDlg : public CDialogEx { ・・・ public:   CComboBox m_xcCombo_OK_BOX;   CComboBox m_xcCombo_NG_BOX;   DWORD dwSel_OK;   DWORD dwSel_NG;   CString LastFocus;   void InsertStrIntoKeywords(CString str);   afx_msg void OnBnClickedBtnAsterisk(); }; 【KeywordDlg.cpp】マッチする文字を入れるOK_BOXの部分を主に載せます。 BOOL KeywordDlg::OnInitDialog(){   //WndProc;   LastFocus = _T("NotSelected");      return true; } void KeywordDlg::OnCbnEditchangeComboOkBox() {   // TODO: ここにコントロール通知ハンドラー コードを追加します。   LastFocus = _T("OK_BOX");   DWORD dwSel;   //if ((dwSel = m_xcCombo_OK_BOX.GetEditSel()) != CB_ERR){   if ((dwSel = ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetEditSel()) != CB_ERR){     dwSel_OK = dwSel;   }   CString tempStr;   tempStr.Format(_T(" LOWORD(dwSel):%d \r\n HIWORD(dwSel):%d \r\n\r\n"),(int)LOWORD(dwSel),(int)HIWORD(dwSel));   TRACE(tempStr); //ここでは、値が変わらない&カーソルのみ動く…ということが、拾えない } void KeywordDlg::OnCbnSetfocusComboOkBox() {   // TODO: ここにコントロール通知ハンドラー コードを追加します。   ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->SetEditSel(dwSel_OK,dwSel_OK); } void KeywordDlg::OnBnClickedBtnAsterisk() {   // TODO: ここにコントロール通知ハンドラー コードを追加します。   InsertStrIntoKeywords(_T("*")); } void KeywordDlg::InsertStrIntoKeywords(CString str){   CString ComboStr = _T("");   DWORD dwSel;   if (LastFocus == _T("OK_BOX")){     ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetWindowText(ComboStr);     dwSel = dwSel_OK;     if (dwSel != CB_ERR){       ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->SetWindowText(const_cast<LPTSTR>(static_cast<LPCTSTR>(ComboStr.Left(LOWORD(dwSel)) + str + ComboStr.Right(ComboStr.GetLength()-LOWORD(dwSel)))));     }   }else if (LastFocus == _T("NG_BOX")){     ((CComboBox*)GetDlgItem(IDC_COMBO_NG_BOX))->GetWindowText(ComboStr);     dwSel = dwSel_NG;     if (dwSel != CB_ERR){       ((CComboBox*)GetDlgItem(IDC_COMBO_NG_BOX))->SetWindowText(const_cast<LPTSTR>(static_cast<LPCTSTR>(ComboStr.Left(LOWORD(dwSel)) + str + ComboStr.Right(ComboStr.GetLength()-LOWORD(dwSel)))));     }   }else{     dwSel = CB_ERR;     return;   } } 変数に入れてない、冗長で見にくいですが、お許し下さい。 後、「イベントハンドラの追加」でも#1に書かれている事はできますね。知りませんでした。 メンバ変数の追加ウィザードで、追加したときに、カテゴリを「Value」にしたのが、問題だったのか、 DDX_Controlの動作がうまく行かなかったのかもしれません。

すると、全ての回答が全文表示されます。
回答No.1

別に、そんな大変なことをしなくても、コンボボックスのCBN_SETFOCUSに対するハンドラを用意すればいいんじゃないですか? 数が多くて、1つ1つハンドラを作成するのが大変とかであれば、親ウィンドウ(ダイアログなど)のPreTranslateMessageで処理できるはずです。 MFCを使っていても、独自にCreateWindowでウィンドウを作成するとか、ウィンドウプロシージャを別のものにするとかはできますが、MFCの動作をよく理解していないと大変苦労します。MFCの枠組み内でできることは、利用したほうが無難です。

psychang
質問者

補足

雷マークを押して、追加するのですね。どおりて、簡単すぎてググっても ダメなはずです。(遅くなってすみません。その他の部分をずっと考えてました。) とりあえず、フォーカスを検知はできましたが、下のコードすら通らないです。 僕のMFCライブラリは壊れてしまったのでしょうか? >  FileListCreator.exe!CComboBox::GetEditSel() 行 854 + 0x2d バイト C++ +  m_hWnd  0x00000000 {unused=??? } HWND__ * +  this  0x0292ae18 {CComboBox hWnd=0x00000000}  const CComboBox * const 以下のようなエラーが出て、中断せざるを得ません。続けると、ちゃんと文字も入っているのですが、 Get,Setする所が悪さをしているように思います。  GetEditSel()  m_xcCombo_OK_BOX.GetWindowTextW(ComboStr); Setするのは、他のボタンを押したときです。カーソル位置に一文字「*」などを挿入したいです。 LeftとRightを使うだけなので、カーソルが何文字目にあるか?さえ分かれば作れます。 くだらない(?)機能にお手間を取らせてすみません。 BOOL KeywordDlg::OnInitDialog(){   //WndProc;   LastFocus = _T("NotSelected");   return true; } void KeywordDlg::OnCbnEditchangeComboOkBox() {   // TODO: ここにコントロール通知ハンドラー コードを追加します。   LastFocus == _T("OK_BOX")   DWORD dwSel;   // Set the selection to be all characters after the current selection.   if ((dwSel = m_xcCombo_OK_BOX.GetEditSel()) != CB_ERR){     //m_xcCombo_OK_BOX.SetEditSel(HIWORD(dwSel), -1);          //CString tempStr;     //tempStr.Format(_T("%d"),(int)dwSel);     //MessageBox(tempStr);     dwSel_OK = dwSel;//マッチキーワードボックス内の文字位置をグローバル変数に退避   } } 途中報告でした。回答ありがとうございました。

すると、全ての回答が全文表示されます。

関連するQ&A