VC++6.0 CDateTimeCtrl の暴走について

このQ&Aのポイント
  • VC++6.0環境でCDateTimeCtrlを使用している際に、日時が変更されると暴走する問題について
  • メッセージが表示されるたびに自動的に次月に進むバグが発生する場合があります
  • 回避策としては、バグの修正や別のライブラリの使用が考えられます
回答を見る
  • ベストアンサー

VC++6.0 CDateTimeCtrl の暴走について

開発環境 VC++6.0 WindowsXP Home CDateTimeCtrl(日時指定プロパティ)を使用していますが、 日付を変更した場合はメッセージを表示して、ある処理を行おうと思っています。 ドロップダウンで月のカレンダーを表示させ、 前月または次月などを行います。(何度か同じ処理を繰り返す) 日付が変更されるため、メッセージが表示されます。 「OKボタン」クリック後に自動的に次月→次月→次月・・・・と繰り返されます。 これはバグでしょうか? また、回避策はありますでしょうか? 下記はサンプルプログラムです void クラス::OnDatetimechangeXX(NMHDR* pNMHDR, LRESULT* pResult) { AfxMessageBox( "メッセージ", MB_ICONEXCLAMATION ); } 以上、ご教授よろしくお願いします

noname#59240
noname#59240

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

  • ベストアンサー
  • xcrOSgS2wY
  • ベストアンサー率50% (1006/1985)
回答No.1

DateTimePickerコントロールで何かを変更してChangeイベントが発生し、その処理中にフォーカスが移動すると、同じ「変更」が発生して新たなChangeイベントが発生するようです。 ウィンドウ描画においてPaintイベント処理中にウィンドウ上のコントロールを変更すると再度Paintイベントが発生してしまうようなもので、とりたてて「バグ」と呼ぶには当たらず「制限事項」程度ではないかと思います。 回避方法としては (1) Changeイベント処理中はメッセージボックス表示を行わず、これに代わって例えばウィンドウ上に用意したStaticにメッセージを表示する等する。 (2) メッセージボックスを表示したい場合は、Changeイベントの中ではフラグを立てるだけにしておき、Changeイベントを終了してからメッセージボックスを表示する。(例えば自ウィンドウに「メッセージボックス表示要求メッセージ」をPostしておく等。) という感じかと思います。 ただし、1回の「変更」操作でChangeメッセージが複数発生する場合があるので、Changeメッセージが1回発生するたびごとにメッセージボックスを1つ表示することは好ましくありません。上記(2)の方法を取るとすれば「メッセージボックス表示前あるいは表示中は新たなメッセージボックス表示要求メッセージをPostしない」等の対処が必要でしょう。

noname#59240
質問者

お礼

ありがとうございました。 (2)を採用させていただきました。 Changeメッセージが複数発生に関しましては、 1回目だけ処理してフラグを立てる。 フラグはPost処理後にクリアする方法で制御しました。

関連するQ&A

  • VC++のLV_KEYDOWNについて

    キーボードのショートカット処理の関数を作成しているのですが、Ctrl + sでデフォルトの保存処理ではなく 別の処理を作成したいと考えております。 ですが下記のように実装してもCtrl + sを検出できません。(Ctrl + a)は検出するのですが。 何か原因があるのでしょうか? ご存知の方がいましたらご教授いただけないでしょうか? void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) { LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR; SHORT nCtrl = 0; switch(pLVKeyDow->wVKey) { case 's': case 'S': nCtrl = GetKeyState(VK_CONTROL); if(nCtrl >= 0) { // Ctrlキーが押下されていない場合 break; } // Ctrl + sの処理 break; case 'a': case 'A': nCtrl = GetKeyState(VK_CONTROL); if(nCtrl >= 0) { // Ctrlキーが押下されていない場合 break; } // Ctrl + aの処理 break; } *pResult = 0; }

  • CTreeCtrlでアイコンが変化しない

    環境は、MSVC++6.0&MFCです。 やりたいことは、ツリーコントロールのアイコンをエクスプローラのフォルダのように、 開いたときと閉じたときとで、アイコンを変化させたいのです。 以下は、ソースです。 CTreeCtrlからMyTreeCtrlを派生しています。 テスト用に開いたときは、文字列を"開いた"、閉じたときは、"閉じた"のように変化させるようにしています。 void MyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; if(pNMTreeView->action == TVE_EXPAND){ SetItemState(pNMTreeView->itemNew.hItem , INDEXTOSTATEIMAGEMASK(0) , TVIS_STATEIMAGEMASK); SetItemText(pNMTreeView->itemNew.hItem , "開いた"); }else{ SetItemState(pNMTreeView->itemNew.hItem , INDEXTOSTATEIMAGEMASK(1) , TVIS_STATEIMAGEMASK); SetItemText(pNMTreeView->itemNew.hItem , "閉じた"); } *pResult = 0; } 実行すると、文字は、開いたときは、"開いた"、閉じたときは、"閉じた"とちゃんと表示されますが、 アイコンが変化しません。 お分かりの方、いらっしゃいましたら、教えてください。

  • MSGFILTER lParmで得られるキーコード?

    いつもお世話になっております。 以下のような関数で押されたキーを判定しています。 lParmで得られるキーコードはVK_??のコードと違うようなのですが、 (キーボードの並び方順になってる?) これをVK_??に変換するような方法はあるのでしょうか? (本当はSHIFTデータもプラスして文字コードに変換したいのですが・・・) 何か良い方法があればアドバイスお願いいたします。 void CCtypeView::OnMsgfilterEdit1(NMHDR* pNMHDR, LRESULT* pResult) { MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR); if( pMsgFilter->msg == WM_KEYDOWN ) { SHORT sho = GetAsyncKeyState(VK_SHIFT); TRACE( "%d : \nWM_LBUTTON x=%x,y=%d sho=%x", pMsgFilter->msg, HIWORD( pMsgFilter->lParam), LOWORD( pMsgFilter->lParam), sho ); } *pResult = 0; }

  • インライン処理

    VS2008 MFC を使用して、CListCtrlの派生クラスを全てインラインで書きたいと思い、 ・追加->クラス->C++クラス->基本クラス"CListCtrl" + インラインオプションにチェック で作成したのですが、メッセージ処理を追加するとcppファイルが出来てしまいます。 利便性からヘッダファイル単体で使用したいのですが、cppの内容をヘッダに全て書き写し、cppファイルを削除することは出来ないのでしょうか? Ex. <クラス生成直後=ヘッダファイルのみ> #pragma once #include "afxcmn.h" class CTest01 : public CListCtrl { public: CTest01(void) { } virtual ~CTest01(void) { } }; <メッセージ追加後=ヘッダ> #pragma once #include "afxcmn.h" class CTest01 : public CListCtrl { public: CTest01(void) { } virtual ~CTest01(void) { } DECLARE_MESSAGE_MAP() afx_msg void OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult); }; <メッセージ追加後=cpp> #include "StdAfx.h" #include "Test01.h" BEGIN_MESSAGE_MAP(CTest01, CListCtrl) ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, &CTest01::OnLvnColumnclick) END_MESSAGE_MAP() void CTest01::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // TODO: ここにコントロール通知ハンドラ コードを追加します。 *pResult = 0; } 上記の例でOnLvnColumnclickをヘッダファイルに記述することは可能でしたが、BEGIN_MESSAGE_MAPの辺りと、インクルードをヘッダに移動するとリンク時にエラーが出てしまいます。 メッセージ処理をする場合cppファイルは必須なのでしょうか? ・追加->クラス->MFCクラス->基本クラス"CListCtrl" で作成した場合、上記プラスIMPLEMENT_DYNAMICもインクルードファイル内に記述出来ずに困っています。 MFC初心者のため、いまいちBEGIN_MESSAGE_MAPやIMPLEMENT_DYNAMICの意味がわからず行き詰まっています。 なにかヒント等有りましたら、教えていただけないでしょうか? よろしくお願いいたします。

  • アドレス

    利用環境はMFCのVC++6.0です。 void CTestDlg::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) { CString str; int num=m_list.GetSelectionMark(); str=m_list.GetItemText(num,0); if(Tstr!=NULL){ *Tstr=str; } CTest2 dlg2; dlg2.DoModal(); ・ ・ ・ } ヘッダ:CString *Tstr; とすると*Tstr=str;がおかしいらしく、アドレスがきちんと渡っていないようです。Tstr!=NULLの所ではアドレスは0xcccccc"???"となっていて if文は意味をなしません。 値を受け取るダイアログでは CTest Tdlg; CString aa; Tdlg.Tstr=&aa; MessageBox(aa); としています。 TestDlgのリストビューの内容をうけとりそれを新しくダイアログを作って そちらに移すプログラムです。

  • 時刻の日時指定コントロールで実行エラー

    時刻の日時指定コントロールで実行エラー MFCでwindowsアプリケーションを勉強しているものです。 OS : Vista Premium VS : 2008 Pro 日時指定コントロールで、日付や時刻を選択する参考書サンプルを動かそうとしています。 結果は、 時刻のDate Time Pickerのスピンコントロールを動かすとエラーが表示されます。 添付画像にあるエラー表示内の 'File: f:\dd\vctools\crt_bld\self_x86\crt\src\output.c ' というファイルは、 C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\ にあるoutput.cのことでしょうか? そうだとしても、今の私のスキルでは解読することができません。 この時刻のコントロールのプロパティは、以下のように設定しました。 ID : IDC_DATETIMEPICKER4 Format : 時刻 Use Spin Control : True ( 淡色表示になっている ) その他は、デフォルト値です。 このコントロールのイベントハンドラコード部分 void CDateTimeCtrlDialog::OnDtnDatetimechangeDatetimepicker4(NMHDR *pNMHDR, LRESULT *pResult) {     LPNMDATETIMECHANGE pDTChange = reinterpret_cast<LPNMDATETIMECHANGE>(pNMHDR);     // TODO: ここにコントロール通知ハンドラ コードを追加します。     CTime ct;     m_MonthCal4.GetTime( ct );     m_strDate4.Format( L"%02d:%02d:%02" , ct.GetHour() , ct.GetMinute() , ct.GetSecond() );     UpdateData( false );     *pResult = 0; } どなたか教えてください。 お願いします。

  • リストコントロールのデータの変更を検知したい

    リストコントロールのデータの変更時に呼び出されるイベントが分かりません、 OnLvnItemchangedList()であっているのでしょうか?もっと簡単に実現できるのなら、 教えてください。 VC++2010 MFC です。 削除のときは、条件なしに、OnLvnDeleteitemList()内でいいのですが、 追加も pNMLV->uChanged == 4 にすれば問題ないです。でもその他は、厳しくしすぎると クリックしただけで、データが変更されたと判断されたり、・・・でうまく行きません。 【リスト上のデータが変更されるケース】 データが変更される場合は、非選択状態から「すべてを置換」するケースや 一個一個 検索(選択)しながら、「置換」するケースがあります。 後は、リストコントロールにエディットボックスを張り付かせて、「編集」(エンターで確定) して、データを変更するケースがあります。 ただし、「すべてを置換」する場合でも、既に選択状態のデータを処理する場合もあり、困っています。 自分で作ったプログラムなのですから、各機能終了時に変更されたか?されてないか?は 分かっているのですが、勉強のため、質問をしました。 PreTranslateMessage()で出来るのでしょうか? (参考サイト: http://isobe.exblog.jp/996027/ ) 【目的】 起動時 から(前回保存時から)リストデータに変化がない場合、何もせずに終了したい 【やりたいこと】 リストの文字が変わったら、キャプションを FileListCreator(*) にすると ともに、ListDataNoChange_FLG = FALSE; にする。 保存ややリカバリ(復帰)を行ったら (*) を取って、 ListDataNoChange_FLG = TRUE; にする。 if ( ListDataNoChange_FLG == TRUE ) //保存処理をスキップする。 【できれば】 あとは、pNMLV->uChanged などの 4とか8とか、定数で記述したいです。 lParamが何を意味しているか?分からないです。教えて下さい。 void CFileListCreatorDlg::OnLvnItemchangedList(NMHDR *pNMHDR, LRESULT *pResult) {   LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);   // TODO: ここにコントロール通知ハンドラー コードを追加します。   if (( pNMLV->uChanged == 4 && pNMLV->uNewState == 0 && pNMLV->uOldState == 0 ) //リストコントロールにアイテムが追加した時     || ( pNMLV->uChanged == 8 && pNMLV->uNewState == 3 && pNMLV->uOldState == 0)){ //「すべてを置換」「置換」ボタンを押した時 //「検索」ボタンで検索しただけでも選択状態になる     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 1 )     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 2 )     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 3 )){     ListDataNoChange_FLG = FALSE;//追加 2012.05.13          CFileListCreatorDlg* m_Dlg = (CFileListCreatorDlg*)AfxGetMainWnd();     if( (m_Dlg==NULL)||(m_Dlg->GetSafeHwnd()==NULL) ){       return;     }     m_Dlg->SetWindowText(_T("FileListCreator (*)"));   }   //CString tempStr;   //tempStr.Format(_T("OnLvnItemchangedList iItem: %d, lParam: %d, uChanged: %d, uNewState: %d, uOldState: %d\n"), pNMLV->iItem, pNMLV->lParam, pNMLV->uChanged, pNMLV->uNewState, pNMLV->uOldState);   //MessageBox(tempStr);   *pResult = 0; } void CFileListCreatorDlg::OnLvnDeleteitemList(NMHDR *pNMHDR, LRESULT *pResult) {   LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);   // TODO: ここにコントロール通知ハンドラー コードを追加します。   ListDataNoChange_FLG = FALSE;//追加 2012.05.13   CFileListCreatorDlg* m_Dlg = (CFileListCreatorDlg*)AfxGetMainWnd();   if( (m_Dlg==NULL)||(m_Dlg->GetSafeHwnd()==NULL) ){     return;   }   m_Dlg->SetWindowText(_T("FileListCreator(*)"));   *pResult = 0; } ご教授下さい。

  • WM_NOTIFYのメッセージクラッカー

    Borland C++5.5 FreeVersion XP SP3の環境でAPIの練習中なのですが。 WM_NOTIFYのメッセージクラッカーってできるのでしょうか? windowsx.hのヘッダーを見ても見当たりません。 commctrl.hの中にそれらしきものがあるので試しに追加してもダメでした。 ---------------------------------------------------------------------------- //====== WM_NOTIFY Macros ===================================================== #define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) \ (fn)((hwnd), (int)(wParam), (NMHDR FAR*)(lParam)) #define FORWARD_WM_NOTIFY(hwnd, idFrom, pnmhdr, fn) \ (LRESULT)(fn)((hwnd), WM_NOTIFY, (WPARAM)(int)(idFrom), (LPARAM)(NMHDR FAR*)(pnmhdr)) ---------------------------------------------------------------------------- とあるので、次のように宣言をしたのですが //プロトタイプ宣言 void Cls_OnTreeNotify(HWND,int,(NMHDR FAR*)); //メッセージクラッカー宣言 HANDLE_MSG(hWnd, WM_NOTIFY, Cls_OnTreeNotify); //実際の定義 void Cls_OnTreeNotify(HWND hwnd, int idFrom, (NMHDR FAR*)pnmhdr ) { } でコンパイルしたのですが、次のようなコンパイルエラーが発生します。 "未定義のシンボル HWND" 追加した部分(WM_NOTIFY)以外のメッセージクラッカーはWM_PAINT,WM_CREATEは正常にコンパイルできます。 WM_NOTIFYのメッセージクラッカーはできるのでしょうか。 ご教授お願いします。

  • 右クリックメニューの非活性化

    MFCのCListViewを使用してリストビューのプログラムを作成しています。 で、現在その右クリックメニューを作成しようと思いい、ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)でハンドルし、その中で右クリックメニューの活性、非活性(グレーアウト)の制御を追加したいのですが、その制御がうまくいきません。(例えばある条件下の場合はあるメニューを非活性にする等) 詳しい方がいましたら教えていただけないでしょうか? ちなみに右クリックメニューは以下のようにして出力しています。 void CDebugTool::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) { CMenu cme; cme.LoadMenu(IDR_RCLICKMENU); cme.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTBUTTON|TPM_RIGHTBUTTON, pt.x, pt.y, this); }

  • CTreeCtrlのHitTestメソッドについて

    環境:WinXP VS2005 MFC使用 CTreeCtrlに階層のあるアイテムを複数個設定しています。 ノード開閉時にカーソル位置にあるアイテムをGetCorsorPos()+HitTest()関数を使用し、取得していました。これは正しいアイテムのハンドルが返ってきています。 ところが、ある程度ノードを開いていき、表示しきれなくなるとスクロールが表示されますが、一番下までスクロールしている状態だとアイテムがうまく取得できていないようです。 おそらく、GetCursorPosが画面上の相対座標を取得するのに対し、HitTestで設定するのはツリーコントロール自体の相対座標なので、スクロールしている分だけずれてしまっているのではないかと思っているのですが、スクロールしているサイズを取得する方法がわかりませんでした。ご存じの方いましたらご教授をお願いします。 ※ソース抜粋 void CTestTreeCtrl::OnTvnItemexpanded(NMHDR *pNMHDR, LRESULT *pResult) { CPoint point; GetCursorPos(&point); ScreenToClient(&point); // マウスカーソルの位置からアイテムのハンドルを取得する HTREEITEM hItem = HitTest(point);           ・           ・           ・