■動作環境 :WindowsXP
■開発環境 :Visual C++6.0(ダイアログベース)
■データベース :Access2000(ADO接続)
左クリックで再レスです。
ダイアログに月間予定表を貼り付けて日付をとって、それを元にして
Accessのデータを表示させるプログラムを作っています。
カレンダーのクリックした日を取りたいのですが
カレンダーにカーソルがあたっていないと取ってくれません。
(私は日にちをクリックした時点でカーソルはカレンダーにあたっていると
思っていました)
フォーカスがあたっている時は日付を取ってくれていますが、これもクリック
してとゆうよりも選択されていたら取得してるようです。
1.クリックした日をとる場合はどうすればいいか教えてください。
2.OKボタン以外はEnterを使えないようにしているのですが
日にちを選択してEnterを押下しますと画面が消えてしまいます。
カレンダー自体はEnterを押下しても消えないので、カレンダー
の中の日付を制御する方法を教えてください。
3.プログラムの書き方で修正したほうがいい箇所がありましたら、
教えてください。(独学ですので普通はこのようにやるのかとゆう不安と
無駄な処理が多そうな気がする為)
よろしくお願い致します。
2006年10月
日 月 火 水 木 金 土
24 25 26 27 28 29 30
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 1 2 3 4
<以下プログラム>
BOOL CZzzDlg::PreTranslateMessage(MSG* pMsg)
{
CString Year;
CString Month;
CString Day;
// IDC_BUTTON1 以外はEnter無効
if(GetFocus() != GetDlgItem(IDC_BUTTON1)){
if(pMsg->wParam == VK_RETURN) { // エンターキー
return FALSE;
}
else if(pMsg->wParam == VK_ESCAPE) { //エスケープキー
return FALSE;
}
}
// フォーカスがカレンダーの時
if(GetFocus() == GetDlgItem(IDC_MONTHCALENDAR2)){
//左クリックしたら
if(pMsg->wParam == VK_LBUTTON){
// 月間予定表 コントロールの機能
CMonthCalCtrl* pMonthSel;
// 月間予定表のコントロールのウィンドウハンドルを取得
pMonthSel = (CMonthCalCtrl *)GetDlgItem(IDC_MONTHCALENDAR2);
// 現在選択されている日付情報を取得
SYSTEMTIME st;
pMonthSel->GetCurSel(&st);
// %04d, %02d 0が指定されていると、数値の前に余白があるときは、
// 0が詰めて表示されます(省略した場合は空白が詰められます)。
// SYSTEMTIME型 ~ CString型 + 結合
Date.Format( %04d/%02d/%02d, st.wYear, st.wMonth, st.wDay );
// 日付を表示
AfxMessageBox(Date);
}
}
return CDialog::PreTranslateMessage(pMsg);
}
1.
とりあえず、MCN_SELCHANGEをハンドルして取得すればいいような気がするんだけど。
void CXXXXXDlg::OnSelchangeMonthcalendar1(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
NMSELCHANGE* pNMSC = ( NMSELCHANGE* )pNMHDR;
CTime t( pNMSC->stSelStart );
TRACE1( _T( %s\n ), t.Format( _T( %Y/%m/%d ) ) ); // ※
*pResult = 0;
}
※AfxMessageBoxだと、無限ループしちゃうようです。(VC6)
確認用としてTRACEを使っています。[!]での実行ではなく、F5実行で、デバッグウィン
ドウで確認してみてください。
(上部のボタンやリスト等で月を変更するとMCN_SELCHANGEイベントが2度発生するっぽ)
Blueさんありがとうございます。
MFCをよく分かっていないのでいつも勉強になります。
プログラムも最初に比べたらずいぶんすっきりしました。
ほとんど真似になってしまいましたが、自分で調べてコメントをつけてみました。
間違っていたら指摘して下さい。
void CAbcDlg::OnSelchangeMonthcalendar1(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
// NMSELCHANGE に NMHDR* pNMHDR の先頭アドレスをセット
NMSELCHANGE* pNMSC = ( NMSELCHANGE* )pNMHDR;
// CTime t() は CTime::GetTime の事
// stSelStartはユーザーの選択の範囲で最初の日のための日付を含んでいる
//SYSTEMTIMEの構造(月間予定表で選択した日付)。
CTime t( pNMSC->stSelStart );
// CString型に日時を代入
CString Date = t.Format( %Y/%m/%d);
*pResult = 0;
}
>2.OKボタン以外はEnterを使えないようにしているのですが
> 日にちを選択してEnterを押下しますと画面が消えてしまいます。
> カレンダー自体はEnterを押下しても消えないので、カレンダー
> の中の日付を制御する方法を教えてください。
に関しては引き続き調査をしています。
2.はおそらく、CMonthCalCtrlをクリックしてもフォーカスが移動しないからでしょう。
MCN_SELCHANGEイベントで強制的にフォーカスを移してあげれば出来るかも。
this->GetDlgItem( IDC_MONTHCALENDAR1 )->SetFocus();
ちょっと気になったので一言。
// CTime t() は CTime::GetTime の事
と言うのはちょっと理解が違うような気がします。
この場合、CTime::CTime( const SYSTEMTIME& sysTime, int nDST = -1 );と言う
引数付きのコンストラクタを呼んでいます。
コンストラクタが分からない場合は、C++言語の入門書で確認してください。
9999年12月31日まで正常に動作させるなら
CTime→COleDateTime
としましょう。
Blueさん, PATIOさん, subaruさん ありがとうございます。
みんさんのアドバイスで上手くいきそうです。
前回質問するべきだった事なんですが・・・
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200609/06090060.txt
本来は教えてもらったように
>1.どんなウィンドウメッセージか?
>2.エンターキーまたはエスケープキーか?
>3.対象コントロールか?
この順番でif文を作りたかったのですが
if( pMsg->wParam == WM_KEYDOWN ){}を使うと IDC_BUTTON1 以外の時に
Enterを押下するとダイアログの画面が閉じてしまいます。
参考になるアドバイスがありましたら、よろしくお願い致します。
// 今現在のプログラム
BOOL CDcDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
// キーボードのキーが押下された時
//if ( pMsg->wParam == WM_KEYDOWN ){ 動かす為にコメントにしました。
//カーソルが IDC_BUTTON1 でない時はエンターキー, エスケープキーを無効にする
if(GetFocus() != GetDlgItem(IDC_BUTTON1)){
if(pMsg->wParam == VK_RETURN) { // エンターキー
return FALSE;
}
else if(pMsg->wParam == VK_ESCAPE) { //エスケープキー
return FALSE;
}
}
//}
return CDialog::PreTranslateMessage(pMsg);
}
> if( pMsg->wParam == WM_KEYDOWN ){}を使うと IDC_BUTTON1 以外の時に
> Enterを押下するとダイアログの画面が閉じてしまいます。
何でだろ。下のようにしてもダメでしょうか?
BOOL CXXXXDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してくだ
さい
if ( pMsg->message == WM_KEYDOWN )
{
if ( ( pMsg->wParam == VK_RETURN ) ||
( pMsg->wParam == VK_ESCAPE ) )
{
CWnd* pWnd = this->GetFocus();
if ( pWnd && ( pWnd->GetDlgCtrlID() != IDC_BUTTON1 ) )
{
return FALSE;
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
>何でだろ。
って、対象が違うやんけ。
>if( pMsg->wParam == WM_KEYDOWN ){}
wParamじゃなくてmessage
って、もともとの
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200609/06090060.txt
のBlue 2006/09/25(月) 14:40:00のコードが間違っていました。 orz
すいません、Blue 2006/10/04(水) 12:58:50のように直しておいてください。
みなさんありがとうございます。
少しづつですが、知識が増えていくのを感じる事が出来始めました。
今後ともよろしくお願い致します。