月間予定表からの左クリックでの日付のとり方 – プログラミング – Home

月間予定表からの左クリックでの日付のと...
 
通知
すべてクリア

[解決済] 月間予定表からの左クリックでの日付のとり方


こまったちゃん
 こまったちゃん
(@こまったちゃん)
ゲスト
結合: 18年前
投稿: 39
Topic starter  

■動作環境      :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);
}


引用未解決
トピックタグ
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

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度発生するっぽ)


返信引用
こまったちゃん
 こまったちゃん
(@こまったちゃん)
ゲスト
結合: 18年前
投稿: 39
Topic starter  

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を押下しても消えないので、カレンダー
> の中の日付を制御する方法を教えてください。

に関しては引き続き調査をしています。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

2.はおそらく、CMonthCalCtrlをクリックしてもフォーカスが移動しないからでしょう。
MCN_SELCHANGEイベントで強制的にフォーカスを移してあげれば出来るかも。

this->GetDlgItem( IDC_MONTHCALENDAR1 )->SetFocus();


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

ちょっと気になったので一言。

// CTime t() は CTime::GetTime の事
と言うのはちょっと理解が違うような気がします。
この場合、CTime::CTime( const SYSTEMTIME& sysTime, int nDST = -1 );と言う
引数付きのコンストラクタを呼んでいます。
コンストラクタが分からない場合は、C++言語の入門書で確認してください。


返信引用
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

9999年12月31日まで正常に動作させるなら
CTime→COleDateTime
としましょう。


返信引用
こまったちゃん
 こまったちゃん
(@こまったちゃん)
ゲスト
結合: 18年前
投稿: 39
Topic starter  

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);
}


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

> 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);
}


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

>何でだろ。
って、対象が違うやんけ。

>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のように直しておいてください。


返信引用
こまったちゃん
 こまったちゃん
(@こまったちゃん)
ゲスト
結合: 18年前
投稿: 39
Topic starter  

みなさんありがとうございます。
少しづつですが、知識が増えていくのを感じる事が出来始めました。

今後ともよろしくお願い致します。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました