상세 컨텐츠

본문 제목

[MFC] MFC에서 UI Thread MFC 스레디 관련, 스레드 중 관련 UI 생성 관련

프로그래밍 관련/MFC

by AlrepondTech 2017. 6. 1. 12:08

본문

반응형

 

=================================

=================================

=================================

 

 

 

출처 :http://blog.naver.com/xtelite/50023358990

 

 

 

MFC에서의 Multithread OS는 구분하지 않지만 MFC는 사용자 편의를 위하여 두 가지 형태로 지원 1.

     

Worker thread2.

     

User Interface thread 

Worker thread

 ::AfxBeginThread() 함수를 이용 

CWinThread* ::AfxBeginThread(

       AFX_THREADPROC pfnThreadProc,

       LPVOID pParam,

       int nPriority = THREAD_PRIORITY_NORMAL, // 기본적으로  Process 동일

       UINT nStackSize = 0,

       DWORD dwCreateFlags = 0,                      // 0 또는 CREATE_SUSPENDED

       LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL

); 우선 Thread를 이용할 함수를 먼저 정의한다 UINT ThreadFunc(LPVOID pParam)

{

       int option = (int)pParam;

       

}

 

만약 인자가 많은 경우에는

 

typedef struct tagPARAMS

{

       ...

} PARAMS;

 와 같이 한 후에 

PARAMS *pParams = new PARAMS;

CWinThread *pThread = ::AfxBeginThread(ThreadFunc, &pParams); 와 같이 하고 

UINT ThreadFunc(LPVOID pParam)

{

       PARAMS *pThreadParams = (PARAMS *)pParam;

       ...

       delete pThreadParams;

 

       return 0;

}

 와 같이 사용하면 된다. Thread를 잠시 중지시키고 싶을 때는 주 Process에서 pThread->SuspendThread(); 다시 돌리고 싶을 때는 주 Process에서 pThread->ResumeThread(); 와 같이 하면 된다.(Thread 자신이 호출할 수는 없다.)또는 경우에 따라서는 Sleep(2000); 과 같이 사용할 수도 있는데 이 경우는 제어권을 다른 Process에 넘겨 주게 된다. Sleep(0); 와 같이 할 경우에는 우선 순위가 높거나 같은 Process에 넘겨 주고 우선 순위가 높거나같은 Process가 없을 경우에는 아무 일도 생기지 않는다. Thread를 종료시키고 싶을 때는 TerminateThread() 함수를 사용하면 되는데 이 경우 Thread 함수가내부 정리를 하지 못할 수가 있기 때문에 다음과 같은 방법이 많이 사용된다. static BOOL bContinue = TRUE;CWinThread *pThread = ::AfxBeginThread(ThreadFunc, &bContinue);

 

UINT ThreadPrintNum(LPVOID pParam)

{

       BOOL *pbContinue = (BOOL *)pParam;

       while ( *pbContinue )

       {

             

       }

       return 0;

} 와 같이 하고 bContinue 값을 FALSE로 하면 Thread 함수가 종료된다. Thread가 완전히 종료된 것을 확신해야 하는 경우에는 if ( ::WaitForSingleObject(pThread->m_hThread, INFINITE) )

{

       // 이곳은쓰레드가확실히종료된상태임} 와 같이 하면 된다. Thread가 죽어 버려서 먹통이 되는 경우까지 대비하려면 

DWORD result;

result = ::WaitForSingleObject(pThread->m_hThread, 1000);   // 1초기다림if ( result == WAIT_OBJECT_0 )

{

       // 이곳은쓰레드가확실히종료된상태임

}

else if ( result == WAIT_TIMEOUT )

{

       // 1초가지나도쓰레드가종료되지않은상태

}

 이 방법을 사용해야 한다어떤 Thread가 현재 실행 중인지 알고 싶을 때는 if ( ::WaitForSingleObject(pThread->m_hThread, 0 ) == WAIT_TIMEOUT )

{

       // pThread 실행중

}

else

{

       // pThread가실행중이아님} 와 같이 하면 된다. 

User Interface Thread

 User interface thread는 그 자체로 윈도우와 메시지 루프를 가지고 있다. class CUIThread : public CWinThread

{

       DECLARE_DYNCREATE(CUIThread)

 

public:

       virtual BOOL InitInstance();

};

 

 User interface thread 독자의 윈도우도 가질  있다일반적으로 전용 Dialog 띄워Thread 처리하는 경우가 많으므로  User Dialog CMyDialog라고 이름 지었다고 가정하면

 

IMPLEMENT_DYNCREATE(CUIThread, CWinThread)

 

BOOL CUIThread::InitInstance()

{

       m_pMainWnd = new CMyDialog;

       m_pMainWnd->ShowWindow(SW_SHOW);

       m_pMainWnd->UpdateWindow();

       return TRUE;

} 와 같이 CMyDialog Thread로 띄울 수 있다그 다음 CWinThread *pThread = ::AfxBeginThread(RUNTIME_CLASS(CUIThread)); 와 같이 하면 MFC가 알아서 CUIThread를 생성해서 그 포인터를 pThread에 넘겨 준다. 아래 예제에는 CMyDialog를 띄우고 주 Process는 사용자의입력을 기다린다. Dialog Design 및 생성은 별도로 이야기하지 않는다아래 예제를 사용하기 위해서는CMyDialog를 만들고 ID IDD_MYDIALOG라고 가정하면 CMyDialog의 생성자에 다음과 같이 추가해야 제대로 동작한다. 

CMyDialog::CMyDialog(CWnd* pParent /*=NULL*/)

       : CDialog(CMyDialog::IDD, pParent)

{

       Create(IDD_MYDIALOG, NULL);

}

 

이제 완전히 별도로 동작하는(Thread로 동작하는윈도우를 하나 가지는 것이다만약 이것을 Dialog가 아닌FrameWnd라고 해도 거의 똑같다다만 위에서도 언급했듯이 Thread를 이용할 때는 Dialog가 더 일반적일 것이다.Worker thread에 비해 훨씬 더 많은 기능을 하는 것을 알게 되었을 것이다. 나머지 것들은 위의 Worker Thread에 있는 내용과 동일하다. 만약 여러 개의 CUIThread 를 여러 개 만들려고 한다면 

CWinThread *pThread[5];

for ( int i = 0; i < 5; i++ )       m_pThread[i] = ::AfxBeginThread(RUNTIME_CLASS(CUIThread)); 와 같이 하면 5개의 Thread가 생성된다. Program Execution Priority(프로그램 실행 우선순위) Thread 0~31까지의 priority를 가질 수 있다. 프로그램의 priority BOOL SetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass); 함수를 이용해서 조정할 수 있다첫 번째 인자 hProcess ::AfxGetInstanceHandle()로 얻으면 된다. dwPriorityClass

Execution Priority Description
IDLE_PRIORITY_CLASS CPU IDLE일 때만 사용 가능
NORMAL_PRIORITY_CLASS 보통
HIGH_PRIORITY_CLASS 높은 우선 순위
REALTIME_PRIORITY_CLASS 최상위의 우선순위

 Thread Execution Priority(쓰레드 실행 우선순위) ::AfxBeginThread() 함수의 nPriority를 통해서 설정하거나 CWinThread::SetThreadPriority 를 사용해 설정할 수 있다. BOOL SetThreadPriority(HANDLE hThread, int nPriority); nPriority

Execution Priority Description
THREAD_PRIORITY_IDLE REALTIME_PRIORITY_CLASS의 경우 16, 그 외에는 1
THREAD_PRIORITY_LOWEST 프로세스의 우선순위보다 2단계 낮은 우선순위를 가진다
THREAD_PRIORITY_BELOW_NORMAL 프로세스의 우선순위보다 1단계 낮은 우선순위를 가진다
THREAD_PRIORITY_NORMAL 프로세스의 우선순위가 같은 우선순위
THREAD_PRIORITY_ABOVE_NORMAL 프로세스의 우선순위보다 1단계 높은 우선순위를 가진다
THREAD_PRIORITY_HIGHEST 프로세스의 우선순위보다 2단계 높은 우선순위를 가진다
THREAD_PRIORITY_CRITICAL REALTIME_PRIORITY_CLAS의 경우 31 그 외에는 16

 프로그래머가 우선순위를 조정해도 Windows Scheduler가 상황에 맞게 조정하기 때문에 우선순위는생각하고 조금 다를 수 있다. 

Thread & Memory

  Thread의 지역 변수는 모두 별도로 Stack을 만들고 Local Variable들을 관리하기 때문에 위의 

CWinThread *pThread[5];

for ( int i = 0; i < 5; i++ )       m_pThread[i] = ::AfxBeginThread(RUNTIME_CLASS(CUIThread)); 와 같은 경우에도 각 Thread가 다른 Thread를 침범하는 일은 없다. 이 쯤에서 끝났나 싶겠지만… 아직 갈 길이 멀다.Critical section, Mutex, Semaphore 같은 것들은 다음에

 

Multithreading synchronization(멀티쓰레드의 동기화) => http://blog.naver.com/xtelite/50023359879 

프로그램

 

Worker thread

 

#include "stdafx.h"#include "console.h"

 

#include <iostream>

 

using namespace std;

 

#ifdef _DEBUG#define new DEBUG_NEW

#endif

 

// The one and only application object

CWinApp theApp;

 

using namespace std;

 

UINT ThreadPrintNum(LPVOID pParam);

 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])

{

       int nRetCode = 0;

 

       // initialize MFC and print and error on failure

       if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))

       {

             _tprintf(_T("Fatal Error: MFC initialization failed\n"));

             return 1;

       }

 

       static BOOL bContinue = TRUE;

       CWinThread *pThread = ::AfxBeginThread(ThreadPrintNum, &bContinue);

 

       int count = 0;

       while ( count < 1000 )

       {

             count++;

       }

 

       Sleep(1000);

       pThread->SuspendThread();

       cout << "Thread suspended. Waiting for 2 seconds" << endl;

 

       Sleep(2000);

       cout << "Thread resumed" << endl;

       pThread->ResumeThread();

 

       cout << "Quit thread" << endl;

       bContinue = FALSE;

       Sleep(100);

 

       return nRetCode;

}

 

// 쓰레드함수

UINT ThreadPrintNum(LPVOID pParam)

{

       BOOL *pbContinue = (BOOL *)pParam;

       int count = 0;

       while ( *pbContinue )

       {

             count++;

       }

       cout << "Exit thread" << endl;

       return 0;

}

 

User interface thread

 

#include "stdafx.h"#include "console.h"

 

#include "MyDialog.h"

 

#include <cstdlib>

 

using namespace std;

 

#ifdef _DEBUG#define new DEBUG_NEW

#endif

 

// The one and only application object

CWinApp theApp;

 

using namespace std;

 

class CUIThread : public CWinThread

{

       DECLARE_DYNCREATE(CUIThread)

 

public:

       virtual BOOL InitInstance();

};

 

IMPLEMENT_DYNCREATE(CUIThread, CWinThread)

 

BOOL CUIThread::InitInstance()

{

       m_pMainWnd = new CMyDialog;

       m_pMainWnd->ShowWindow(SW_SHOW);

       m_pMainWnd->UpdateWindow();

       return TRUE;

}

 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])

{

       int nRetCode = 0;

 

       // initialize MFC and print and error on failure

       if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))

       {

             _tprintf(_T("Fatal Error: MFC initialization failed\n"));

             return 1;

       }

 

       CWinThread *pThread = ::AfxBeginThread(RUNTIME_CLASS(CUIThread));

      

       system("pause");

 

       return nRetCode;

}

 



=================================

=================================

=================================

 

 

출처: http://packetslaboratory.blogspot.kr/2013/09/mfc-mfc-ui-thread-dialog.html

 

[MFC] MFC에서 UI Thread를 이용한 Dialog 호출 방법

 
===============================================================
출처 :
 http://blog.naver.com/PostView.nhn?blogId=aladdin07&logNo=150074142378&categoryNo=8&viewDate=&currentPage=1&listtype=0
===============================================================

1.목적
메인 프로그램에서 메뉴 항목을 선택하면 별도의 Dialog가 생성되어 거기서 정보를 입력 받는다.
단, 메인프로그램과 생성된 Dialog는 상호 독립적으로 구동되어야 한다.
(즉, 메인프로그램에서 DoModal()로 Dialog를 구동시키지 않고 별도 Thread로 구동 시켜야 한다)

2.방법
CWinThread Class를 활용한다.

① Class Wizard를 사용하여 CWinThread를 Base Class로하는 Class(CDlgThread)를 정의한다.
    Header File(DlgThread.h)에는 'DECLARE_DYNCREATE(CDlgThread);'
    Source File(DlgThread.cpp)에는 'IMPLEMENT_DYNCREATE(CDlgThread ,CWinThread)'
    ClassWizard에 의해 자동으로 추가됩니다.

② DlgThread.h를 수정한다.
    - protected로 정의된 Constructor DlgThread()와 Deconstructor ~DlgThread()를 public으로
      바꾸어 준다. (이유는 해보면 안다)

      public:
           DlgThread();
           ~DlgThread();

③ Dialog 변수를 정의 한다.
    public:
         CDialog* m_pDlg;

④ CDlgThread의 InitInstance()에서 다음과 같이 독립실행 시킬 Dialog(CMyDlg)를 생성한다.
    이 작업은 Thread에 Dialog를 Binding 시키는 과정이다.
    BOOL CDlgThread::InitInstance()
    {
        m_pDlg = new CMyDlg();
        m_pDlg->ShowWindow( SW_SHOW );
        m_pDlg->UpdateWindow();
        return TRUE;
    }

⑤ CMyDlg Class의 Constructor를 수정한다.
    CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)
         : CDialog(CMyDlg::IDD, pParent)
    {
        Create( IDD_MyDlg );    <== 요놈 추가
        //{{AFX_DATA_INIT(CDlgClub)
        // NOTE: the ClassWizard will add member initialization here
        //}}AFX_DATA_INIT
    }

⑥ 필요한 곳에서 다음과 같이하여 Thread를 구동 시키면 된다.

    CDlgThread*  m_pThread = new CDlgThread();
    m_pThread->CreateThread();

※ 상기와 같이하면 UI Thread를 구현할 수 있다..간단하죠~~잉..?
    위와 같이 구동된 Thread Dialog는 OK, CANCEL 버튼을 눌러도 소멸되지 않습니다.
    단지 HIDE 상태로 되는 거죠..
    따라서, 명시적으로 Thread Dialog를 죽이지 않았다면..메인 프로그램이 끝날때까지 Thread로
    남아 있게되는 거죠....요놈을 다시 사용하고 싶을때는 다음 두 줄로 다시 나타나게 만들면 된다.
    m_pThread->m_pDlg->ShowWindow( SW_SHOW );
    m_pThread->m_pDlg->UpdateWindow();
    
※ 명시적으로 Thread Dialog를 종료시킬려면 간단하다.
    Thread Dialog에 WM_QUIT Message를 보내면 된다.
    어떻게..?  PostThreadMessage()를 사용하면 된다.

    m_pThread->PostThreadMessage(WM_QUIT,0,0);

 

=================================

=================================

=================================

 

 

 

반응형

 

728x90

 

 

 

출처: http://darkpgmr.tistory.com/42

 

MFC C++ 다이얼로그(dialog) 기반 프로그램에서 시간이 오래 걸리는 작업을 수행하다 보면 수행 동안에는 사용자 입력(키보드, 마우스)이 먹히지 않고 다이얼로그가 먹통이 되는 UI 블로킹(응답없음,멈춤,정지,다운 등) 현상이 발생한다.

 

 

 

 

원인은 다이얼로그 사용자 이벤트 메시지 처리하는 부분과 함수 실행 부분이 단일 쓰레드로 실행되어 메시지 파이프라인을 공유하기 때문에 함수처리가 끝나기 전까지는 메시지 처리가 안되기 때문인데, 가장 좋은 해결책은 시간이 오래 걸리는 해당 함수처리 부분을 별도 쓰레드로 분리하여 실행시키는 것이다.

 

하지만, 다른 한 방법은 메시지 큐에 있는 메시지들을 다음과 같이 직접 처리해 주는 방법도 있다.

 

void ProcessWindowMessage()

{

   MSG msg;

   while(::PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))

   {

      ::SendMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);

   }

}

 

이렇게 메시지처리 함수를 하나 만들어 놓고, 시간이 걸리는 함수 중간 중간에 위 함수를 호출해 주면 함수 실행 도중이더라도 사용자가 누른 버튼이나 키보드 메시지가 정상적으로 처리된다.

 

물론 가장 좋은 방법은 별도 쓰레드로 분리시키는 것이겠지만, while이나 for문 돌리는 반복형태의 프로그램에서는 그냥 간단하게 위 코드를 삽입해서 처리하는 것도 좋은 방법이다.



출처: http://darkpgmr.tistory.com/42 [다크 프로그래머]

 

=================================

=================================

=================================

 

 

출처: http://mhspecial.tistory.com/entry/MFC-%EC%9E%91%EC%97%85%EC%9E%90-%EC%8A%A4%EB%A0%88%EB%93%9CWorker-Thread-%EC%99%80-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%8A%A4%EB%A0%88%EB%93%9CUser-Interface-Thread

 

스레드(Thread) :

 

하나의 응용프로그램에서 한번에 여러가지 작업을 할 수 있게끔 해주는 역할을 한다. Thread는 크게 두가지 종류가 있다. Worker Thread UI Thread가 그것이다.

Worker Thread Thread가 작업을 하고 있을 때해당 Thread에 별도의 입력이 필요 없을 때 사용한다메시지 루프를 사용하지 않기 때문이다해당 Thread를 제외하고 다른 부분에서는 입력을 받을 수 있지만, Worker Therad 내에서의 동작중에서 Worker Thread에 입력은 안된다.

반면에 UI Therad의 경우 Thread의 작업을 하는 동안에도 메시지 루프는 계속 돌아가고 있기 때문에동작중에도 사용자의 입력을 받아 처리가 가능하다.

 

Worker Thread 의 사용예를 간단한 Progress control  Edit Box를 사용하여 알아본다.


 

 

 

1.   Progress Control : Worker ThreadA.   ID : IDC_PROGRESS_WTB.   컨트롤 변수 : m_progressWT2.   Progress Control : UI ThreadA.   ID : IDC_PROGRESS_UIB.   컨트롤변수 : m_progressUI3.   Static ControlA.   ID : IDC_STATIC_WTB.   컨트롤변수 : m_strWT4.   Static ContriolA.   ID : IDC_STATIC_UIB.   컨트롤변수 : m_strUI

 

일단 위와 같은 Dialog based 프로젝트 디자인을 한다.

 

그리고 Dialog를 초기화하며 Progress Bar 의 범위를 지정 해 준다

BOOL CThreadDlg::OnInitDialog()

{

//       ~~~

         m_progressWT.SetRange(0, 1000);

         m_progressUI.SetRange(0, 1000);

         return TRUE;

}

 

Worker Thread의 경우 전역함수로 간단하게 구현해 보았다.

전역함수로 다음을 추가

 

UINT WorkerThread(LPVOID lParam)   //Thread를호출한클래스의주소값을받는다

{

         CThreadDlg* dlg = (CThreadDlg*)lParam; //호출한클래스의포인터객체생성

         int per = 0;

         for(int i=0; i<1000; i++)  //0부터999까지1000번의루프를실행하며

         {

                  Sleep(1);

                  dlg->m_progressWT.SetPos(i);       //프로그레스바를수정

                  if(i%10==0)

                  {

                           per++;

                           dlg->m_strWT.Format(_T("%d%%"), per);       //퍼센트출력

                           dlg->SetDlgItemTextW(IDC_STATIC_WT, dlg->m_strWT);

                  }

         }

         dlg->GetDlgItem(IDC_BTN_WT)->EnableWindow(TRUE);     //작업완료시버튼활성화

         return 0;

}

 

호출부는 다음과 같다

Start 버튼 클릭 시 이벤트를 발생

void CThreadDlg::OnBnClickedBtnWt()

{

         AfxBeginThread(WorkerThread, this);

         GetDlgItem(IDC_BTN_WT)->EnableWindow(0);

}

 

Worker Thread를 호출하는 부분은 의외로 간단하다

AfxBeginThread(WorkerThread, this);

호출할 함수의 이름과 함수의 인자값을 위와 같이 차례로 적어주면 스레드가 생성된다.

 

 

 

 

또한 UI 스레드의 사용 예는 다음과 같다

 

CUIThread 클래스를 생성해준다. Based Class  CwinThread

그리고 클래스의 멤버함수로 int Run() 함수를 등록한다.

이 함수는 UIThread가 호출될 때 실행 될 함수다.

다음과 같이 함수를 작성한다

 

#include "ThreadDlg.h"int CUIThread::Run(void)

{

        CThreadApp* pApp = (CThreadApp*)AfxGetApp();

        CThreadDlg* pDlg = (CThreadDlg*)pApp->m_pMainWnd;

        int nPer = 0;

        for(int a=1; a<1001; a++)

        {

               pDlg->m_progressUI.SetPos(a);

               if(a%10 ==0)

               {

                       nPer++;

                       pDlg->m_strUI.Format(_T("%d%%"), nPer);

                       pDlg->SetDlgItemText(IDC_STATIC_UI, pDlg->m_strUI);

               }

               Sleep(1);

        }

        pDlg->GetDlgItem(IDC_BTN_UI)->EnableWindow(TRUE);

        return 0;

}

 

UIThread의 호출부는 다음과 같다.#include "UIThread.h"void CThreadDlg::OnBnClickedBtnUi()

{

        AfxBeginThread(RUNTIME_CLASS(CUIThread));

        GetDlgItem(IDC_BTN_UI)->EnableWindow(FALSE); //버튼비활성화

}


실행해보면 버튼을 누를때마다 스레드가 생성되어 별개의 작업을 하고 동시에 에디트박스도 이용이 가능함을 알 수 있다.

 

=================================

=================================

=================================

 

 

출처: http://igotit.tistory.com/entry/MFC-User-Interface-Thread-%EA%B5%AC%ED%98%84

 

 
 
Visual C++ 에서 User Interface Thread 구현방법.
 
상황예.
프로젝트 CyFinAPI 에 2개의 클래스 CCyDevice2_Market_UIT (CWinThread를 베이스클래스로함), CCyDevice2_Market_UITDlg(CDialogEx를 베이스 클래스로 함) 신규생성.
 

 

 

 

 

상세.

 
 
단계1. 프로젝트에 CWinThread를 베이스로 하는 클래스 추가.
 
클래스 위저드에서 MFC Class 추가 선택하여, CWinThread를 베이스로 하는 CCyDevice2_Market_UIT  추가한다. 





단계2. 프로젝트에 대화상자 추가.
상세방법 : http://igotit.tistory.com/480 과 동일하며 베이스클래스를 CDialogEx로하고, 클래스이름을 CCyDevice2_Market_UITDlg로 하면됨. 
 
 
단계3. CWinThread와 CDialog 의 연동처리
 
앞의 단계1에서 만들어진 클래스 CCyDevice2_Market_UIT 와 단계2에서 만들어진 클래스 CCyDevice2_Market_UITDlg 연동처리한다
. 연동의 의미는 우리가 UI 스레드 생성시 CWinThread 인 CCyDevice2_Market_UIT 를 생성하게되며 동시에 종속된 CDialog 인
 CCyDevice_Market_UITDlg 도 생성하게 된다. 이를 달성하기 위해서 CCyDevice2_Market_UIT 의 InitInstnce 에는 CDialog 개체
 생성, CWinThread의 멤버변수인 m_pMainWnd를 CDialog 개체로 지정 한다. 
스레드 종료시  수행되는 CCyDevice2_Market_UIT 의 ExitInstance 에는 CDialog 개체 제거하는 코드가 추가된다.
 
 
상세.
 
 
단계1. 프로젝트에 CWinThread를 베이스로 하는 클래스 추가.
 
클래스 위저드에서 MFC Class 추가 선택하여, CWinThread를 베이스로 하는 CCyDevice2_Market_UIT  추가한다. 
 
 
 
 
 
단계2. 프로젝트에 대화상자 추가.
상세방법 : http://igotit.tistory.com/480 과 동일하며 베이스클래스를 CDialogEx로하고, 클래스이름을 CCyDevice2_Market_UITDlg로 하면됨. 
 
 
단계3. CWinThread와 CDialog 의 연동처리
 
앞의 단계1에서 만들어진 클래스 CCyDevice2_Market_UIT 와 단계2에서 만들어진 클래스 CCyDevice2_Market_UITDlg 연동처리한다. 연동의 의미는 우리가 UI 스레드 생성시 CWinThread 인 CCyDevice2_Market_UIT 를 생성하게되며 동시에 종속된 CDialog 인 CCyDevice_Market_UITDlg 도 생성하게 된다. 이를 달성하기 위해서 CCyDevice2_Market_UIT 의 InitInstnce 에는 CDialog 개체 생성, CWinThread의 멤버변수인 m_pMainWnd를 CDialog 개체로 지정 한다. 
스레드 종료시  수행되는 CCyDevice2_Market_UIT 의 ExitInstance 에는 CDialog 개체 제거하는 코드가 추가된다.
 
BOOL CCyDevice2_Market_UIT::InitInstance()
{
/// 시작 - 본 CWinThread 와 연동된 CDialog 생성.
m_pCyDevice2_Market_UITDlg[m_emItemtype] = new CCyDevice2_Market_UITDlg(); // this에 연동할 CDialog 동적생성하고 받아둠. 
m_pCyDevice2_Market_UITDlg[m_emItemtype]->m_pUIT = this; // CDialog에서 this에 접근하기 위한 변수에 this저장.아래 Create보다 먼저할것.
m_pCyDevice2_Market_UITDlg[m_emItemtype]->Create(IDD_CYDEVICE2_MARKET_UITDLG); // CDialog Create 
m_pCyDevice2_Market_UITDlg[m_emItemtype]->ShowWindow(SW_SHOW);                  // CDialog Show
m_pCyDevice2_Market_UITDlg[m_emItemtype]->UpdateWindow(); // CDialog WM_PAINT
this->m_pMainWnd = m_pCyDevice2_Market_UITDlg[m_emItemtype]; // this(CWinThread)의 m_pMainWnd를 CDialog 로지정.
/// 끝 - 본 CWinThread 와 연동된 CDialog 생성.
return TRUE;
}
 



출처: http://igotit.tistory.com/entry/MFC-User-Interface-Thread-구현 [igotit]

 

 

=================================

=================================

=================================

 

반응형


관련글 더보기

댓글 영역