반응형

MFC에서 ComboBox(콤보박스) 사용시 사용자가 임의적으로 항목을 수정할 수 있다.


물론 수정된 값을 받는 경우도 있지만, 해당 선택된 항목의 index값을 가져와서 쓰는경우 매개변수가 잘못되었다는 등의 오류가 발생 할 수 있다.


사용자가 수정할 항목이 아닌 경우라면 이를 ReadOnly로 바꿔줄 필요가 있다.


ReadOnly 설정은 따로 코드를 수정하는 경우도 있지만, 간단하게 해당 리소스 속성항목에서 


Type를 "Drop List"로 바꿔주면 된다.


아래는 Reference에 나와있는 Style Type별 상태

StyleWhen is list box visibleStatic or edit control
SimpleAlwaysEdit
Drop-downWhen dropped downEdit
Drop-down listWhen dropped downStatic


반응형

Create로 생성한 모달리스 다이얼로그(dlgModal2)의 생성하고 show가 되었는지 확인하는 조건식


if( dlgModal2 != NULL && dlgModal2->IsWindowVisible() == TRUE )

보이고 숨길떄에는


dlgModal2.ShowWindow(SW_SHOW);
dlgModal2.ShowWindow(SW_HIDE);


이렇게 사용하면 되고


부모창 destory시 반드시 자식 모달리스도 delete해줘야한다.

반응형

사용한 버젼은 CGridCtrl v2.20 이며 생성된 그리드컨트롤에

체크박스를 생성할때 아래와 같이 추가하면된다.

m_gridBinTable.SetCellType(nRow, nCol, RUNTIME_CLASS(CGridCellCheck));	//
pCell = (CGridCellCheck*)m_gridBinTable.GetCell(nRow, nCol);


반응형

출처 : http://bigmark.tistory.com/7


1. 부모 다이얼로그 생성


2. 자식 다이얼로그 생성


- 자식 다이얼로그 속성창에서 style은 child, border는 NONE 으로 설정 변경


3. 부모 다이얼로그의 헤더파일에서 해당 자식 다이얼로그 변수 포인터로 생성


CChildDlg *m_pChildDlg;



4. 부모 다이얼로그의 OnInitDialog에서



m_pChildDlg = new CChildDlg;
m_pChildDlg->Create( CChildDlg::IDD, this );
m_pChildDlg->ShowWindow( SW_SHOW );
m_pChildDlg->MoveWindow( rcDlg ); // 크기는 알아서 맞게 지정


이렇게 하면 자식 다이얼로그가 부모 다이얼로그에 붙는다.

반응형

MFC 로 시리얼 통신하는 코드의 일부이다. 

이번에 공부를 하면서 참고한 코드이다.

WriteByte()함수에서 버퍼크기를 수정하여 사용하면 될듯싶다.


프로그램 종료시 시리얼도 닫아주는걸 잊지말자.


SerialPort.h

class CSerialPort
{
public:
	CSerialPort();
	~CSerialPort();
private:
	HANDLE	m_hComm;
	DCB		m_dcb;
	COMMTIMEOUTS m_CommTimeouts;
	BOOL	m_bPortReady;
	bool	m_bWriteRC;
	bool	m_bReadRC;
	DWORD	m_iBytesWritten;
	DWORD	m_iBytesRead;
	DWORD	m_dwBytesRead;
	BYTE	m_nWriteData[DATA_SIZE];

public:
	void ClosePort();
	bool ReadByte(BYTE &resp);
	bool ReadByte(BYTE* &resp, UINT size);
	bool WriteByte(BYTE *pBuff);
	int SetLevel(int nChannel, int nValue);
	int LightOnOff(int nChannel, bool bOn);
	bool OpenPort(CString portname);
	bool SetCommunicationTimeouts(DWORD ReadIntervalTimeout,
		DWORD ReadTotalTimeoutMultiplier, DWORD ReadTotalTimeoutConstant,
		DWORD WriteTotalTimeoutMultiplier, DWORD WriteTotalTimeoutConstant);
	bool ConfigurePort(DWORD BaudRate, BYTE ByteSize, DWORD fParity,
		BYTE  Parity, BYTE StopBits);
	BOOL ch_state[4];
	BOOL comm_status = OFF;
};

extern CSerialPort m_serial;



SerialPort.cpp

#include "stdafx.h" #include "SerialPort.h" CSerialPort m_serial; CSerialPort::CSerialPort() { } CSerialPort::~CSerialPort() { } bool CSerialPort::OpenPort(CString portname) { m_hComm = CreateFile(L"//./" + portname, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (m_hComm == INVALID_HANDLE_VALUE) { return false; } else return true; } bool CSerialPort::ConfigurePort(DWORD BaudRate, BYTE ByteSize, DWORD fParity, BYTE Parity, BYTE StopBits) { if ((m_bPortReady = GetCommState(m_hComm, &m_dcb)) == 0) { //MessageBox(L"GetCommState Error", L"Error", MB_OK + MB_ICONERROR); CloseHandle(m_hComm); return false; } m_dcb.BaudRate = BaudRate; m_dcb.ByteSize = ByteSize; m_dcb.Parity = Parity; m_dcb.StopBits = StopBits; m_dcb.fBinary = true; m_dcb.fDsrSensitivity = false; m_dcb.fParity = fParity; m_dcb.fOutX = false; m_dcb.fInX = false; m_dcb.fNull = false; m_dcb.fAbortOnError = true; m_dcb.fOutxCtsFlow = false; m_dcb.fOutxDsrFlow = false; m_dcb.fDtrControl = DTR_CONTROL_DISABLE; m_dcb.fDsrSensitivity = false; m_dcb.fRtsControl = RTS_CONTROL_DISABLE; m_dcb.fOutxCtsFlow = false; m_dcb.fOutxCtsFlow = false; m_bPortReady = SetCommState(m_hComm, &m_dcb); if (m_bPortReady == 0) { MessageBox((HWND)"SetCommState Error",NULL, L"Error", MB_OK + MB_ICONERROR); CloseHandle(m_hComm); return false; } return true; } bool CSerialPort::SetCommunicationTimeouts(DWORD ReadIntervalTimeout, DWORD ReadTotalTimeoutMultiplier, DWORD ReadTotalTimeoutConstant, DWORD WriteTotalTimeoutMultiplier, DWORD WriteTotalTimeoutConstant) { if ((m_bPortReady = GetCommTimeouts(m_hComm, &m_CommTimeouts)) == 0) return false; m_CommTimeouts.ReadIntervalTimeout = ReadIntervalTimeout; m_CommTimeouts.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant; m_CommTimeouts.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier; m_CommTimeouts.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant; m_CommTimeouts.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier; m_bPortReady = SetCommTimeouts(m_hComm, &m_CommTimeouts); if (m_bPortReady == 0) { MessageBox((HWND)"StCommTimeouts function failed", NULL, L"Com Port Error", MB_OK + MB_ICONERROR); CloseHandle(m_hComm); return false; } return true; } bool CSerialPort::WriteByte(BYTE *pBuff) { m_iBytesWritten = 0; BYTE temp[9] = { NULL }; for (int i = 0; i < 9;i++) { temp[i] = pBuff[i]; } if (WriteFile(m_hComm, temp, 9, &m_iBytesWritten, NULL) == 0) return false; else return true; } bool CSerialPort::ReadByte(BYTE &resp) { BYTE rx; resp = 0; DWORD dwBytesTransferred = 0; if (ReadFile(m_hComm, &rx, 1, &dwBytesTransferred, 0)) { if (dwBytesTransferred == 1) { resp = rx; return true; } } return false; } bool CSerialPort::ReadByte(BYTE* &resp, UINT size) { DWORD dwBytesTransferred = 0; if (ReadFile(m_hComm, resp, size, &dwBytesTransferred, 0)) { if (dwBytesTransferred == size) return true; } return false; } void CSerialPort::ClosePort() { CloseHandle(m_hComm); return; }


반응형

출처 : http://codens.info/678

쓰레드 생성

- AfxBeginThread 권장 

- CWinThread::m_bAutoDelete 

- 기본은 TRUE, 자동으로 개체(핸들포함)가 삭제됨 <- 권장

- FALSE로 설정하려면 CREATE_SUSPENED 로 시작해서 설정후 ResumeThread()해줘야함

- 해제시 핸들을 닫으면 안되고 CWinThread개체를 delete 해야 함


- AfxEndThread()는 강제 종료 함수로 권장 안함


- CreateThread() 권장 안함



* 쓰레드 종료 대기

    - WaitForSingleObject 사용 권장


    - GetExitCodeThread 는 bAutoDelete = TRUE시 문제 있음, 

- CreateThread()때만 사용, 하지만 권장 안함



//=======================================
//AfxBeginThread

//시작
CWinThread * CSimpleTestDlg::MFC_TrdStart( bool _bAutoDel)
{
    char *str = "MFC_TrdStart"; g_pstr[0]=str;m_pstr[0] = str;
    //쓰레드 생성
    m_bStop=false;
    CWinThread *pWThd=0;
    //
    if( _bAutoDel == false){
        _DbgStr(_T("MFC_TrdStart- 자동삭제=false"));
        //값을 바꾸기위해서는 멈춤->설정->시작
        pWThd = AfxBeginThread( MFC_TrdFunc, this, 0, 0, CREATE_SUSPENDED  );//멈춤    
        pWThd->m_bAutoDelete = FALSE; //기본값은 TRUE, 설정
        pWThd->ResumeThread();//시작
    }else{
        _DbgStr(_T("MFC_TrdStart- 자동삭제=true"));
        pWThd = AfxBeginThread( MFC_TrdFunc, this, 0, 0, 0  );//<- 권장
    }

    if( !pWThd )
        return 0;

    m_hThread = pWThd->m_hThread;
    
    _DbgStr(_T("MFC_TrdStart- 끝=%X"), m_hThread);
    return pWThd;
}

//쓰레드 트리거 함수
UINT __cdecl CSimpleTestDlg::MFC_TrdFunc( LPVOID pParam )
{
    char *str = "MFC_TrdFunc";g_pstr[1]=str;
    CSimpleTestDlg *pClass = (CSimpleTestDlg *)pParam;
    pClass->MFC_TrdProc();
    _DbgStr(_T("쓰레드 종료 MFC_TrdFunc"));//MFC_TrdProc()에 AfxEndThread()가 있으면 여기까지 실행이 안됨
    return 1;
}

//실제 쓰레드 동작
int CSimpleTestDlg::MFC_TrdProc()
{
    char *str = "MFC_TrdProc";g_pstr[2]=str; m_pstr[2] = str;
    while(1)
    {
        if( m_bStop ){
            _DbgStr(_T("쓰레드 종료신호 MFC_TrdProc"));
            break;
        }

        Sleep(1000);
        _DbgStr(_T("쓰레드 실행중 MFC_TrdProc"));
    }

    _DbgStr(_T("쓰레드 종료 MFC_TrdProc-1-%d"), (UINT)GetTime() );
    //AfxEndThread(0);//쓰레드가 강제 종료됨, 사용하면 안됨 TerminateThread()와 같음
    _DbgStr(_T("쓰레드 종료 MFC_TrdProc-2-%d"), (UINT)GetTime() );//
    
    return 1;
}


//===============================================
//쓰레드 종료를 기다린다
//WaitForSingleObject 사용 권장


// CreadThread()로 시작한 쓰레드만 대기, AfxBeginThread() 로 시작한 쓰레드는 사용하면 안됨
int WaitThreadEndH(HANDLE _hThread, int _nWaitMilSec ,  LPCTSTR _sMsg, bool _bClose)
{
    if( !_hThread ) return 0;
    _DbgStr(_T("WaitThreadEnd-시작-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
    //bFinishThread == TRUE; // 종료를 위한 변수설정 후 3초간 대기
    
    DWORD dwExit=0;
    DWORD dwRetCode = WaitForSingleObject(_hThread, _nWaitMilSec);
    if(dwRetCode == WAIT_OBJECT_0) // 정상종료
    {
        _DbgStr(_T("WaitThreadEnd-정상 종료-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
    }
    else if(dwRetCode == WAIT_TIMEOUT) // 타임아웃
    {
        //::TerminateThread(_hThread, 0 );
        _DbgStr(_T("WaitThreadEnd-강제종료-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
    }    

    if( _bClose){  
        //AfxBeginThread()로 생성된 쓰레드는 핸들을 닫으면 안된다. CWinThread를 delete 해야한다.
        //m_bAutoDelete == TRUE 일때는 호출하면 안된다
        CloseHandle( _hThread );
    }

    _DbgStr(_T("WaitThreadEnd-끝-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
    return 1;
}


//AfxBeginThread() 로 시작한 쓰레드는 이함수로 종료해야 함
int WaitThreadEndW(CWinThread *_pWinThread, int _nWaitMilSec, LPCTSTR _sMsg)
{
    if( !_pWinThread ) return 0;
    HANDLE _hThread = _pWinThread->m_hThread;
    _DbgStr(_T("WaitThreadEnd(W)-시작-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
    //bFinishThread == TRUE; // 종료를 위한 변수설정 후 3초간 대기
    bool bAutoDel = _pWinThread->m_bAutoDelete;
    DWORD dwExit=0;
    DWORD dwRetCode = WaitThreadEndH( _pWinThread->m_hThread, _nWaitMilSec, _sMsg, false  );//핸들을 닫으면 안된다.
    
    //m_bAutoDelete = FALSE의 경우 스레드의 삭제
    if(bAutoDel==false)
    {
        GetExitCodeThread(_pWinThread->m_hThread, &dwExit);
        _DbgStr(_T("WaitThreadEnd(W)-쓰레드 클래스 삭제(code=%d)", dwExit));
        
        //if( _bClose) CloseHandle( _hThread );//하면 안됨클래스 해제시 자동 해제 된다.
        
        delete _pWinThread;  
    }    

    _DbgStr(_T("WaitThreadEnd(W)-끝-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
    return 1;
}
//===================================================================


+ Recent posts