▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼デバッグ出力▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

TRACE("%d",10);
TRACE("  ");
ビルド→デバッグの開始→実行

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ビープを鳴らす▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

MessageBeep(NULL);

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼CStringのtrim▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

文字列の両端のスペースなどを消して整形します

CString str;
str = " test "
str.Trim(' ');//両端から削除する文字を指定する

■結果
test


▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼charとCString▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■charからCStringに変換
char test[5] = "test";
CString str;
str = test;

■CStringからcharに変換
CString str="test 今日は晴天なり 1234";
char buff[1024]="";
wsprintf(buff,_T("%s"),str);
printf("%s\n",buff);

■文字列連結
CString str="a";
str=str+"b"+"c"+"d"+"e"+"f"+"g";
↑ならOKですが、
str="b"+"c"+str+"d"+"e"+"f"+"g";だとエラー

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼文字から数字に▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

stdlib.hをインクルードする
double atof( char* p )
int atoi( char* p )
long atol( char* p )

itoa( int n, char* p, 進数 )

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼数字から文字に▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■CStringを使い変換する

CString str;
str.Format("%d",100);

strの中に文字列"100"が入ります

■CStringからcharに変換

void xxx()
{
     CString str = "test";
     char *p = new char[str.GetLength()+1];
     strcpy( p, str );
     delete [] p;
}


▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼CStringの文字←→数字▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
atoiなどの標準ライブラリを使って文字から数字に変換します

CString str;
m_edit1.GetWindowText(str);//エディットから文字列を取得します
int a=atoi(str);//文字列を数字に変換
a=a+2;
str.Format("%d",a);//数字を文字列に変換
m_edit2.SetWindowText(str);//結果をエディットに書き込みます

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼Controlの使い方▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
ダイアログに貼り付けたコントロールのIDからハンドルを取得して
変数に格納することにより、ダイアログに貼り付けたコントロールを操作します

CString ss;
CEdit* myED1=(CEdit*)GetDlgItem(IDC_EDIT1);//IDC_EDIT1のハンドルを取得
CEdit* myED2=(CEdit*)GetDlgItem(IDC_EDIT2);//IDC_EDIT2のハンドルを取得

myED1->GetWindowText(ss);//変数からIDC_EDIT1の文字を取得します
myED2->SetWindowText(ss);//変数からIDC_EDIT2に文字を書き込みます

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼Controlのリサイズ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

フォームのリサイズと同じ比率でコントロールをリサイズします


bool flg = false;//起動時にイベントが発生してサイズを変えると落ちるため、回避のためのフラグ
void CtestDlg::OnSize(UINT nType, int cx, int cy)
{
  CDialog::OnSize(nType, cx, cy);
  
  // TODO: この位置にメッセージ ハンドラ用のコードを追加してください

  if(flg) GetDlgItem(IDC_STATIC)->MoveWindow(cx/10,cy/10, cx/2,cy/2);//動的なサイズの変更
  flg = true;
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログの起動時にテキストボックスに値を入れておく▼▼▼▼▼▼▼▼▼▼▼

BOOL ...::OnInitDialog()
{
〜〜ここにたくさんのコードがあって、〜〜

  GetDlgItem(IDC_EDIT1)->SetWindowText("hello");//←ここに追加
  return TRUE;
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログの表示▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■モーダルで表示させます

CDialog d;//ダイアログ変数

d.Create(IDD_DIALOG1,this);//リソースからダイアログの生成

int r_value;
r_value = d.DoModal();
if( r_value != IDOK ){
//IDOKが押された場合に実行されます。
return;
}
//Invalidate();                        //再描画


■モードレスで表示させます


CDialog d;//ダイアログ変数

d.Create(IDD_DIALOG1,this);//リソースからダイアログの生成

//d.Create(IDD_DIALOG1);//SDIからダイアログの生成
d.ShowWindow(SW_SHOWNA);//表示
//d.ShowWindow(SW_HIDE);//非表示



■ダイアログ間のフォーカスの移動
SetFocus();

ダイアログ変数.SetFocus();

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログをエンターキーで終了しなくする▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

//クラスウィザードでPreTranslateMessageメンバ関数を追加し、次のように修正します


BOOL CDdddDlg::PreTranslateMessage(MSG* pMsg)
{
  // TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
   if( (pMsg->message == WM_KEYDOWN) || (pMsg->message == WM_SYSKEYDOWN) ) {
        switch(pMsg->wParam) {
        case VK_RETURN:
            return TRUE;
        }
    }
    if( pMsg->message == WM_DESTROY) {
        Sleep( 100);
    }
  
  return CDialog::PreTranslateMessage(pMsg);
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログを常に最前面で表示▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログを最大化で起動▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

//OnInitDialog()にて実行すると起動時に最大化になります。
RECT rc;
::SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);//タスクバーを除いたデスクトップのサイズを知る
MoveWindow( &rc );

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログのサイズ変更▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

//サイズ変更(縦横10拡大)
RECT    rect;
GetWindowRect( &rect );
rect.right += 10;
rect.bottom += 10;
MoveWindow( &rect );

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログの最大化、最小化▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

MFCで作られたプログラムを最小化/最大化/終了するためには、メインウィンドウへそれぞれのシステムコマンドメッセージをポストします。

// 最小化する
AfxGetMainWnd()->PostMessage(WM_SYSCOMMAND, SC_MINIMIZE);

// 最大化する
AfxGetMainWnd()->PostMessage(WM_SYSCOMMAND, SC_MAXIMIZE);

// 元のサイズに戻す
AfxGetMainWnd()->PostMessage(WM_SYSCOMMAND, SC_RESTORE);

// 終了する
AfxGetMainWnd()->PostMessage(WM_CLOSE);
MSDN の WM_SYSCOMMAND の項目では、システムコマンドメッセージの一覧が参照できます。


▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログのサイズ変更可能と変更不可の切り替え▼▼▼▼▼▼▼▼▼▼

ModifyStyle( 0, WS_THICKFRAME ); //サイズ変更不可
ModifyStyle( WS_THICKFRAME, 0 ); //サイズ変更加

により切り替えます

■サイズ変更不可に切り替えるボタン
void ****::OnButton1()
{
   ModifyStyle( 0, WS_THICKFRAME ); //サイズ変更不可
    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if(pSysMenu != NULL)
    {
        pSysMenu->AppendMenu( MF_STRING, SC_SIZE, "サイズ変更(&S)" );
    }
}

■サイズ変更可に切り替えるボタン
void ****::OnButton2()
{
    ModifyStyle( WS_THICKFRAME, 0 ); //サイズ変更加
    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if(pSysMenu != NULL)
    {
        pSysMenu->RemoveMenu( SC_SIZE, MF_BYCOMMAND );
    }
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログの初期表示位置を設定する▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

通常、ダイアログは親ウィンドウに対して中央部に表示される。これを任意の位置に表示するには
OnInitDialog関数をオーバーライドし、その中でSetWindowPos関数を使えばよい。


BOOL CDialog1::OnInitDialog()
{
  CDialog::OnInitDialog();
  
  // TODO: この位置に初期化の補足処理を追加してください
  //--------------------ここから↓---------------------------------------------
  CRect rect;
  GetWindowRect(&rect);
  SetWindowPos(&wndTop, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
    SWP_SHOWWINDOW);
  //--------------------ここまで↑---------------------------------------------
  return TRUE;  // コントロールにフォーカスを設定しないとき、戻り値は TRUE となります
                // 例外: OCX プロパティ ページの戻り値は FALSE となります
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼タスクバーに表示されないようにする▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

ダイアログリソースを開いたら、「表示」−「プロパティ」メニューでプロパティを開きます。
この中にある「拡張スタイル」タブを選択し、「ツールウィンドウ」の項目をチェックします。
これで、ダイアログには拡張スタイルであるWS_EX_TOOLWINDOWスタイルが設定されたことになります。

BOOL CUKTaskTrayDlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  (中略)
  // TODO: 特別な初期化を行う時はこの場所に追加してください。
  ModifyStyleEx(WS_EX_APPWINDOW, 0);    //******* この1行を追加する!*******
  return TRUE;  // TRUE を返すとコントロールに設定したフォーカスは失われません。
}

ただし、WS_EX_TOOLWINDOWスタイルを設定したウィンドウには、最大化ボタンと最小化ボタンをつけることができないため
このダイアログから新しいダイアログを作成すると、通常のダイアログとして使えます。
ModifyStyleEx(WS_EX_APPWINDOW, 0);
の直後に、
CChildDlg dlg;
int iID = dlg.DoModal();
EndDialog(iID);

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログにメニューの追加▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

リソースのツリーにて挿入→Menu
追加したいダイアログのプロパティー→一般→メニュー→選択する

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼UpdateDataメソッド▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■コントロールから変数へ
UpdateData(TRUE);
■変数からコントロールへ
UpdateData(FALSE);

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼コントロールの状態変化▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■コントロールのVisible
m_edit1.ShowWindow(SW_SHOW);//見えるようにする
GetDlgItem(IDC_BUTTON1)->ShowWindow(SW_SHOW);
m_edit1.ShowWindow(SW_HIDE);//見えなくする
GetDlgItem(IDC_BUTTON1)->ShowWindow(SW_HIDE);

■最大化最小化
m_edit1.ShowWindow(SW_MAXIMIZE);//最大化する
m_edit1.ShowWindow(SW_MINIMIZE);//最小化する

■コントロールのEnable
m_b.EnableWindow(false);  

■フォーカスの移動
SetFocus();

■コントロールの色替え(ダイアログの描画メソッドに置く)
UINT nID=IDC_EDIT1;
CWnd* pWnd=GetDlgItem(nID);
CDC* pDC=pWnd->GetDC();
CRect rect;
pWnd->GetClientRect (&rect);
rect.InflateRect(-1,-1,-1,-1);
CBrush brush(RGB(255,0,0));
pDC->FillRect (rect,&brush);
brush.DeleteObject();
pWnd->ReleaseDC(pDC);

■ウインドウサイズに合わせてコントロールのサイズ変更
WM_SIZEのメッセージなどで描画する必要があります
void ****::OnSize(UINT nType, int cx, int cy)
引数の cx,cy にウインドウの横縦サイズが入っています。

RECT    rect,pos;
CDialog::GetClientRect(&rect);
pos.top=0;
pos.left =0;
pos.right =rect.right ;
pos.bottom =rect.bottom/4;//高さを1/4サイズにする
m_****.MoveWindow( &pos );

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログの起動時にフォーカスを指定▼▼▼▼▼▼▼▼▼▼▼▼▼▼

CWnd::OnInitDialog() の中で CWnd::SetFocus() で指定し、戻り値にFALSE を返す。
Example
    BOOL CTiCfgDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
          :
          :
        // IDC_ServerEdit にフォーカスを与える
        CEdit* pzServerEdit = (CEdit *)GetDlgItem( IDC_ServerEdit );
        pzServerEdit->SetFocus();
        return FALSE;  // FALSE を返さないとフォーカスが変えられてしまう
    }

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼メッセージボックス▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

CString result;
result.Format("%dです",10);
MessageBox(result);
もしくは
AfxMessageBox("");

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼タイマー▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■タイマーのセットの仕方
起動時からタイマーをスタートさせる時はWM_CREATEイベントが発生したときに作る
OnInitでのセットはできません


//  ID=1015で 0.5秒タイマーを掛けます。
SetTimer(1015, 500, NULL);



■タイマーイベントの受け取り方
クラスウィザードで WM_TIMERのハンドラを作ります。
OnTimerには全てのタイマーイベントが来ますので、条件式によりIDを調べる必要があります。

void CTest2Dlg::OnTimer(UINT nIDEvent)
{
if (nIDEvent == 1015)//自分がセットしたタイマーIDであるか調べる
{
   KillTimer(1015);//停止
   //自分のタイマーを停止させて処理を行います



   //処理が完了した時点で再びタイマーをセットします
   SetTimer(1015, 500, NULL);;//開始
}
CDialog::OnTimer(nIDEvent);
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼スレッド▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼


■スレッドとして動作する関数
最初にスレッドとして動作する関数を作成します

UINT Thread1( LPVOID pvParam )
{
  while(true){
    Sleep(500);
    TRACE("%d",10);
  }
    return(0);
}

■上で作成された関数をスレッドで動作させます

CWinThread* pThread;
pThread = AfxBeginThread((AFX_THREADPROC)Thread1,
                        (LPVOID)this,      // このクラスをパラメータとして渡しています
                         THREAD_PRIORITY_NORMAL);


上記関数を呼び出すことによりスレッドが動作します。




■クラス内に作成した関数をスレッドで動作させる
スレッドとして動作する関数を含んだクラス

class CThreadTestDlg
{
CWinThread* pThread;
static UINT Thread1( LPVOID pvParam );// スレッドは外部関数か static メンバしか呼べないため
};
//スレッドのメイン
UINT CThreadTestDlg::Thread1( LPVOID pvParam )
{
  while(true){
  //  Sleep(500);
    TRACE("%d",10);
  }
    return(0);
}

▼上記クラスの関数をスレッドとして動作させる

//生成とコントロール
pThread = AfxBeginThread((AFX_THREADPROC)Thread1,
                        (LPVOID)this,      // このクラスをパラメータとして渡しています
                        THREAD_PRIORITY_NORMAL,
                        0,
                        CREATE_SUSPENDED);//スタート時からサスペンド

//pThread->SuspendThread();//スレッドのサスペンド
pThread->ResumeThread();//スレッドのレジューム


上記関数を呼び出すことによりスレッドが動作します。




■スレッドからダイアログのメソッドや変数にアクセスする
スレッドを作成するときにパラメータとして渡したpvParamを使ってアクセスします


UINT CThreadTestDlg::Thread1( LPVOID pvParam )
{
      while(true){
           Sleep(1000);
           ((CThreadTestDlg*)pvParam)->m_Button1.EnableWindow(false);
         //((CThreadTestDlg*)pvParam)->GetDlgItem(IDC_BUTTON2)->EnableWindow(false);
           Sleep(1000);
           ((CThreadTestDlg*)pvParam)->m_Button1.EnableWindow(true);
      }
      return(0);
}


■クリティカルセッション
ミューティクスオブジェクトによりスレッドがぶつかるのを防ぎます


HANDLE     hIOMutex = CreateMutex (NULL, FALSE, NULL);//ミューティクスオブジェクトを作成
//↑グローバルで宣言

void CThreadTestDlg::brink(void){
     WaitForSingleObject( hIOMutex, INFINITE );//排他処理の開始

     //処理内容

     ReleaseMutex( hIOMutex);//排他処理の終了
}


▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼例外処理▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■例外処理の受け取り

try{  }catch(...){  } //すべての例外を取得


■例外の送出

▼例外クラスを作成します

class err{
public:
     CString str;
     err(){str="エラー";}
};


▼プログラム中においての例外の送出
例外errクラスがtry{}catchで囲まれた中で送出されることにより、
処理がcatchに飛び、catch(err x)で例外がキャッチされ例外処理が行われます

try{

     throw err();//エラーを仮定して、例外errクラスを送出します

}catch(err x){

     //errクラスを受け取った時の例外
     MessageBox(x.str);

}catch(...){
     //その他の例外
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼アプリケーションの終了▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

this->SendMessage( WM_CLOSE, (WPARAM)NULL, (LPARAM)NULL );
もしくは
AfxGetMainWnd()->PostMessage(WM_CLOSE);

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼二重起動禁止▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

ソフトのイニシャル部分でミューテックスオブジェクトを作成することにより二重起動を防止します


BOOL CAaaApp::InitInstance()
{
  AfxEnableControlContainer();
//↓ここから
  HANDLE m_hMutex;  //ミューテックスオブジェクトのハンドル
  m_hMutex = CreateMutex(NULL, TRUE, "任意の識別名");
  if ( GetLastError() == ERROR_ALREADY_EXISTS ){
    //既に同じ名前で起動されている場合
    //起動せずに終了する処理をここに書く
    AfxMessageBox("既に起動しています。");
    return FALSE;
  }
//ここにいろいろな処理があり、
//一番最後にて
  ReleaseMutex(m_hMutex);
  return FALSE;
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼イベント▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■重い処理中にイベントをシステムに戻す

while(true){  
    MSG message;
    if(::PeekMessage(&message, NULL, 0, 0, PM_REMOVE)){
        ::TranslateMessage(&message);
        ::DispatchMessage(&message);
    }
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼コントロールの動的貼り付け▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■CEdit-------------------------------------------

void CDsdsdsDlg::OnButton1()
{
RECT r;
r.top =10;  //上の座標
r.bottom =30;  //下の座標
r.left =10;  //左の座標
r.right=100;  //右の座標

CEdit* pEdit = new CEdit();
pEdit->Create(WS_VISIBLE | WS_CHILD | WS_TABSTOP, r, this,100);
pEdit->ModifyStyleEx(0,WS_EX_CLIENTEDGE,SWP_DRAWFRAME);
//pEdit->DestroyWindow();//オブジェクトの破棄
}
void CDsdsdsDlg::OnButton2()
{
GetDlgItem(100)->SetWindowText("test");//このようにして使います。
//GetDlgItem(100)->DestroyWindow();//オブジェクトの破棄もできます。
}

■CStatic------------------------------------------

RECT r;
r.top =10;  //上の座標
r.bottom =30;  //下の座標
r.left =10;  //左の座標
r.right=100;  //右の座標
  
CStatic* pStatic = new CStatic();
pStatic->Create("static text" ,WS_VISIBLE | WS_CHILD ,r, this,1000);

■CEditの継承と動的配置-----------------------------------

class editX : public CEdit{
public:
  void test(void){
    SetWindowText("test");
  }
};

RECT r;
r.top =10;  //上の座標
r.bottom =30;  //下の座標
r.left =10;  //左の座標
r.right=100;  //右の座標

editX* pEdit = new editX();
pEdit->Create(WS_VISIBLE | WS_CHILD | WS_TABSTOP, r, this,1000);
pEdit->ModifyStyleEx(0,WS_EX_CLIENTEDGE,SWP_DRAWFRAME);
pEdit->test();
//pEdit->DestroyWindow();//オブジェクトの破棄

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼数字しか入力できないCEditとサブクラス化▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

挿入→クラスの新規作成→クラス名と基本クラスを入力して
CEdit を継承したクラスを作成します。
Class Wizard や プロジェクトワークスペース にて
WM_CHARのメッセージハンドラを作成します。
次のように変更します。

void edit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
  if( nChar == VK_BACK    ||
    nChar == VK_DELETE  ||
    nChar == VK_TAB      )
    // Backspace、Delete、Tabの場合は、
    // 既存のハンドラ呼び出し。
  {
  CEdit::OnChar(nChar, nRepCnt, nFlags);
  return;
  }
  // 0〜9以外の場合は、何も行わずに終了。
  // 0〜9までは、既存のハンドラ呼び出し。
  if( !(nChar >= '0' && nChar <= '9'))
  {
    return;
  }
  CEdit::OnChar(nChar, nRepCnt, nFlags);
}

あとはCEditを動的配置して使うか、
サブクラス化(自前のプロシージャと差し替え)により、
ダイアログに貼り付けたCEditと数字しか入力できないテキストボックスの入れ替えができます。
IDC_EDIT2がダイアログに貼り付けてあるCEditです。

edit* pEdit = new edit();
pEdit->SubclassDlgItem(IDC_EDIT2,this);

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ファイル処理▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼


■ファイルの存在チェック

// CFileクラスの静的メンバGetStatus()を使ってファイルの存在チェックを行うサンプル
CFileStatus status;
if(CFile::GetStatus(_T("c:\\autoexec.bat"), status)){
    TRACE(_T("c:\\autoexec.batは存在します"));
}else{
    TRACE(_T("c:\\autoexec.batは存在しません"));
}


■一行読み込み

FILE * fp;
if((fp=fopen("test.txt","r"))==NULL){
    //エラー処理
}else{
    //ファイルからの一行入力
    char buf[256]="";
    fgets(buf,256,fp);
            //---←読み出す最大数
    CString str=buf;
    m_edit1.SetWindowText(str);
    fclose(fp);
}


■一行書き込み

FILE * fp;
if((fp=fopen("test.txt","w"))==NULL){
    //エラー処理
}else{
    //ファイルからの一行出力
    CString str;
    m_edit1.GetWindowText(str);
    char *buf = new char[str.GetLength()+1];
    strcpy( buf, str );
    fputs(buf,fp);
    //もしくは、次のような形で指定できます
    //fprintf(fp,"%s,%d\n",CString,int);←CSVファイル形式で出力されます
    delete [] buf;
    fclose(fp);
}


■CSVファイル読み出しの考察

FILE * fp;
if((fp=fopen("test.txt","r"))==NULL){
    //エラー処理
}else{
    char buf[256]="";
    fgets(buf,256,fp);
  int c=0,valcount=0;
  CString val[7];
  while(valcount<7){
    while(buf[c]!='\0' && buf[c]!=','){
      val[valcount]+=buf[c];
      c++;
    }
    c++;
    valcount++;
  }
  TRACE("%s\n",val[0]);
  TRACE("%s\n",val[1]);
  TRACE("%s\n",val[2]);
  TRACE("%s\n",val[3]);
  TRACE("%s\n",val[4]);
  TRACE("%s\n",val[5]);
  TRACE("%s\n",val[6]);
    fclose(fp);
}


■CSVファイルをファイルの最後まで読み出す

FILE * fp;
if((fp=fopen("c:/Data2.CSV","r"))==NULL){
    //エラー処理
}else{

  char buf[256]="";
  while(fgets(buf,256,fp)!=NULL){
    int c=0,valcount=0;
    CString val[50];
    while(valcount<50){
      while(buf[c]!='\0' && buf[c]!=','){
        val[valcount]+=buf[c];
        c++;
      }
      c++;
      valcount++;
    }
    TRACE("%s\n",val[0]);
    TRACE("%s\n",val[1]);
    TRACE("%s\n",val[2]);
    TRACE("%s\n",val[3]);
    TRACE("%s\n",val[4]);
    TRACE("%s\n",val[5]);
    TRACE("%s\n",val[6]);
    TRACE("%s\n",val[7]);
    TRACE("%s\n",val[8]);
    TRACE("%s\n",val[9]);
    TRACE("%s\n",val[10]);

  }
    fclose(fp);
}


■CSVファイルをファイルの最後まで読み出す改良型

CString を使用しないことにより数倍以上に速度が上がります。
ファイルから30万件の値の読み出し+配列格納に上のコードだと、12秒ですが、これだと2秒で終了しました。

  FILE * fp;
  if((fp=fopen("c:/Data.CSV","r"))==NULL){
    //エラー処理
  }else{
  char buf[256]="";
  while(fgets(buf,256,fp)!=NULL){
    int c=0,valcount=0;
    char val[256][256];
      while(valcount<256){
        int cc=0;
        while(buf[c]!='\0' && buf[c]!=','){
          val[valcount][cc++]=buf[c++];
        }
        val[valcount][cc++]='\0';
        c++;
        valcount++;
      }
    TRACE("%s\n",val[0]);//0〜255まで
    TRACE("%s\n",val[1]);
    TRACE("%s\n",val[2]);
    TRACE("%s\n",val[3]);
    TRACE("%s\n",val[4]);
    TRACE("%s\n",val[5]);
    TRACE("%s\n",val[6]);
  }
    fclose(fp);
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼外部アプリケーションを起動する▼▼▼▼▼▼▼▼▼▼▼▼▼▼

    // C:\MyText.txtを関連付けされたアプリケーションで開く
    HINSTANCE h;    
    h = ShellExecute( m_hWnd,      
                      _T("open"),      
                      _T("C:\\MyText.txt"),      
                      NULL,      
                      NULL,      
                      SW_SHOWNORMAL);      
    if(h <= (HINSTANCE)32){      
        AfxMessageBox(_T("起動できませんでした"));      
    }

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼TCP/IPクライアント▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■WinSock2

MFCのウィザードにてソケット追加
#include "afxsock.h"    // MFC のソケット拡張機能

//MFCのウィザードにてソケット追加をする必要がありますが、追加を行わなかった場合、
//winsock2.hを自分でインクルードする必要があります
//#include "winsock2.h"

WSADATA wsaData;
char *server="localhost";
u_short port=2000;
if(WSAStartup(MAKEWORD(1, 1), &wsaData)==0){
  SOCKET s = socket(PF_INET,SOCK_STREAM,0);
  if(s!=INVALID_SOCKET){
    LPHOSTENT ipHost = gethostbyname(server);
    if(ipHost != NULL){
      SOCKADDR_IN sockadd;
      memset(&sockadd,0,sizeof(sockadd));
      sockadd.sin_family = AF_INET;
      sockadd.sin_port = htons(port);
      sockadd.sin_addr = *((LPIN_ADDR)*ipHost->h_addr_list);
      if(connect(s,(PSOCKADDR)&sockadd,sizeof(sockadd))==0){
        int nRtn;
        nRtn = send(s,"test",(int)sizeof("test"),0);//送信
        char buff[1024]="";
        nRtn = recv(s,buff,(int)sizeof(buff),0);//受信
        //MFC以外では、recv(s,buff,(int)sizeof(buff),-1,0)
        TRACE(buff);
        //nRtn==0        接続が終了しました
        //nRtn==SOCKET_ERROR  エラー
      }else{
        //接続失敗
      }
    }else{
      //接続先が見つかりません
    }
    closesocket(s);
    WSACleanup();
  }
}


■上記プログラムをメソッドに修正しました

char* TCPSendToRead(char *server,u_short port,char* sendWord){
  WSADATA wsaData;
  char buff[1024]="";
  if(WSAStartup(MAKEWORD(1, 1), &wsaData)==0){
    SOCKET s = socket(PF_INET,SOCK_STREAM,0);
    if(s!=INVALID_SOCKET){
      LPHOSTENT ipHost = gethostbyname(server);
      if(ipHost != NULL){
        SOCKADDR_IN sockadd;
        memset(&sockadd,0,sizeof(sockadd));
        sockadd.sin_family = AF_INET;
        sockadd.sin_port = htons(port);
        sockadd.sin_addr = *((LPIN_ADDR)*ipHost->h_addr_list);
        if(connect(s,(PSOCKADDR)&sockadd,sizeof(sockadd))==0){
          int nRtn;
          //ポインタで渡された送信文字列はsizeofが使えないため
          //文字数をカウントします
          for(int i=0;sendWord[i]!='\0';i++);
          nRtn = send(s,sendWord,i,0);//送信
          nRtn = recv(s,buff,(int)sizeof(buff),0);//受信
          //MFC以外では、recv(s,buff,(int)sizeof(buff),-1,0)
          //nRtn==0        接続が終了しました
          //nRtn==SOCKET_ERROR  エラー
        }else{
          //接続失敗
        }
      }else{
        //接続先が見つかりません
      }
      closesocket(s);
      WSACleanup();
    }
  }
  return buff;
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼TCP/IPサーバー▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

MFCのウィザードにてソケット追加する必要があります。


int tcpServer(){
  u_short uport = 1000;//待機するポート
  WSADATA wsaData;
  if (WSAStartup(MAKEWORD(1, 1), &wsaData)) {//WinSockの初期化失敗
    WSACleanup();
    return -1;
  }
  SOCKET listen_s = socket(AF_INET, SOCK_STREAM, 0);
  if (listen_s < 0) {//ソケットのオープン失敗
    WSACleanup();
    return -2;
  }
  SOCKADDR_IN saddr;
  memset(&saddr, 0, sizeof(SOCKADDR_IN));
  saddr.sin_family = AF_INET;
  saddr.sin_port = htons(uport);
  saddr.sin_addr.s_addr = INADDR_ANY;
  if (bind(listen_s, (struct sockaddr *)&saddr, sizeof(saddr)) == SOCKET_ERROR) {//バインドエラー
    closesocket(listen_s);
    WSACleanup();
    return -3;
  }
  if (listen(listen_s, 0) == SOCKET_ERROR) {
    closesocket(listen_s);
    WSACleanup();
    return -4;
  }
  SOCKADDR_IN from;
  int fromlen = (int)sizeof(from);
  SOCKET s = accept(listen_s, (SOCKADDR *)&from, &fromlen);//接続されるまでここで待機
  if (s == INVALID_SOCKET) {
    closesocket(listen_s);
    WSACleanup();
    return -5;
  }
  closesocket(listen_s);//この接続待ちソケットはもう必要ない

  while (true) {
    char buff[1024]="";
    int nRcv = recv(s, buff, sizeof(buff) - 1, 0);
    if (nRcv == SOCKET_ERROR) break;//recvエラー
    buff[nRcv] = '\0';
    if (strcmp(buff, "c_end") == 0) break;//クライアントが切断
    TRACE(buff);//受信文字列

    char *sendBuff="Hello Server";//送信文字列
    if (strcmp(sendBuff, "s_end") == 0) {
      send(s, sendBuff, (int)strlen(sendBuff), 0);
      break;
    }
    send(s, sendBuff, (int)strlen(sendBuff), 0);
  }
  closesocket(s);
  WSACleanup();
  return 0;
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼時間の取得▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

GetCurrentTimeはスタティック関数ですのでCTimeオブジェクトを作成する必要はありません

CTime curTime=CTime::GetCurrentTime();
CString str=curTime.Format("%H:%M:%S");



▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ダイアログの背景色の変更▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■クラスウィザードでWM_CTLCOLORのメッセージハンドラを追加し、以下の処理を行います。

HBRUSH CColorTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
  CBrush* m_pBrush = new CBrush(RGB(255, 0, 0));
  switch (nCtlColor) {
    case CTLCOLOR_DLG: //ダイアログ ボックス
    //case CTLCOLOR_BTN: // ボタン コントロール
    //case CTLCOLOR_EDIT: //エディット コントロール
    //case CTLCOLOR_LISTBOX: //リスト ボックス コントロール
    //case CTLCOLOR_MSGBOX: //メッセージ ボックス
    //case CTLCOLOR_SCROLLBAR: //スクロール バー コントロール
    //case CTLCOLOR_STATIC: //スタティック コントロール
      
      return (HBRUSH)(m_pBrush->GetSafeHandle());

    default:
      return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
  }
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼スタティックテキストおよびエディットの背景色の変更▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■クラスウィザードでWM_CTLCOLORのメッセージハンドラを追加し、以下の処理を行います。

HBRUSH CColorTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
  CBrush* m_pBrush = new CBrush(RGB(255, 0, 0));
  switch (nCtlColor) {
    //case CTLCOLOR_DLG: //ダイアログ ボックス
    //case CTLCOLOR_BTN: // ボタン コントロール
    //case CTLCOLOR_EDIT: //エディット コントロール
    //case CTLCOLOR_LISTBOX: //リスト ボックス コントロール
    //case CTLCOLOR_MSGBOX: //メッセージ ボックス
    //case CTLCOLOR_SCROLLBAR: //スクロール バー コントロール
    case CTLCOLOR_STATIC: //スタティック コントロール
      pDC->SetTextColor(RGB(255,255,255));//テキストの色
      pDC->SetBkMode(TRANSPARENT);//「テキストが書かれている部分」の背景色を透明なブラシで塗る
      return (HBRUSH)(m_pBrush->GetSafeHandle());
    default:
      return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);//コントロールの色
  }

}

■コントロールごとに色を設定する

  switch (nCtlColor) {
    //case CTLCOLOR_DLG: //ダイアログ ボックス
    //case CTLCOLOR_BTN: // ボタン コントロール
    case CTLCOLOR_EDIT: //エディット コントロール
    //case CTLCOLOR_LISTBOX: //リスト ボックス コントロール
    //case CTLCOLOR_MSGBOX: //メッセージ ボックス
    //case CTLCOLOR_SCROLLBAR: //スクロール バー コントロール
    //case CTLCOLOR_STATIC: //スタティック コントロール
      if(IDC_EDIT6==pWnd->GetDlgCtrlID()){  //IDC_EDIT6の設定
      CBrush* m_pBrush = new CBrush(RGB(255, 0, 0));
      pDC->SetTextColor(RGB(255,255,255));//テキストの色
      pDC->SetBkMode(TRANSPARENT);//「テキストが書かれている部分」の背景色を透明なブラシで塗る
      return (HBRUSH)(m_pBrush->GetSafeHandle());
      }
      if(IDC_EDIT7==pWnd->GetDlgCtrlID()){  //IDC_EDIT7の設定
      CBrush* m_pBrush = new CBrush(RGB(0, 255, 0));
      pDC->SetTextColor(RGB(255,255,255));//テキストの色
      pDC->SetBkMode(TRANSPARENT);//「テキストが書かれている部分」の背景色を透明なブラシで塗る
      return (HBRUSH)(m_pBrush->GetSafeHandle());
      }
    default:
      return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);//コントロールの色
  }

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ボタンの背景色の変更▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

ボタンのプロパティーにてビットマップにチェックをつける

■グローバルにて宣言

CBitmap m_zBitmap;

//■ボタンにビットマップを貼り付けて初期設定(一度しか実行できない)
//**************************************************
// ボタンのサイズを取得
CButton* pzButton = (CButton *)GetDlgItem(IDC_BUTTON5);
RECT zButtonRect;
pzButton->GetClientRect( &zButtonRect );
int iWidth = zButtonRect.right;
int iHeight = zButtonRect.bottom;
// ボタンに色を表示するための bitmap を用意
CClientDC dcScreen(this);
m_zBitmap.CreateCompatibleBitmap(&dcScreen,iWidth,iHeight);
// ボタンに張り付け
pzButton->SetBitmap( m_zBitmap );
//**************************************************

//■ボタンのビットマップの描画(何度でも実行可能)
//**************************************************
// ディスプレイの DCを取得
CClientDC dcScreen(this);
// ビットマップを描画する DCメモリの作成
CDC pDC;
pDC.CreateCompatibleDC(&dcScreen);
// ボタンのサイズを取得
RECT zButtonRect;
CButton* pzButton = (CButton *)GetDlgItem(IDC_BUTTON5);
pzButton->GetClientRect( &zButtonRect );
// 描画
CBrush zBrush( RGB(255,0,0) );//ブラシの色
CBitmap* pzOldBitmap = pDC.SelectObject( &m_zBitmap );//ビットマップを取得
pDC.FillRect( &zButtonRect, &zBrush );//塗りつぶす
pDC.SetTextColor(RGB(255,255,255));//テキストの色
pDC.SetBkMode(TRANSPARENT);//「テキストが書かれている部分」の背景色を透明なブラシで塗る
pDC.TextOut(0,0,"hello");//テキストの描画
pDC.SelectObject( pzOldBitmap );//ビットマップを戻す
pzButton->RedrawWindow();//再描画
//**************************************************

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼グラフィックス▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
描画メソッドの中で描画処理を行います

CPen Pen;
CPen *pTmpPen;
CBrush Brush;
CBrush *pTmpBrush;
Pen.CreatePen(PS_SOLID,1,RGB(255,0,0));  //ペンの作成
Brush.CreateSolidBrush(RGB(255,0,0));  //ブラシの作成
pTmpPen = pDC->SelectObject(&Pen);    //元のペンを一時退避しながら新たなペンの設定
pTmpBrush = pDC->SelectObject(&Brush);  //元のブラシを一時退避しながら新たなブラシの設定
//pDC->MoveTo(10,10);//スタート地点
//pDC->LineTo(100,100);//スタート地点からの線の描画
//pDC->Rectangle(100,100,200,200);//塗りつぶしの四角
//
//Chord・・・・・・・・・・・・・・・弦
//Ellipse・・・・・・・・・・・・・・楕円
//Pie・・・・・・・・・・・・・・・・・扇形
//Polygon・・・・・・・・・・・・・多角形
//PolyPolygon・・・・・・・・・2 つ以上の多角形
//Rectangle・・・・・・・・・・四角形
pDC->SelectObject(pTmpPen);        //ペンを戻す
pDC->SelectObject(pTmpBrush);      //ブラシを戻す
Pen.DeleteObject();
Brush.DeleteObject();



■コントロールのCDCの取得

UINT nID=IDC_STATIC;
CWnd* pWnd=GetDlgItem(nID);
CDC* pDC=pWnd->GetDC();//CDCを取得
//描画処理
//pDC->********
//
pWnd->ReleaseDC(pDC);//CDCを解放(必ず必要)


▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼クリップボード操作▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

テキストの書き込みと読み出し

//クリップボードへテキストのセット
BOOL SetClipboard(LPCTSTR text)
  {
    CString str(text);
    // クリップボードのオープン
    if( !::OpenClipboard(NULL) ) return FALSE;
    // ヒープ上にメモリ領域を確保し、文字列をコピー
    int iStrLen = str.GetLength() + 1;
    HGLOBAL hMem = ::GlobalAlloc(GMEM_FIXED, iStrLen);
    LPTSTR pMem = (LPTSTR)hMem;
    ::lstrcpy(pMem, (LPCTSTR)str);
    // クリップボードへ文字列をコピーし、クローズ
    ::EmptyClipboard();  // クリップボードの中身を空にする
    ::SetClipboardData(CF_TEXT, hMem);
    ::CloseClipboard();
    return TRUE;
  }


//クリップボードからテキストを取得
CString GetClipboard()
  {
    CString str;
    str.Empty();

    // クリップボードにテキストデータが入っているかを調べる
    if( !::IsClipboardFormatAvailable(CF_TEXT) ) return str;
    // クリップボードのオープン
    if( !::OpenClipboard(NULL) ) return str;
    // クリップボードからデータを取得し、strTextへコピー
    HANDLE hMem = ::GetClipboardData(CF_TEXT);
    LPTSTR pMem = (LPTSTR)::GlobalLock(hMem);
    ::lstrcpy((LPTSTR)(LPCTSTR)str, pMem);
    ::GlobalUnlock(hMem);
    ::CloseClipboard();
    return str;
  }

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼MFCでのレジストリ操作▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

レジストリに記録するには、まずC..App::InitInstanceで記録する場所を指定します。
この作業を省略するとINIファイルに記録されます。

BOOL C..App::InitInstance()
{
  AfxEnableControlContainer();
  SetRegistryKey("test\\testApp");//←ここ

上記の例の場合、HKEY_CURRENT_USER\Software\test\testApp\プロジェクト名\に記録されます。
(INIファイルに記録する場合は関係ありません)
INIファイルに記録する場合は、Windowsフォルダ\プロジェクト名.INIに記録されます。


■キーの作成&データの書き込み

文字列を書き込む場合はWriteProfileString、数値を書き込む場合はWriteProfileIntを使います。
3番目の引数には、書き込む値を設定します。下記の例のイメージとしては、
aという名前のフォルダにあるbというファイルの内容にtestTextという値を書き込むような感じです。

CWinApp* pApp = AfxGetApp();
pApp->WriteProfileString("a", "b", "testText");
//pApp->WriteProfileInt("a", "b", 100);


■データの読み込み

文字列を読み込む場合はGetProfileString、数値を読み込む場合はGetProfileIntを使います。
3番目の引数には、キーが存在しなかった場合に返すデフォルト値です。

CWinApp* pApp = AfxGetApp();
CString str = pApp->GetProfileString("a", "b", "");
//int n = pApp->GetProfileInt("a", "b",0);


▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼SDIの描画▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

View.cppのOnDraw( ) 関数には最初から GetDocument() によって、 Document クラスへのポインターが
pDoc に代入されているので、Document クラスの public で宣言された変数やメソッドは
pDoc->
のようにしてアクセスすることができる

pDC->TextOut(0,0,"てすと");
にてテキストを描画できます

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼フォント▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

■フォントの指定

LOGFONT logfont;    //フォント構造体
logfont.lfHeight =-20;    //文字セルまたは文字の高さ
logfont.lfWeight=0;    //平均文字幅
logfont.lfEscapement=0;  //文字送りの方向とX軸との角度
logfont.lfOrientation=0;  //ベースラインとX軸との角度
logfont.lfWeight=0;    //フォントの太さ
logfont.lfItalic=0;    //イタリック体指定
logfont.lfUnderline =0;  //下線付き指定
logfont.lfStrikeOut =0;  //打ち消し線付き指定
logfont.lfCharSet =0;    //キャラクタセット 0=ANSI_CHARSET
logfont.lfOutPrecision = OUT_STROKE_PRECIS;//出力精度
logfont.lfClipPrecision = CLIP_STROKE_PRECIS;//クリッピングの精度
logfont.lfQuality = PROOF_QUALITY;//出力品質
logfont.lfPitchAndFamily = DEFAULT_PITCH;//ピッチとファミリ
//FIXED_PITCH=固定幅  VARIABLE_PITCH=可変幅
sprintf(logfont.lfFaceName,"%s","MS Pゴジック");//フォント名
//空文字列を指定すると、ほかのメンバで指定された属性に合うフォントの中から
//最初に見つけられたフォントが選択されます。


■*View.cppのOnDrawメソッドにて上で指定したフォントを使い描画します

CFont font;      //フォント変数
font.CreateFontIndirect(&logfont);  //フォントの作成
pDC->SelectObject(font);    //フォントの設定
pDC->TextOut(0,0,"");    //描画
font.DeleteObject();      //フォントの削除

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼色▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

COLORREF color1=RGB(255,0,0);
COLORREF color2=RGB(0,0,255);
pDC->SetBkColor(color1);
pDC->SetTextColor(color2);

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼メニュー▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

メニュー項目のプロパティにおいてキャプションには、項目名(&h) のように設定します
(&h)はALT+Hの組み合わせを表すショートカットキーです

プロパティのプロンプトの部分に値を入れると、メニューを選択した時に内容がステータスバーに表示されます。


■イベントの作成はメニューリソースをボタンなどと同じようにクラスウィザードで作成できます。
クラスウィザードでのメッセージの種類

COMMAND    メッセージが選択された時に実行

UPDATE_COMMAND_UI  メニューが表示されるときに実行、引数pCmdUIにメニューのオブジェクトのポインタが入ってます
    メニューの状態を変更することができます  pCmdUI->Enable(false);//メニュー無効に切り替える


■起動時からメニューを表示させないようにする

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if(cs.hMenu != NULL){
        ::DestroyMenu(cs.hMenu);      // ロードされているメニューを破棄
        cs.hMenu = NULL;
    }
    return CFrameWnd::PreCreateWindow(cs);
}

▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼SDI描画のタイマー▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

▼クラスウィザードを使い*View.cppに次のメッセージの関数を作成します

WM_CREATE
WM_TIMER


▼OnCreate関数に適当なタイマーIDで再描画のタイマーを生成します

SetTimer(1015, 500, NULL);

▼OnTimer関数内で上で作成したタイマーにより再描画を行います

if (nIDEvent == 1015){
 KillTimer(1015);//停止

 Invalidate(false);//背景を消去せずに描画

 SetTimer(1015, 500, NULL);//開始
}



▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼再描画を行う▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
再描画を行う関数です。

■*View.cppから再描画させるには、

Invalidate(false);//背景を消去しない

■*Doc.cppから再描画させるには、

UpdateAllViews(NULL);

■ダイアログから再描画させるには、

Invalidate();


▲トップページ > Windows と C++