【VC++】メールスロットで単方向プロセス間通信を行う

0

    <機能>

    (1)メールスロットクライアントとサーバを作成します

    (2)メールスロットを使って2つのexe間でプロセス間通信を行います

    (3)クライアントは[送信]ボタン押下によりメッセージを送付します

    (4)サーバは受信メッセージをリストボックスに表示します

    (5)クライアント起動時にサーバも起動します

     (サーバからクライアントの起動ななし)

     

    <実行イメージ>

    上の実行ファイルはメールスロットクライアント(MFCApplication1)

    下の実行ファイルはメールスロットサーバ(MFCApplication2)

    MFC,VisualStudio,MailSlot,実行サンプル,
     

    <動作検証&開発環境>
    Visual Studio Community 2017

     

    <使い方>

    1.MFCApplication1プロジェクトを作成します

    2.MFCApplication1ソリューションにMFCApplication2プロジェクトを追加します

     (どちらもダイアログベースです)

     

    サンプルのソリューション構成

    MFCApplication1(ソリューションフォルダ)

     Debug

     MFCApplication1(プロジェクトフォルダ)

     MFCApplication2(プロジェクトフォルダ)

     Release

     MFCApplication1.sln

     

    3.コントロールを追加

    MFCApplication1

    MFC,VisualStudio,MailSlot,送信,
     

    MFCApplication2

    MFC,VisualStudio,MailSlot,受信,
     

    4.メンバ変数を追加

    MFCApplication1

     IDC_EDIT1:

    MFC,VisualStudio,MailSlot,送信,メンバ変数追加,クラスウィザード,
     

    MFCApplication2

     IDC_LIST1:

    MFC,VisualStudio,MailSlot,受信,メンバ変数追加,クラスウィザード,
     

    5.MFCApplication2にイベントを追加

     WM_TIMER(タイマーイベントでメッセージを受信)

     WM_DESTROY(画面終了イベントでメールスロットとタイマー停止)

    MFC,VisualStudio,MailSlot,受信,イベント追加,クラスウィザード,
     

    5.ソースを追加

     

    MFCApplication1(クライアント「送信」側アプリ)

     

    MFCApplication1Dlg.h

    class CMFCApplication1Dlg : public CDialog
    {
    //〜省略〜
    // 実装
    protected:
        HICON m_hIcon;
        // 生成された、メッセージ割り当て関数
        virtual BOOL OnInitDialog();
        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        DECLARE_MESSAGE_MAP()
    private:
        CString m_sendEdt;
        HANDLE m_mailSlot;
    public:
        afx_msg void OnBnClickedButton1();
    };

     

    MFCApplication1Dlg.cpp

     

    BOOL CMFCApplication1Dlg::OnInitDialog()

    {
        //〜省略〜〜
        //受信側(MFCApplication2.exe)も一緒に起動する
        //※本サンプルでは受信側と送信側が同一フォルダに出力されているものとしますが実行環境に合わせて修正してください

        TCHAR buf[2048];
        ZeroMemory(&buf, sizeof(buf));
        GetModuleFileName(NULL, buf, sizeof(buf));
        size_t ichi = wcslen(buf) - wcslen(L"MFCApplication1.exe");
        //送信側(MFCApplication1.exe)実行ファイル名を受信側(MFCApplication2.exe)に置換
        wmemcpy_s(&buf[ichi],wcslen(buf), L"MFCApplication2.exe", wcslen(L"MFCApplication2.exe")*2);
        //受信側(MFCApplication2.exe)を起動
        ShellExecute(NULL, L"open", buf, NULL, NULL, SW_HIDE);
        //エディットボックスを初期化
        m_sendEdt = L"";
        UpdateData(FALSE);
        return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
    }
     
    /*************************************************
    関数名 OnBnClickedButton1
    機能   送信ボタン押下イベント
    *************************************************/

    void CMFCApplication1Dlg::OnBnClickedButton1()
    {
        CString csError;
        TCHAR cName[256];
        ZeroMemory(&cName,sizeof(cName));
        //エディットボックスの入力値を取得
        UpdateData(TRUE);
        m_sendEdt = m_sendEdt.Trim();
        //メッセージが未入力ならエラーとする
        if (m_sendEdt.IsEmpty())
        {
            AfxMessageBox(L"送信文字列を入力してください",MB_ICONERROR);
            return;
        }
        //コンピュータ名を取得
        //※本サンプルでは同一コンピュータに送信する

        DWORD wksize = sizeof(cName);
        if (!GetComputerName(cName, &wksize))
        {
            AfxMessageBox(L"コンピューター名の取得に失敗しました", MB_ICONERROR);
            return;
        }
        //メールスロットを作成
        //メールスロットの名前は ¥¥mailslot¥¥MailSlot とする

        //詳細はMSDN参照
        CString csSlot;
        csSlot.Format(L"¥¥¥¥%s¥¥mailslot¥¥MailSlot", cName);
        HANDLE hSlot = CreateFile(csSlot, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ,
                                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hSlot == INVALID_HANDLE_VALUE)
        {
            csError.Format(L"MailSlotの作成に失敗しました(ErrorCode=%d)¥r¥n%s",GetLastError(),csSlot);
            AfxMessageBox(csError, MB_ICONERROR);
            return;
        }
        //メッセージの送信
        LPTSTR cMsg = new TCHAR[2048];
        DWORD dwSize;
        DWORD dwWrite;
        BOOL bResult;
        //dwSize = wcslen(cMsg);
        dwSize = wsprintf(cMsg, L"%s", m_sendEdt);
        bResult = WriteFile(hSlot, cMsg, dwSize * 2, &dwWrite, NULL);
        if (!bResult) {
            csError.Format(L"MailSlotの送信に失敗しました(ErrorCode=%d)¥r¥n%s", GetLastError(), csSlot);
            AfxMessageBox(csError, MB_ICONERROR);
        }
        CloseHandle(hSlot);
        delete cMsg;
    }

     

    MFCApplication2(サーバ「受信」側アプリ)

     

    MFCApplication2Dlg.h
    class CMFCApplication2Dlg : public CDialog
    {
    //〜省略〜〜
    // 実装
    protected:
        HICON m_hIcon;
        // 生成された、メッセージ割り当て関数
        virtual BOOL OnInitDialog();
        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        DECLARE_MESSAGE_MAP()
    private:
        HANDLE m_Slot;
    public:
        afx_msg void OnTimer(UINT_PTR nIDEvent);
        afx_msg void OnDestroy();
    private:
        CListBox m_recvList;
    };
     
    MFCApplication2Dlg.cpp
    BOOL CMFCApplication2Dlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
       
        //〜省略〜〜
       
        //メールスロットを作成
        //メールスロットの名前は ¥¥mailslot¥¥MailSlot とする
        //メッセージの最大長(バイト数):0(任意サイズ)
        //メッセージ読み取りタイムアウト値(ms)
        //詳細はMSDN参照

        m_Slot = CreateMailslot(L"¥¥¥¥.¥¥mailslot¥¥MailSlot", 0, 1000, NULL);
        if (m_Slot == INVALID_HANDLE_VALUE)
        {
            CString csError;
            csError.Format(L"メールスロット作成に失敗しました(ErrorCode=%d)", GetLastError());
            AfxMessageBox(csError, MB_ICONERROR);
            return FALSE;
        }
        //タイマースタート
        //1000(ms)ごとにチェック
        //コールバック関数なし

        SetTimer(DTIMER_ID, 1000, NULL);
        return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
    }
    /*************************************************
    関数名 OnTimer
    機能   タイマーイベントで受信をチェック
    *************************************************/

    void CMFCApplication2Dlg::OnTimer(UINT_PTR nIDEvent)
    {
        TCHAR cMsg[2048];
        DWORD dwRead;
        BOOL bResult;
        CString csMsg;
       
        //タイマー停止
        KillTimer(DTIMER_ID);
        //メッセージがあれば処理する
        MSG msg;
        while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
       
        //メッセージの読み取り
        //詳細はMSDN参照

        ZeroMemory(&cMsg, sizeof(cMsg));
        bResult = ReadFile(m_Slot, cMsg, sizeof(cMsg), &dwRead, NULL);
        if(bResult)
        {
            //リストボックスに表示
            CTime ct;
            ct = CTime::GetCurrentTime();
            csMsg.Format(L"%04d/%02d/%02d %02d:%02d:%02d : %s", ct.GetYear(), ct.GetMonth(),
                ct.GetDay(), ct.GetHour(), ct.GetMinute(), ct.GetSecond(), cMsg);
            m_recvList.InsertString(-1, csMsg);
            UpdateData(FALSE);
        }else
        {
            LRESULT lrlt = GetLastError();
            if ((lrlt == ERROR_SEM_TIMEOUT) || (lrlt == ERROR_ACCESS_DENIED)) {
                //メッセージがタイムアウトのときエラーを出さない
                //別のエラーが出るようならエラーコードを追加する

            }
            else {
                csMsg.Format(L"MailSlotのメッセージ読み取りに失敗しました(ErrorCode=%d)", lrlt);
                AfxMessageBox(csMsg, MB_ICONERROR);
                SetTimer(DTIMER_ID, 1000, NULL);
            }
        }
        //タイマー起動
        SetTimer(DTIMER_ID, 1000, NULL);
        CDialog::OnTimer(nIDEvent);
    }
     
    /*************************************************
    関数名 OnDestroy
    機能   アプリケーションの終了処理
    *************************************************/

    void CMFCApplication2Dlg::OnDestroy()
    {
        CDialog::OnDestroy();
        //タイマー停止
        KillTimer(DTIMER_ID);
        //メールスロットを閉じる
        if (m_Slot != INVALID_HANDLE_VALUE)
        {
            CloseHandle(m_Slot);
        }
    }
     

    よろしければポチッと押してください

    プログラマー ブログランキングへ

     


    【VC++】ピクチャーボックスに画像を表示する

    0

      <機能>

      (1)ピクチャーボックスに直接絵をかきます

      (2)ピクチャーボックスに任意の画像を表示します

        (2)-1.画像を表示する際にピクチャーボックスのサイズに伸縮します

        (2)-2.伸縮画像が劣化しないように伸縮モードを指定します

       

      <実行イメージ>

      上はピクチャーボックスに直接グラデーションを描画

      下はJPEGをピクチャーボックスに表示(伸縮して表示)

      VC,MFC,PICTURECONTROL,伸縮,DC,描画モード,HALFTONE,
       

      <動作検証&開発環境>
      Visual Studio Community 2017

       

      <使い方>

      1.MFCのダイアログベースアプリケーションを作成します

        ※サンプルではプロジェクト名をPictureTestとします

      VC,MFC,PICTURECONTROL,伸縮,DC,ダイアログベース,ウィザード,
       

      2.リソースファイル(PictureTest.rc)を開いて"言語 17、"を""LANGUAGE 17,"に修正

        ※ダイアログベースでビルドエラー参照

      3.ダイアログにコントロールを追加

        ・ピクチャーボックス:IDC_PICTURE1/IDC_PICTURE2

        ・ボタンはIDOKをそのまま使用

      VC,MFC,PICTURECONTROL,伸縮,DC,描画モード,ウィザード,
       

      4.ピクチャーボックスにメンバ変数を追加

        ・IDC_PICTURE1 : m_Picture1(コントロール変数)

        ・IDC_PICTURE2 : m_Picture2(コントロール変数)

      VC,MFC,PICTURECONTROL,伸縮,DC,描画モード,メンバ変数追加ウィザード,
       

      5.メンバ関数setPictureControl()を追加

      VC,MFC,PICTURECONTROL,伸縮,DC,描画モード,メンバ関数追加ウィザード,
       

      6.ONOKのボタン押下イベント追加

      7.ソースを追加

       

      PictureTestDlg.h

      private:
       //ピクチャーコントロールの描画エリア
       RECT rect1, rect2;
       //ピクチャーコントロールへの描画処理
       void setPictureControl();
      public:
       afx_msg void OnBnClickedOk();
       CStatic m_Picture2;
       CStatic m_Picture1;

       

      PictureTestDlg.cpp

      BOOL CPictureTestDlg::OnInitDialog()

      {

          //~~省略~~

          //ピクチャーコントロールの幅と高さを取得
          m_Picture1.GetWindowRect(&rect1);
          m_Picture2.GetWindowRect(&rect2);

          //~~省略~~
      }

       

      /*************************************************
      関数名 setPictureControl
      機能   ピクチャーコントールに描画する
      *************************************************/

      void CPictureTestDlg::setPictureControl()
      {
          CDC *cdc;
          int iWidth, iHeight;

       

          //IDC_PICTURE1にグラデーションを直接描画
          cdc = m_Picture1.GetDC();
          iWidth = rect1.right - rect1.left;
          iHeight = rect1.bottom - rect1.top;
          for (int y = 0; y < iHeight; y++) {
              for (int x = 0; x < iWidth; x++) {
                  COLORREF clr = RGB(0,x * 0xff / iWidth, 0);
                  SetPixel(cdc->GetSafeHdc(), x,y,clr);
              }
          }

       

          //IDC_PICTURE2にファイルを描画
          cdc = m_Picture2.GetDC();
          iWidth = rect2.right - rect2.left;
          iHeight = rect2.bottom - rect2.top;

       

          //読み込む画像ファイルパス
          TCHAR buf[2048];
          CString cs;
          ZeroMemory(&buf, sizeof(buf));
          GetModuleFileName(NULL, buf, sizeof(buf));
          cs.Format(L"%s",buf);
          cs = cs.Left(cs.ReverseFind('¥¥')) + L"¥¥Sample.jpg";
         
          CImage img;
          HRESULT ret = img.Load(cs);
          if (img.IsNull()) {
              AfxMessageBox(L"画像の読み込み失敗",MB_ICONERROR);
              return;
          }
          //StretchBltで描画領域に合わせてリサイズ
          CDC bmpDC;
          CBitmap *cbmp;
          cbmp = CBitmap::FromHandle(img);
          bmpDC.CreateCompatibleDC(cdc);
          CBitmap *oldbmp = bmpDC.SelectObject(cbmp);
          //伸縮すると画像が汚くなるので伸縮モードを指定
          //詳細は
      MSDN参照
          cdc->SetStretchBltMode(STRETCH_HALFTONE);
          //ブラシのずれを防止するためSetBrushOrgExを呼び出す
          cdc->SetBrushOrg(0, 0);
          //画像を伸縮してピクチャーボックスに表示
          //詳細は
      MSDN参照
          cdc->StretchBlt(0,0,iWidth,iHeight,&bmpDC,0,0,img.GetWidth(),img.GetHeight(),SRCCOPY);
          bmpDC.SelectObject(oldbmp);
          //後片付け
          cbmp->DeleteObject();
          bmpDC.DeleteDC();
          ReleaseDC(cdc);
      }

       

      /*************************************************
      関数名 OnBnClickedOk
      機能   OKボタン押下イベントハンドラ
      *************************************************/

      void CPictureTestDlg::OnBnClickedOk()
      {
          setPictureControl();
      }

       

      よろしければポチッと押してください

      プログラマー ブログランキングへ

       


      【VC++】VS2017のダイアログベースでビルドエラーとなる場合の対応

      0

        <現象>

        Visual Studio2017のダイアログベースでリソースを編集するとビルドエラーとなる

        (英語版では発生しないが日本語版では発生する)

        RC2135 file not found

        VC++,RC2135file not found,MFC,
         

        再現手順は以下の通り

        1.Visual Stuido2017でダイアログベースアプリのプロジェクト作成

        2.ダイアログにエディットボックスなどを追加

        3.ビルドするとエラーとなる

         

        ちょっとはまったので、私の環境で行ったことをメモとして残します

         

        Visual Stuido2017も最初は大丈夫だった気がする、、、

        アップデートでしこまれたバグだと思われますが早く修正してほしい!!!

         

        <バージョン>

         

        Visual Studio Community 2017

        Version 15.5.6

         

        <ダイアログアプリ作成方法>

         

        行ったこと

        (1)MFC と ATL のサポート(x86 と x64)をインストール

        Visual Studioメニューの[ツール]→[ツールと機能を取得]または

        WindowsメニューのVisual Studio Installerを選択
        VC++,ツール,ツールと機能,VS2017,MFC,
         

        (2)新規プロジェクトを作成

        (3)MFCアプリケーションを選択
        VC++,ウィザード,VS2017,MFC,
         

        (4)アプリケーションの種類でダイアログベースを選択して[完了]押下

        VC++,ウィザード,VS2017,MFC,
         

        (5)リソースファイル(.rc)を開く

        本サンプルではMFCApplication1.rcを右クリックしたコンテキストメニューで

        [コードの表示]を選択

        VC++,ウィザード,VS2017,MFC,
        (6)下記の箇所を全て修正する(「言語」「、」を修正する)

        修正前)"言語 171¥r¥n"

        修正後)"LANGUAGE 17,1¥r¥n"

        VC++,修正,VS2017,MFC,rc,リソースファイル,
         

        <確認方法>

        (1)ダイアログに確認用のGUIを追加

        VC++,修正,VS2017,MFC,確認,
         

        (2)ヘッダファイルにメンバ変数とイベント追加

        本サンプルではMFCApplication1Dlg.hに追加

         

        public:
            afx_msg void OnBnClickedCheck1();
            afx_msg void OnBnClickedButton1();

         

        private:
            CButton *cbtn;
            CButton *ccheck;
            CEdit *cedit;

         

        (3)処理を追加

         

        本サンプルではMFCApplication1Dlg.cppに追加

         

        BOOL CMFCApplication1Dlg::OnInitDialog()
        {

            //~~ 省略 ~~

            //初期化
            cbtn = (CButton*)GetDlgItem(IDC_BUTTON1);
            ccheck = (CButton*)GetDlgItem(IDC_CHECK1);
            cedit = (CEdit*)GetDlgItem(IDC_EDIT1);

         

            cbtn->SetWindowText(L"メッセージ表示");
            ccheck->SetCheck(FALSE);
            cedit->SetWindowText(L"");

         

            //~~ 省略 ~~

        }

         

        //チェックON/OFF
        void CMFCApplication1Dlg::OnBnClickedCheck1()
        {
            if (ccheck->GetCheck()) {
                cedit->SetWindowText(L"チェックはONです");
            }
            else {
                cedit->SetWindowText(L"チェックはOFFです");
            }
        }

         

        //ボタン押下
        void CMFCApplication1Dlg::OnBnClickedButton1()
        {
            AfxMessageBox(L"VisualStudio2017 MFCダイアログアプリケーション");
        }

         

        (4)ビルドして実行

         

        よろしければポチッと押してください

        プログラマー ブログランキングへ

         


        【VC++】デバイスコンテキストを使って帳票を出力する

        0

          <機能>

          (1)コモンダイアログ(印刷)を表示します

          (2)デバイスコンテキストに文字を線を描画して帳票を生成します

           (StartDoc→StartPage→EndPage→EndDoc)

          (3)サンプルとして領収書を作成します

           

          <イメージ>

          VC,デバイスコンテキスト帳票

           

          <動作検証&開発環境>

          Visual Studio Community 2017

           

          <使い方>

          Win32アプリケーションを作成します

          1.Windowsデスクトップを選択

          VC,ソリューション作成1

          2.アプリケーションの種類で「コンソールアプリケーション」を選択

          3.共通ヘッダの「MFC」にチェック

          VC,ソリューション作成2

          4.ソースを追加

           

          //プロトタイプ宣言
          void SamplePrintOut(CDC *pDC);
          void SetLogFont(CDC *pDC, LOGFONT& logfont, CString csFontName, int iSize);
          void DeleteFont();
          void LineOut(CDC *pDC, int stx, int sty, int edx, int edy);
          //フォントを宣言
          CFont *pFont10; //10ポイントのフォントを宣言
          CFont *pFont20; //20ポイントのフォントを宣言

          // 唯一のアプリケーション オブジェクトです。
          CWinApp theApp;
          using namespace std;
          int main()
          {
              int nRetCode = 0;
              HMODULE hModule = ::GetModuleHandle(nullptr);
              if (hModule != nullptr)
              {
                  // MFC を初期化して、エラーの場合は結果を印刷します。
                  if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
                  {
                      // TODO: 必要に応じてエラー コードを変更してください。
                      wprintf(L"致命的なエラー: MFC の初期化ができませんでした。¥n");
                      nRetCode = 1;
                  }
                  else
                  {

                      //コモンダイアログ[印刷]で提供されているダイアログ
                      CPrintDialog dlg(FALSE);
                      //通常使うプリンターのデバイス コンテキストを取得するとき
                      //dlg.GetDefaults();
                      //コモンダイアログを表示するとき

                      if (dlg.DoModal() != IDOK) return nRetCode;
                     
                      CDC prDC;
                      HDC hd = dlg.GetPrinterDC();
                      prDC.Attach(hd);
                     
                      //プリンタデバイスコンテキストの情報が必要な時は GetDeviceCaps で取得
                      //int iPixelx = prDC.GetDeviceCaps(LOGPIXELSX); //水平方向のピクセル数
                      //int iPixely = prDC.GetDeviceCaps(LOGPIXELSY); //垂直方向のピクセル数
                      //印刷用の論理フォント(フォント種類やサイズ情報を含む)
                      LOGFONT logfont;
                      //10ポイント「MS 明朝」フォント
                      SetLogFont(&prDC, logfont, _T("MS 明朝"), 10);
                      pFont10 = new CFont;
                      pFont10->CreateFontIndirect(&logfont);
                      //20ポイント「HG丸ゴシックM-PRO」フォント
                      SetLogFont(&prDC, logfont, _T("HG丸ゴシックM-PRO"), 20);
                      pFont20 = new CFont;
                      pFont20->CreateFontIndirect(&logfont);
                      //サンプル帳票の印刷処理開始
                      SamplePrintOut(&prDC);
                      //後処理
                      prDC.Detach();
                      DeleteDC(hd);
                      //フォントオブジェクトの破棄
                      DeleteFont();
                  }
              }
              else
              {
                  // TODO: 必要に応じてエラー コードを変更してください。
                  wprintf(L"致命的なエラー: GetModuleHandle が失敗しました¥n");
                  nRetCode = 1;
              }
              return nRetCode;
          }

          /*************************************************
          関数名 SamplePrintOut
          機能   サンプル帳票を生成
          *************************************************/

          void SamplePrintOut(CDC *pDC)
          {
              CFont *pOld;
              //印刷領域を取得
              CRect rect;
              pDC->GetClipBox(&rect);
              //印刷ドキュメント(入出力ファイル情報)の設定
              DOCINFO dinfo;
              memset((char *)&dinfo, 0x00, sizeof(DOCINFO));
              //DOCINFO構造体のサイズ
              dinfo.cbSize = sizeof(DOCINFO);
              //ドキュメント名
              dinfo.lpszDocName = _T("やさしいプログラミング備忘録 VC++サンプル");
              //ドキュメント開始
              pDC->StartDoc(&dinfo);
              //ページ開始
              pDC->StartPage();
              //大きいフォントを指定
              pOld = pDC->SelectObject(pFont20);
              //文字を出力
              pDC->TextOut(700, 900, _T("領 収 書"));
              pDC->TextOut(1700, 1400, _T("株式会社 ○○○○商事 様"));
              pDC->TextOut(1100, 2000, _T("¥   59,800(消費税込み)"));
              //小さいフォントを指定
              pDC->SelectObject(pFont10);
              pDC->TextOut(3000, 950, _T("No.○○-1234567890"));
              pDC->TextOut(3000, 1100, _T("2017年10月10日"));
              pDC->TextOut(1600, 2500, _T("但し パンフレットデザイン費、及び印刷代金として"));
              pDC->TextOut(1600, 2700, _T("上記正に領収いたしました。"));
              pDC->TextOut(2200, 3500, _T("神奈川県横浜市○○区○○○1−2−3 ××ビル2階"));
              pDC->TextOut(2700, 3650, _T("やさしいプログラミング備忘録 株式会社"));
              //線を引く
              LineOut(pDC, 3000, 1050, 4300, 1050);
              LineOut(pDC, 1050, 2200, 4000, 2200);
              //ページ終了
              pDC->EndPage();
              //ドキュメント終了
              pDC->EndDoc();
          }

          /*************************************************
          関数名 SetLogFont
          機能   フォントに種別、サイズを設定する
          *************************************************/

          void SetLogFont(CDC *pDC, LOGFONT& logfont, CString csFontName, int iSize)
          {
              memset(&logfont, 0x00, sizeof(logfont));
              lstrcpy(logfont.lfFaceName, csFontName);
              //LOGFONT構造体についてはDeveloperNetwork参照
              //出力精度を指定
              logfont.lfOutPrecision = OUT_TT_PRECIS;
              //クリッピング領域を外れた時の精度
              logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
              //出力品質を指定
              logfont.lfQuality = PROOF_QUALITY;
              //ピッチとファミリを指定
              logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
              //文字セットを指定
              logfont.lfCharSet = SHIFTJIS_CHARSET;
              //文字または文字の論理単位で、高さを指定(デバイス論理インチのピクセル数)
              //MicrosoftSupport参考
              logfont.lfHeight = -MulDiv(iSize, pDC->GetDeviceCaps(LOGPIXELSY), 72);
          }

          /*************************************************
          関数名 SetLogFont
          機能   フォントに種別、サイズを設定する
          *************************************************/

          void DeleteFont()
          {
              if (pFont10) {
                  pFont10->DeleteObject();
                  delete pFont10;
              }
              if (pFont20) {
                  pFont20->DeleteObject();
                  delete pFont20;
              }
          }

          /*************************************************
          関数名 LineOut
          機能   線を引く
          *************************************************/

          void LineOut(CDC *pDC, int stx, int sty, int edx, int edy)
          {
              CPen newPen;
              CPen *pOld = NULL;
              newPen.CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
              pOld = pDC->SelectObject(&newPen);
              pDC->MoveTo(stx, sty);
              pDC->LineTo(edx, edy);
              pDC->SelectObject(pOld);
          }
           

          よろしければポチッと押してください

          プログラマー ブログランキングへ

           


          【VC++】簡単なマルチスレッド その2

          0

            <機能>

            (1)AfxBeginThreadを使用したマルチスレッドサンプルです

            (2)セマフォ(CSemaphoreクラス)を使って排他制御します

            (3)public変数 count を5スレッドからカウントアップします

             ※1スレッドあたり100カウントアップするためcount=500となります

             (排他制御(CSingleLock::Lock/Unlock)がないとcount<500)

             

            <イメージ>

            排他制御実装前の結果は、100カウントアップするスレッドを5つ起動してcount=500になりません

            CSemaphoreを使用しない結果

            セマフォを使ってcountをいずれか1スレッドからしか使えないように排他制御(CSingleLock::Lock/Unlock)するとcount=500となりました

            CSemaphoreを使用した結果

             

            <動作検証&開発環境>
            Visual Studio Community 2017

            <使い方>
            1.ダイアログベースでThreadSample2プロジェクトを作成
            2.エディットボックスとボタンを配置

             

            ダイアログにGUI配置
            IDC_EDIT1/IDC_EDIT2:ReadOnly=TRUE
            3.コントロール変数を追加
            エディットボックスにコントロース変数設定
            IDC_EDIT1 : m_EdtCount(種類EDIT/カテゴリControl)
            IDC_EDIT2 : m_EdtThread(種類EDIT/カテゴリControl)
            4.ソース追加

            ThreadSample2Dlg.h
            class CThreadSample2Dlg : public CDialogEx
            {
                //~~省略~~
            public:
                afx_msg void OnBnClickedButton1();
                int count;
                int threadno;
                CWinThread *mythread;
                CEdit m_EdtCount;
                CEdit m_EdtThread;
                //セマフォオブジェクト(スレッド間のロックに使用)
                CSemaphore m_cSmp;
            };
            ThreadSample2Dlg.cpp
            //プロトタイプ宣言
            UINT __cdecl CountUpThread(LPVOID p);
            BOOL CThreadSample2Dlg::OnInitDialog()
            {
                CDialogEx::OnInitDialog();
                // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、
                //  Framework は、この設定を自動的に行います。
                SetIcon(m_hIcon, TRUE);            // 大きいアイコンの設定
                SetIcon(m_hIcon, FALSE);        // 小さいアイコンの設定
                //エディットボックスの初期表示
                m_EdtCount.SetWindowTextW(L"0");
                m_EdtThread.SetWindowTextW(L"0");
                return TRUE;
            }
            /*************************************************
            関数名 OnBnClickedButton1
            機能   セマフォで同期 ボタン押下イベント
            *************************************************/

            void CThreadSample2Dlg::OnBnClickedButton1()
            {
                MSG msg;
                count = 0;
                threadno = 0;
                //複数スレッド(5スレッド)起動
                for (int i = 0; i < 5; i++) {
                    //スレッド番号(IDC_EDIT2に表示する)
                    threadno = (i+1);
                    TRACE(L"スレッド %d 起動¥n",threadno);
                    AfxBeginThread(CountUpThread, this, 0, 0, NULL);
                    while (PeekMessage(&msg, this->GetSafeHwnd(), 0, 0, PM_REMOVE)) {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                    }
                    Sleep(300);
                }
            }
            /*************************************************
            関数名 CountUpThread
            機能   ダイアログの変数をカウントアップして表示
            *************************************************/

            UINT __cdecl CountUpThread(LPVOID p) {
               
                CThreadSample2Dlg* pDlg = (CThreadSample2Dlg*)p;
                CString cs;
                MSG msg;
                CSingleLock singlelock(&(pDlg->m_cSmp));
                //スレッド番号を更新
                cs.Format(L"%d", pDlg->threadno);
                pDlg->m_EdtThread.SetWindowTextW(cs);
                //1スレッドで100カウントアップする
                for(int i=0;i<100;i++){
                   
                    //複数スレッドからcountにアクセスする際に、いずれか1スレッドからしか
                    //使用できないように排他制御する
                    //CSingleLockについてはDeveloperNetWork参照

                    singlelock.Lock();
                    pDlg->count++;
                    singlelock.Unlock();
                    //ダイアログのエディットボックスに表示
                    cs.Format(L"%d", pDlg->count);
                    pDlg->m_EdtCount.SetWindowTextW(cs);
                    while (PeekMessage(&msg, pDlg->GetSafeHwnd(), 0, 0, PM_REMOVE)) {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                    }
                    TRACE(L"count = " + cs + L"¥n");
                    Sleep(100);
                }
                return 0;
            }
             

            よろしければポチッと押してください

            プログラマー ブログランキングへ

             



            << | 2/6PAGES | >>

            calendar

            S M T W T F S
                  1
            2345678
            9101112131415
            16171819202122
            23242526272829
            30      
            << September 2018 >>

            profile

            others

            mobile

            qrcode         スマホ表示に戻す