よろしくおねがいします。
MFCのエディットボックスにprintf(...)みたいな感じでログ表示をして欲しいと言われたのでこんな感じで作りました。
どっちが良いか(あるいはどっちも悪いか)を判定してください。
設定
OS:Windows7 pro 64bit
開発環境:VisualStudio 2005
プロジェクト環境: MFC > ダイアログベース
構成プロパティ: 文字セット > マルチバイト文字セットを使用する
リソースプロパティ: AutoVScroll > True
提案1
冗長な箇所は省略しています。
C++
1#define _LOG(a) { \ 2 printf("[%s:%d]", __FUNCTION__, __LINE__); \ 3 _thisPtr->__printedit a; \ 4 printf("\n"); \ 5 } 6#define CRLF "\r\n" 7 8static CsampleDlg *_thisPtr; // Dialog Class Pointer 9 10// 標準コンストラクタ 11CsampleDlg::CsampleDlg(CWnd* pParent /*=NULL*/) 12 : CDialog(CsampleDlg::IDD, pParent) 13{ 14 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 15 _thisPtr = this; 16} 17 18void CsampleDlg::OnBnClickedClog() 19{ 20 for(int i=0; i < 60 ; i++){ 21 _LOG(("test message output for LogMsg Editbox.")); 22 23 } 24 25} 26 27void CsampleDlg::__printedit(CHAR* format, ...) 28{ 29 /* 2バイト文字を使った場合の動作については保証しない */ 30 static unsigned int _LineCnt = 0; 31 32 unsigned int limit; // テキストの最大値 33 char szTextBuff[250] = {0}; 34 char tmpBuff[250] = {0}; 35 36 va_list list; 37 char *p; 38 int len; 39 40 // エディットボックスに表示できる最大バイト数を取得する 41 limit = m_EditLogMsg.GetLimitText(); 42 43 // 古いログを削除 44 if( _LineCnt > 500 ){ 45 // 一番上の行を""に置換 46 len = m_EditLogMsg.GetLine(0, szTextBuff, 250-1) + sizeof(CRLF); 47 m_EditLogMsg.SetSel( 0, len, FALSE ); 48 m_EditLogMsg.ReplaceSel("",0); /* 置換 */ 49 } 50 sprintf(szTextBuff, "%05d ", _LineCnt++); 51 52 va_start( list, format ); 53 54 for(len = (int)strlen(szTextBuff), p=format;*p; ++p){ /* formatの先頭から末尾まで */ 55 if(*p != '%' ){ /* フォーマット指定子に必ず付く % 以外なら、そのまま出力 */ 56 szTextBuff[len++] = (char)*p; 57 continue; 58 } 59 /* % だったら、その直後の文字に応じて出力 */ 60 switch( *(++p) ){ 61 case 'x': sprintf(tmpBuff, "%x", va_arg(list, int) ); break; 62 case 'd': sprintf(tmpBuff, "%d", va_arg(list, int) ); break; 63 case 'c': sprintf(tmpBuff, "%c", va_arg(list, char) ); break; 64 case 's': sprintf(tmpBuff, "%s", va_arg(list, char*) ); break; 65 default: sprintf(tmpBuff, "%c", *p ); break; 66 } 67 len += (int)strlen(tmpBuff); 68 strcat(szTextBuff, tmpBuff); 69 } 70 va_end( list ); 71 strcat(szTextBuff, CRLF); 72 73 // カーソルを最後に移動させる 74 m_EditLogMsg.SetSel( limit, limit, FALSE ); 75 m_EditLogMsg.ReplaceSel(szTextBuff, 0); 76}
提案2
C++
1#define _LOG(a) { \ 2 printf("[%s:%d]", __FUNCTION__, __LINE__); \ 3 _thisPtr->__printedit a; \ 4 printf("\n"); \ 5 } 6#define CRLF "\r\n" 7 8static CsampleDlg *_thisPtr; // Dialog Class Pointer 9 10// 標準コンストラクタ 11CsampleDlg::CsampleDlg(CWnd* pParent /*=NULL*/) 12 : CDialog(CsampleDlg::IDD, pParent) 13{ 14 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 15 _thisPtr = this; 16} 17 18void CsampleDlg::OnBnClickedClog() 19{ 20 for(int i=0; i < 60 ; i++){ 21 _LOG(("test message output for LogMsg Editbox.")); 22 23 } 24 25} 26 27void CsampleDlg::__printedit(CHAR* format, ...) 28{ 29 static unsigned int lcnt; 30 va_list list; 31 char szTextBuff[250]; 32 int limit,k,l,m; 33 34 // 行番号 35 sprintf(szTextBuff, "%05d ", lcnt++); 36 int len = (int)strlen(szTextBuff); 37 38 // 文字列のフォーマット 39 va_start(list, format); 40 vsprintf(szTextBuff+len, format, list); 41 strcat(szTextBuff, CRLF); 42 43 limit=m_EditLogMsg.GetLimitText(); // Editに表示できる最大バイト数 44 len = m_EditLogMsg.GetWindowTextLength(); // Editに表示されている文字数を取得します 45 46 //新しい文字列がログに追加できない時は 47 if(len+(k=strlen(szTextBuff))>limit){ 48 //古いログを削除します。 49 m_EditLogMsg.SetRedraw(FALSE); //再描画フラグをクリアします。 50 51 if((k=k-(limit-len))<0) k=0; //削除しなくてはならないバイト数を求めます。 52 m=m_EditLogMsg.LineFromChar(k); //削除しなくてはならないバイト数を含む行数を求めます。 53 l=m_EditLogMsg.LineIndex(m); //その行のインデックスを求めます。 54 if(l<k) l=m_EditLogMsg.LineIndex(m+1); //その行の先頭では削除しなくてはならないバイト数に満たない時、、、 55 //次の行のインデックスを求めます。 56 m_EditLogMsg.SetSel(0,l); //削除す範囲を選択します。 57 m_EditLogMsg.ReplaceSel(""); //選択した範囲を削除します。 58 59 len=m_EditLogMsg.GetWindowTextLength(); //現在のログの長さを取得します。 60 61 m_EditLogMsg.SetSel(len,len); //ログの最後を選択します。 62 m_EditLogMsg.ReplaceSel(szTextBuff); //文字列を追加します。 63 64 m_EditLogMsg.SetRedraw(); //再描画フラグをセットします。 65 }else{ 66 m_EditLogMsg.SetSel(len,len); //ログの最後を選択します。 67 m_EditLogMsg.ReplaceSel(szTextBuff); //文字列を追加します。 68 } 69}
あとエディットボックスに表示できる限界があるので古い行は削除していますが、表示しっぱなしに出来る方法はないでしょうか?
ご教授お願いいたします。
回答2件
あなたの回答
tips
プレビュー