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

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

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

       


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

      0

        <機能>

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

        (2)マルチスレッドでカウントアップ処理を行います

        (3)バックグラウンドプログラムの中断、再開ができます

         中断:ResumeThread

         再開:SuspendThread

        (4)バックグラウンド処理が終了を通知します

        (5)ダイアログは終了通知を受け取り終了処理をします

         

        <イメージ>

        スレッド開始 ボタン押下によりカウントアップを開始

        スレッド開始イメージ,AfxBeginThread

        中断 ボタン押下により中断します(中断→再開に変更)

        中断ボタンを再開ボタンに変更,AfxBeginThread

        処理が終了したらユーザ定義メッセージで通知します

        終了メッセージ,AfxBeginThread

         

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

         

        <使い方>

        1.ダイアログベースでThreadSampleプロジェクトを作成

        2.エディットボックスとボタンを配置

        IDC_EDIT : ReadOnly=TRUE

        3.コントロール変数を追加

        IDC_EDIT : m_EdtCount(種類EDIT/カテゴリControl)

        IDC_BTNST : m_BtnStart(種類BUTTON)

        IDC_BTNSTOP : m_BtnStop(種類BUTTON)

        IDOK : m_BtnOk(種類BUTTON)

        4.終了通知イベントハンドラ追加

        カスタムWindowsメッセージ : WM_MYMSG

        メッセージハンドラ名 : OnMyMsg

        5.ソースを追加

         

        ThreadSampleDlg.h

         

        class CThreadSampleDlg : public CDialogEx
        {

          //〜〜省略〜〜

        public:
            afx_msg void OnBnClickedOk();
            int count;
            CButton m_BtnStart;
            CButton m_BtnStop;
            CButton m_BtnOk;
            afx_msg void OnBnClickedBtnst();
            afx_msg void OnBnClickedBtnstop();
            CEdit m_EdtCount;
            CWinThread* mythread;
        protected:
            afx_msg LRESULT OnMyMsg(WPARAM wParam, LPARAM lParam);
        };

         

        ThreadSampleDlg.cpp

        //プロトタイプ宣言
        UINT __cdecl CountUpThread(LPVOID p);
        //ユーザ定義メッセージ
        #define WM_MYMSG (WM_USER + 100)
        CThreadSampleDlg::CThreadSampleDlg(CWnd* pParent /*=NULL*/)
            : CDialogEx(IDD_THREADSAMPLE_DIALOG, pParent)
        {
            m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
        }
        void CThreadSampleDlg::DoDataExchange(CDataExchange* pDX)
        {
            CDialogEx::DoDataExchange(pDX);
            DDX_Control(pDX, IDC_BTNST, m_BtnStart);
            DDX_Control(pDX, IDC_BTNSTOP, m_BtnStop);
            DDX_Control(pDX, IDOK, m_BtnOk);
            DDX_Control(pDX, IDC_EDIT, m_EdtCount);
        }
        BEGIN_MESSAGE_MAP(CThreadSampleDlg, CDialogEx)
            ON_WM_SYSCOMMAND()
            ON_WM_PAINT()
            ON_WM_QUERYDRAGICON()
            ON_BN_CLICKED(IDOK, &CThreadSampleDlg::OnBnClickedOk)
            ON_BN_CLICKED(IDC_BTNST, &CThreadSampleDlg::OnBnClickedBtnst)
            ON_BN_CLICKED(IDC_BTNSTOP, &CThreadSampleDlg::OnBnClickedBtnstop)
            ON_MESSAGE(WM_MYMSG, &CThreadSampleDlg::OnMyMsg)
        END_MESSAGE_MAP()

        // CThreadSampleDlg メッセージ ハンドラー
        BOOL CThreadSampleDlg::OnInitDialog()
        {
            CDialogEx::OnInitDialog();
            // "バージョン情報..." メニューをシステム メニューに追加します。
            // IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。
            ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
            ASSERT(IDM_ABOUTBOX < 0xF000);
            CMenu* pSysMenu = GetSystemMenu(FALSE);
            if (pSysMenu != NULL)
            {
                BOOL bNameValid;
                CString strAboutMenu;
                bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
                ASSERT(bNameValid);
                if (!strAboutMenu.IsEmpty())
                {
                    pSysMenu->AppendMenu(MF_SEPARATOR);
                    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
                }
                //バツボタン(「×」ボタン)を無効にする
                pSysMenu->EnableMenuItem(SC_CLOSE, MF_GRAYED);
            }
            // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、
            //  Framework は、この設定を自動的に行います。
            SetIcon(m_hIcon, TRUE);            // 大きいアイコンの設定
            SetIcon(m_hIcon, FALSE);        // 小さいアイコンの設定
            //ボタンの初期状態
            m_BtnStart.EnableWindow(TRUE);
            m_BtnStop.EnableWindow(FALSE);
            m_BtnOk.EnableWindow(TRUE);
            m_BtnStop.SetWindowTextW(L"中 断");
            m_EdtCount.SetWindowTextW(L"0");
            return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
        }
        /*************************************************
        関数名 OnBnClickedOk
        機能   閉じる ボタン押下イベント
        *************************************************/

        void CThreadSampleDlg::OnBnClickedOk()
        {
            CDialogEx::OnOK();
        }
        /*************************************************
        関数名 OnBnClickedBtnst
        機能   スレッド開始 ボタン押下イベント
        *************************************************/

        void CThreadSampleDlg::OnBnClickedBtnst()
        {
            DWORD dwExitCode;
            MSG msg;
            //ボタンの状態をセット(中断のみ活性化)
            m_BtnStart.EnableWindow(FALSE);
            m_BtnStop.EnableWindow(TRUE);
            m_BtnOk.EnableWindow(FALSE);
            //カウントを初期化
            count = 0;
            //新しいスレッドを作成する
            //AfxBeginThreadについてはDeveloper Network参照
            mythread = AfxBeginThread(CountUpThread, this,0,0,NULL);
          
        }
        /*************************************************
        関数名 OnBnClickedBtnstop
        機能   中断 ボタン押下イベント
        *************************************************/

        void CThreadSampleDlg::OnBnClickedBtnstop()
        {
            CString cs;
            DWORD dwExitCode;
            //ボタンの状態をセット(中断のみ活性化)
            m_BtnStart.EnableWindow(FALSE);
            m_BtnStop.EnableWindow(TRUE);
            m_BtnOk.EnableWindow(FALSE);
            //ボタンのキャプションを取得
            m_BtnStop.GetWindowTextW(cs);
            if (cs == L"中 断") {
                m_BtnStop.SetWindowTextW(L"再 開");
                //スレッドを再開
                if (GetExitCodeThread(mythread->m_hThread, &dwExitCode)) {
                    if (dwExitCode == STILL_ACTIVE) {
                        mythread->SuspendThread();
                    }
                }
            }
            else {
                m_BtnStop.SetWindowTextW(L"中 断");
                //スレッドを中断
                if (GetExitCodeThread(mythread->m_hThread, &dwExitCode)) {
                    if (dwExitCode == STILL_ACTIVE) {
                        mythread->ResumeThread();
                    }
                }
            }
        }
        /*************************************************
        関数名 CountUpThread
        機能   ダイアログの変数をカウントアップして表示
        *************************************************/

        UINT __cdecl CountUpThread(LPVOID p) {
            CThreadSampleDlg* pDlg = (CThreadSampleDlg*)p;
            CString cs;
            while(1){
                //100までカウントアップ
                pDlg->count++;
                if (pDlg->count > 100) break;
                //ダイアログのエディットボックスに表示
                cs.Format(L"%d",pDlg->count);
                pDlg->m_EdtCount.SetWindowTextW(cs);
                Sleep(100);
            }
           
            ::SendMessage(pDlg->m_hWnd, WM_MYMSG, 0, 0);
            return 0;
        }
        /*************************************************
        関数名 OnMyMsg
        機能   ユーザ定義メッセージのイベントハンドラ
        *************************************************/

        afx_msg LRESULT CThreadSampleDlg::OnMyMsg(WPARAM wParam, LPARAM lParam)
        {
            AfxMessageBox(L"スレッドが終了しました", MB_ICONINFORMATION);
            //処理終了
            m_BtnStart.EnableWindow(TRUE);
            m_BtnStop.EnableWindow(FALSE);
            m_BtnOk.EnableWindow(TRUE);
           
            return 0;
        }

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

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

         


        【VC++】モードレスダイアログをDLLで実装して呼び出す

        0

          <機能>

          ・プログレスバーをDLL(共通部品)として実装します

          (モードレスダイアログとして実装します)

          ・呼び出し側(親ダイアログ)のボタン押下によりDLL(子ダイアログ)を表示します

          ・[中断]ボタン押下によりプログレスバーを中止できます

          (親ダイアログにユーザ定義メッセージをSendMessageします)

           

          <イメージ>

          親ダイアログ(ProgressCall.exe)

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,

          ボタン押下によりプログレスバーを表示します

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,

          [中断]ボタン押下により中断確認メッセージを表示します

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,

           

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

           

          <使い方>

           

          1.DLLの作成

          (1)ProgressSampleプロジェクトを作成します

           MFC DLLを選択してください

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,エクスポート,

          (2)ProgressSampleプロジェクトのプリプロセッサを定義

           C/C++ → プリプロセッサ → プリプロセッサの定義 に

           PROGRESSSAMPLE_EXPORTSを定義してください。 

           (Debug構成/Release構成とも)

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,エクスポート,

          (3)ダイアログをプロジェクトに追加

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,エクスポート,

          (4)プログレスコントロールとボタンを配置

          子ダイアログ(DLL)のリソースID

           ダイアログ:IDD_DIALOG1

           プログレスコントロール:IDC_PROGRESS1

           中断ボタン:IDC_BUTTON1

           

          (5)CDialogを基底クラスとしてクラスを追加

           クラス名をCProgressSampleDlgとしてください。

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,エクスポート,

          (6)メンバ変数を追加

           プログレスコントロールのメンバ変数

           名前:m_Prog

           種類:CProgressCtrl

           カテゴリ:Control(コントロール変数にチェック)

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,エクスポート,

           中断ボタンのメンバ変数

           名前:m_Btn

           種類:CButton

           カテゴリ:Control(コントロール変数にチェック)

           

          (7)CProgressSampleDlgクラスに仮想関数をオーバーライド

           PostNcDestroy

           OnInitDialog

           ※中断ボタン押下イベントハンドラはソースを参照してください

          VC++,MFC,DLL,モードレスダイアログ,プログレスバー,エクスポート,

           

          (8)ProgressSampleAPI.h を追加

          (9)下記を参考にソースを実装

           

          //////ProgressSampleAPI.h

          #pragma once

          #ifdef PROGRESSSAMPLE_EXPORTS
          #define DLL_API __declspec( dllexport )
          #else
          #define DLL_API __declspec( dllimport )
          #endif

           

          //[中断]ボタン押下メッセージ
          #define UM_PROGRESS WM_USER + 100

           

          #ifdef __cplusplus
          extern "C" {
          #endif  /* __cplusplus */

              //エクスポート
              //プログレスバーを初期化

              DLL_API HWND InitProgressBar(HWND myWnd,int iMin, int iMax, wchar_t* cTitle);

              //プログレスバーダイアログを破棄

              DLL_API void CloseProgressBar(HWND childWnd);

              //プログレスバーを進める

              DLL_API void MoveProgressBar(HWND childWnd, int iVal);

          #ifdef __cplusplus
          }
          #endif

           

          //////ProgressSample.h

          // ProgressSample.h : ProgressSample.DLL のメイン ヘッダー ファイル
          //

          #pragma once

          #ifndef __AFXWIN_H__
              #error "PCH に対してこのファイルをインクルードする前に 'stdafx.h' をインクルードしてください"
          #endif

          #include "resource.h"        // メイン シンボル


          // CProgressSampleApp
          // このクラスの実装に関しては ProgressSample.cpp を参照してください。
          //

          class CProgressSampleApp : public CWinApp
          {
          public:
              CProgressSampleApp();


          // オーバーライド
          public:
              virtual BOOL InitInstance();

              DECLARE_MESSAGE_MAP()
          };

           

          //////ProgressSample.cpp

          // ProgressSample.cpp : DLL の初期化ルーチンです。
          //

          #include "stdafx.h"
          #include "ProgressSample.h"
          #include "ProgressSampleAPI.h"
          #include "ProgressSampleDlg.h"

          #ifdef _DEBUG
          #define new DEBUG_NEW
          #endif

          //
          //TODO: この DLL が MFC DLL に対して動的にリンクされる場合、
          //        MFC 内で呼び出されるこの DLL からエクスポートされたどの関数も
          //        関数の最初に追加される AFX_MANAGE_STATE マクロを
          //        持たなければなりません。
          //
          //        例:
          //
          //        extern "C" BOOL PASCAL EXPORT ExportedFunction()
          //        {
          //            AFX_MANAGE_STATE(AfxGetStaticModuleState());
          //            // 通常関数の本体はこの位置にあります
          //        }
          //
          //        このマクロが各関数に含まれていること、MFC 内の
          //        どの呼び出しより優先することは非常に重要です。
          //        これは関数内の最初のステートメントでなければな 
          //        らないことを意味します、コンストラクターが MFC
          //        DLL 内への呼び出しを行う可能性があるので、オブ
          //        ジェクト変数の宣言よりも前でなければなりません。
          //
          //        詳細については MFC テクニカル ノート 33 および
          //        58 を参照してください。
          //

          // CProgressSampleApp

          BEGIN_MESSAGE_MAP(CProgressSampleApp, CWinApp)
          END_MESSAGE_MAP()


          // CProgressSampleApp コンストラクション

          CProgressSampleApp::CProgressSampleApp()
          {

              // TODO: この位置に構築用コードを追加してください。
              // ここに InitInstance 中の重要な初期化処理をすべて記述してください。

          }


          // 唯一の CProgressSampleApp オブジェクトです。

          CProgressSampleApp theApp;


          // CProgressSampleApp 初期化

          BOOL CProgressSampleApp::InitInstance()
          {
              CWinApp::InitInstance();

              return TRUE;
          }


          /*************************************************
          関数名 InitProgressBar
          機能   プログレスバーを初期化
          *************************************************/

          DLL_API HWND InitProgressBar(HWND myWnd,int iMin, int iMax, wchar_t* cTitle)
          {
              AFX_MANAGE_STATE(AfxGetStaticModuleState());
              
              CProgressSampleDlg *mydlg = new CProgressSampleDlg();
              mydlg->m_iMin = iMin;
              mydlg->m_iMax = iMax;
              mydlg->m_csCap = cTitle;
              mydlg->m_oyaHwnd = myWnd;

              //モードレスダイアログを作成
              mydlg->Create(IDD_DIALOG1);
              mydlg->ShowWindow(SW_SHOW);

              return mydlg->m_hWnd;
          }

          /*************************************************
          関数名 CloseProgressBar
          機能   プログレスバーダイアログを破棄
          *************************************************/

          DLL_API void CloseProgressBar(HWND childWnd)
          {
              AFX_MANAGE_STATE(AfxGetStaticModuleState());

              CWnd* wkdlg = CWnd::FromHandle(childWnd);
              ((CProgressSampleDlg*)wkdlg)->DestroyWindow();
          }

          /*************************************************
          関数名 MoveProgressBar
          機能   プログレスバーを進める
          *************************************************/

          DLL_API void MoveProgressBar(HWND childWnd,int iVal)
          {
              AFX_MANAGE_STATE(AfxGetStaticModuleState());
              int iMin, iMax;

              CWnd* wkdlg = CWnd::FromHandle(childWnd);
              ((CProgressSampleDlg*)wkdlg)->m_Prog.SetPos(iVal);

              //プログレスバーが最後まで進んでいたらボタンキャプション変更
              ((CProgressSampleDlg*)wkdlg)->m_Prog.GetRange(iMin, iMax);
              if (iVal == iMax) {
                  ((CProgressSampleDlg*)wkdlg)->m_Btn.SetWindowText(_T("閉じる"));
              }
          }
           

          //////ProgressSampleDlg.h

          #pragma once
          #include "afxcmn.h"
          #include "afxwin.h"

          // CProgressSampleDlg ダイアログ

          class CProgressSampleDlg : public CDialog
          {
              DECLARE_DYNAMIC(CProgressSampleDlg)

          public:
              CProgressSampleDlg(CWnd* pParent = NULL);
            // 標準コンストラクター
              virtual ~CProgressSampleDlg();

              int m_iMin;
              int m_iMax;
              CString m_csCap;
              //[中断]ボタン押下時にSeneMessageする
              HWND m_oyaHwnd;

          // ダイアログ データ
          #ifdef AFX_DESIGN_TIME
              enum { IDD = IDD_DIALOG1 };
          #endif

          protected:
              virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV サポート

              DECLARE_MESSAGE_MAP()
          public:
              CProgressCtrl m_Prog;
              CButton m_Btn;
              virtual BOOL OnInitDialog();
              virtual void PostNcDestroy();
              afx_msg void OnBnClickedButton1();
          };
           

          //////ProgressSampleDlg.cpp

          // ProgressSampleDlg.cpp : 実装ファイル
          //

          #include "stdafx.h"
          #include "ProgressSample.h"
          #include "ProgressSampleDlg.h"
          #include "ProgressSampleAPI.h"
          #include "afxdialogex.h"
          #include <Windows.h>

          // CProgressSampleDlg ダイアログ

          IMPLEMENT_DYNAMIC(CProgressSampleDlg, CDialog)

          CProgressSampleDlg::CProgressSampleDlg(CWnd* pParent /*=NULL*/)
              : CDialog(IDD_DIALOG1, pParent)
          {

          }

          CProgressSampleDlg::~CProgressSampleDlg()
          {
          }

          void CProgressSampleDlg::DoDataExchange(CDataExchange* pDX)
          {
              CDialog::DoDataExchange(pDX);
              DDX_Control(pDX, IDC_PROGRESS1, m_Prog);
              DDX_Control(pDX, IDC_BUTTON1, m_Btn);
          }


          BEGIN_MESSAGE_MAP(CProgressSampleDlg, CDialog)
              ON_BN_CLICKED(IDC_BUTTON1, &CProgressSampleDlg::OnBnClickedButton1)
          END_MESSAGE_MAP()


          // CProgressSampleDlg メッセージ ハンドラー

          /*************************************************
          関数名 OnInitDialog
          機能   ダイアログの初期化
          *************************************************/

          BOOL CProgressSampleDlg::OnInitDialog()
          {
              CDialog::OnInitDialog();

              m_Prog.SetRange(m_iMin, m_iMax);
              SetWindowText(m_csCap);

              //閉じる[X]ボタンを無効(グレーアウト)
              CMenu* pSysMenu = GetSystemMenu(FALSE);
              pSysMenu->EnableMenuItem(SC_CLOSE, MF_GRAYED);

              return TRUE;
          }

          /*************************************************
          関数名 PostNcDestroy
          機能   ダイアログの破棄
          *************************************************/

          void CProgressSampleDlg::PostNcDestroy()
          {
              delete this;

              CDialog::PostNcDestroy();
          }

          /*************************************************
          関数名 OnBnClickedButton1
          機能   [中 断]ボタン押下イベントハンドラ
          *************************************************/

          void CProgressSampleDlg::OnBnClickedButton1()
          {
              //ユーザー定義メッセージを送信
              CWnd::FromHandle(m_oyaHwnd)->SendMessage(UM_PROGRESS, (WPARAM)NULL, (LPARAM)NULL);
          }
           

          2.呼び出し側(親ダイアログ)の作成

          (1)同一ソリューション内にProgressCallプロジェクトを作成します

           ダイアログベースで作成してください。

          (2)プロジェクトの依存関係を設定(ビルド順も同時設定できます)

           ProgressCallプロジェクトの依存先であるProgressSampleプロジェクトにチェックON

          プロジェクトの依存関係設定,プロジェクトのプロパティ,

           

          プロジェクトのビルド順序設定,プロジェクトのプロパティ,

          (3)IDOKボタン、IDCANCELボタンをそのまま使います

          親ダイアログのリソースID

           ダイアログ:IDD_PROGRESSCALL_DIALOG

           呼び出しボタン:IDOK

           終了ボタン:IDCANCEL

           

          (4)リンカー設定

           ProgressCallプロパティページにて下記を設定

           リンカー → 全般 → 追加のライブラリディレクトリ に

           Debug構成: ..¥Debug

           Release構成: ..¥Release

           

           リンカー → 全般 → 入力 に

           Debug構成/Release構成とも: ProgressSample.lib

           

          (5)下記を参考にソースを実装

           

          //////ProgressCallDlg.h

          // ProgressCallDlg.h : ヘッダー ファイル
          //

          #pragma once


          // CProgressCallDlg ダイアログ
          class CProgressCallDlg : public CDialogEx
          {

          // コンストラクション
          public:
              CProgressCallDlg(CWnd* pParent = NULL); 
             // 標準コンストラクター

          // ダイアログ データ
          #ifdef AFX_DESIGN_TIME
              enum { IDD = IDD_PROGRESSCALL_DIALOG };
          #endif

              protected:
              virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV サポート


          // 実装
          protected:
              HICON m_hIcon;

              // 生成された、メッセージ割り当て関数
              virtual BOOL OnInitDialog();
              afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
              afx_msg void OnPaint();
              afx_msg HCURSOR OnQueryDragIcon();
              afx_msg LRESULT OnButtonClose(WPARAM wParam, LPARAM lParam);
              DECLARE_MESSAGE_MAP()

          private:
              //プログレスバーダイアログのハンドル
              HWND childHWND;
              BOOL m_bProgress;
              HWND ShowProgress();

          public:
              afx_msg void OnBnClickedOk();
          };

           

          //////ProgressCallDlg.cpp

          // ProgressSampleDlg.cpp : 実装ファイル
          //

          #include "stdafx.h"
          #include "ProgressSample.h"
          #include "ProgressSampleDlg.h"
          #include "ProgressSampleAPI.h"
          #include "afxdialogex.h"
          #include <Windows.h>

          // CProgressSampleDlg ダイアログ

          IMPLEMENT_DYNAMIC(CProgressSampleDlg, CDialog)

          CProgressSampleDlg::CProgressSampleDlg(CWnd* pParent /*=NULL*/)
              : CDialog(IDD_DIALOG1, pParent)
          {

          }

          CProgressSampleDlg::~CProgressSampleDlg()
          {
          }

          void CProgressSampleDlg::DoDataExchange(CDataExchange* pDX)
          {
              CDialog::DoDataExchange(pDX);
              DDX_Control(pDX, IDC_PROGRESS1, m_Prog);
              DDX_Control(pDX, IDC_BUTTON1, m_Btn);
          }


          BEGIN_MESSAGE_MAP(CProgressSampleDlg, CDialog)
              ON_BN_CLICKED(IDC_BUTTON1, &CProgressSampleDlg::OnBnClickedButton1)
          END_MESSAGE_MAP()


          // CProgressSampleDlg メッセージ ハンドラー

          /*************************************************
          関数名 OnInitDialog
          機能   ダイアログの初期化
          *************************************************/

          BOOL CProgressSampleDlg::OnInitDialog()
          {
              CDialog::OnInitDialog();

              m_Prog.SetRange(m_iMin, m_iMax);
              SetWindowText(m_csCap);

              //閉じる[X]ボタンを無効(グレーアウト)
              CMenu* pSysMenu = GetSystemMenu(FALSE);
              pSysMenu->EnableMenuItem(SC_CLOSE, MF_GRAYED);

              return TRUE;
          }

          /*************************************************
          関数名 PostNcDestroy
          機能   ダイアログの破棄
          *************************************************/

          void CProgressSampleDlg::PostNcDestroy()
          {
              delete this;

              CDialog::PostNcDestroy();
          }


          /*************************************************
          関数名 OnBnClickedButton1
          機能   [中 断]ボタン押下イベントハンドラ
          *************************************************/

          void CProgressSampleDlg::OnBnClickedButton1()
          {
              //ユーザー定義メッセージを送信
              CWnd::FromHandle(m_oyaHwnd)->SendMessage(UM_PROGRESS, (WPARAM)NULL, (LPARAM)NULL);
          }
           

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

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

           


          【VC++】SetROP2を使用して十字線カーソルを実装する

          0

            <機能>

            (1)画面上に長い十字線カーソルを表示します

            (2)画面上をダブルクリックするとポイント座標を表示します

             ※サンプルのためOnLButtonDblClkで表示しています

             ※再描画するためにはWM_PAINTで描画する必要があります

             

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

             

            <イメージ>

            画面上に十字線カーソルが表示されます

            VC++,MFC,十字,カーソル,十字線,オリジナル,SetROP2,

            ダブルクリックするとポイント座標を表示します

            VC++,MFC,十字,カーソル,十字線,オリジナル,SetROP2,

             

            <使い方>

            (1)CrossCursorプロジェクトを作成

            VisualStudio,プロジェクト,2015,

            (2)シングルドキュメント(SDK)、MFC標準を選択

            VisualStudio,プロジェクト,2015,

            (3)システムメニュー以外のチェックを外す

             (閉じるボタン「X」のみ表示する)

            VisualStudio,プロジェクト,2015,

            (4)本サンプルでは使用しない機能を外す

            VisualStudio,プロジェクト,2015,

            (5)クラスウィザードにてDrawCrossLineメンバ関数を追加

             名前:DrawCrossLine

             戻り値:void

             パラメータ:CPoint cp

            VisualStudio,プロジェクト,2015,メンバ関数,メソッド,

            (6)メッセージハンドラを追加

             ・WM_LBUTTONDBLCLK(ダブルクリックイベント)

             ・WM_MOUSEMOVE(マウス移動イベント)

             ・WM_SETCURSOR(カーソルセット)

            VisualStudio,プロジェクト,2015,メッセージハンドラ,

            (7)ソースの追加

             

            /* CrossCursorView.h */

             

            private:
                CPoint oldpo; //十字線の古いポイント位置を保持するための変数
             

            /* CrossCursorView.cpp */

             

            /*************************************************
            関数名 DrawCrossLine
            機能   カーソルのポイント位置より十字線(縦線+横線)を表示します
            *************************************************/

            void CCrossCursorView::DrawCrossLine(CPoint po)
            {
                RECT rect;
                HWND hWnd = (HWND)this->GetSafeHwnd();
                HDC hdc = ::GetDC(hWnd);

                //描画できるクライアント領域を取得
                ::GetClientRect(hWnd, &rect);
                //前景の描画モードを設定(色を反転させる)
                //SetROP2については
            MSDNを参照してください
                SetROP2(hdc, R2_NOT);

                //縦線を描画
                MoveToEx(hdc, po.x, 0, NULL);
                LineTo(hdc, po.x, rect.bottom);
                //横線を描画
                MoveToEx(hdc, 0, po.y, NULL);
                LineTo(hdc, rect.right, po.y);

                //デバイスコンテキストを開放
                ::ReleaseDC(hWnd, hdc);
            }

             

            /*************************************************
            関数名 OnLButtonDblClk
            機能   ダブルクリックによりポイント座標を表示します
            ※実際の描画はWM_PAINTで行う必要があります(再描画されないため)
            *************************************************/

            void CCrossCursorView::OnLButtonDblClk(UINT nFlags, CPoint point)
            {
                HWND hWnd = (HWND)this->GetSafeHwnd();
                HDC hdc = ::GetDC(hWnd);
                HPEN pen, oldpen;

                //表示する文字列を生成
                TCHAR tcstr[255];
                ZeroMemory(&tcstr, sizeof(tcstr));
                wsprintf(tcstr, L"(%d,%d)", point.x, point.y);

                //緑のペン
                pen = CreatePen(PS_SOLID, 5, RGB(0, 255, 0));
                oldpen = (HPEN)SelectObject(hdc, pen);

                //十字線を消去
                DrawCrossLine(point);

                //ポイント位置を中心に円を描画
                Ellipse(hdc, point.x - 10, point.y - 10, point.x + 10, point.y + 10);
                //ポイント位置を左上座標として文字列を描画
                SetTextColor(hdc, RGB(255, 0, 0));
                TextOut(hdc, point.x, point.y, tcstr, lstrlen(tcstr));
                DrawCrossLine(point);

                //ペンを戻す
                SelectObject(hdc, oldpen);
                //デバイスコンテキストを開放
                ::ReleaseDC(hWnd, hdc);
                //ペンオブジェクトを開放
                DeleteObject(pen);

            }

             

            /*************************************************
            関数名 OnMouseMove
            機能   マウスの動きに合わせて十字線を表示します
            *************************************************/

            void CCrossCursorView::OnMouseMove(UINT nFlags, CPoint point)
            {
                CClientDC dc(this);

                //古い十字線を消去
                DrawCrossLine(oldpo);
                //現在位置の十字線を描画
                DrawCrossLine(point);
                //現在位置を保持
                oldpo = point;
            }

             

            /*************************************************
            関数名 OnSetCursor
            機能   デフォルトのカーソルを4方向矢印(IDC_SIZEALL)に設定します
            *************************************************/

            BOOL CCrossCursorView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
            {
                //カーソルの種類についてはMSDNを参照してください
                
                //ウェイトカーソル
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
                //ウェイトカーソル&矢印
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_APPSTARTING));
                //クロスカーソル
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
                //4方向矢印
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));
                //斜め左下がり矢印
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENESW));
                //斜め右下がり矢印
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE));
                //上下両方向矢印
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
                //左右両方向矢印
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
                //上矢印
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_UPARROW));
                //アイビーム
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_IBEAM));
                //禁止
                //::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO));

             

                //4方向十字カーソルを選択

                ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));
                return TRUE;

             

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

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

             

             

             



            | 1/4PAGES | >>

            calendar

            S M T W T F S
                 12
            3456789
            10111213141516
            17181920212223
            24252627282930
            31      
            << December 2017 >>

            profile

            others

            mobile

            qrcode