본문 바로가기

프로그래밍/MFC (C++)44

MFC ] 정적 라이브러리에서 MFC 사용 MFC 프로젝트를 생성하면 디폴트가 "공유 DLL에서 MFC 사용"으로 되어있다. 이 설정은 해당 프로그램이 필요로 하는 MFC 라이브러리를 DLL을 사용하여 참조하겠다는 뜻으로 대상시스템에서 Visual C++ 재배포 패키지를 설치하거나, mfc*.dll 파일을 구해 system32 또는 sysWow64 경로에 넣어주어야 정상적으로 동작한다. 반면 "정적 라이브러리에서 MFC 사용" 옵션을 선택하면 실행파일에 필요한 dll이 포함되어 컴파일되기 때문에 실행파일의 사이즈는 커지지만 배포시 별도의 dll을 같이 제공할 필요가 없다. 런타임 라이브러리도 실행파일에 포함시켜 배포하기 위해 /MD가 아니라 /MT 옵션으로 바꿔주는 것도 잊지 않는다. 2023. 12. 15.
MFC ] 컨트롤 색상 변경하기 WM_CTLCOLOR 메시지는 컨트롤이 처음 생성될 때 또는 컨트롤이 다시 그려져야할 필요가 있을 때 컨트롤의 색상을 결정하기 위한 메시지 이다. 이 메시지의 핸들러를 등록하여 컨트롤의 색상을 처리할 수 있다. 파라미터는 다음과 같다. pDC : 윈도우에서 그리기 작업에 필요한 모든 정보를 가지고 있는 디바이스 컨텍스트 구조체 포인터 pWnd : 화면에 그려질 대상 컨트롤에 대한 포인터 nCtlColor : 컨트롤의 종류에 대한 정수값. 예를들어 에디트 컨트롤이라면 CTLCOLOR_EDIT이고 해당 컨트롤이 읽기 전용이라면 CTLCOLOR_STATIC이 된다. 위 파라미터를 활용하여 특정 컨트롤에 대한 색상 처리를 수행하고 변경된 색상을 나타내는 HBRUSH를 반환하면 된다. 반환된 브러시는 실제 해당 .. 2023. 12. 14.
MFC ] PeekMessage() / GetMessage()와의 차이 PeekMessage()와 GetMessage() 함수는 Windows 시스템 메시지 큐에서 메시지를 가져오는 함수이며, 동일한 4개의 매개변수를 갖는다. BOOL PeekMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg ); lpMsg: MSG 구조체에 대한 포인터로, 함수 호출 이후 메시지 정보가 채워진다. hWnd: 메시지를 확인할 창 또는 윈도우 핸들. 일반적으로 nullptr로 설정하면 어떤 윈도우에서든 해당 메시지를 확인한다. wMsgFilterMin: 확인할 메시지 범위의 최소 값으로 WinUser.h에 정의되어 있다. wMsgFilterMax: 확인할 메시지 범위의 최대 값으로 Wi.. 2023. 11. 14.
Win32 API ] 메시지 루프 C언어를 처음 배우고 콘솔환경에서 프로그래밍을 하다가 윈도우 프로그래밍을 시작하면 어디가 프로그램의 시작점이고 어디서부터 순차적으로 명령이 실행되는 것인지 알지 못해 당황하는 경우가 적지 않다. 콘솔과 달리 윈도우 환경에서는 사용자가 발생시키는 이벤트에 대한 메시지를 처리하는 방식으로 프로그램이 수행되고 이를 메시지 기반(또는 이벤트 기반) 프로그래밍이라고 한다. 메시지란? 사용자나 시스템에 의해 발생된 일체의 변화에 대한 정보를 말한다. ex. 마우스 왼쪽 버튼 클릭, 키보드 누름, 윈도우 최소화 등 이런 이벤트가 발생하면 윈도우 시스템에 존재하는 메시지큐에 메시지가 쌓이고, 애플리케이션에서는 윈도우시스템 메시지큐에서 메시지를 가져와서 특정 메시지 발생시 어떠한 일을 수행할 것인가에 대한 처리 루틴을 .. 2023. 11. 13.
MFC ] 특정 컨트롤에 포커스 설정하기 1. 다이얼로그 생성시 특정 컨트롤을 포커스된 상태로 두는법 리소스뷰에서 서식 - 탭 순서를 클릭하면 현재 설정된 탭순서(Tab키 눌렀을 때 이동되는 순서)가 표시되는데 컨트롤을 순서대로 클릭하여 탭순서를 재배치 할 수 있다. 포커스된 상태로 둘 컨트롤을 첫번째 순서로 설정하면 된다. 2. 코드에서 포커스 옮기기 컨트롤 객체가 있다면 바로 .SetFoucs() 함수를 사용하면 되지만 컨트롤 객체가 없는 다이얼로그 상의 컨트롤을 조작하려면 GetDlgItem() 함수를 사용하면 된다. GetDlgItem() 함수는 컨트롤의 ID를 통해 다이얼 로그 상 컨트롤을 식별하는 데 사용되며 컨트롤의 핸들 CWnd*를 반환한다. 이 핸들을 사용해 컨트롤을 조작할 수 있다. CWnd* GetDlgItem(int nID.. 2023. 11. 6.
시스템 종료와 관련된 윈도우 메시지 WM_QUERYENDSESSION, WM_ENDSESSION 다이얼로그 종료시 WM_CLOSE 메시지가 전달되지만, 다이얼로그 종료 전 윈도우가 먼저 종료된다면 WM_CLOSE 메시지는 전달되지 않는다. 따라서 응용프로그램이 윈도우 종료 시 수행해야할 작업이 있다면, WM_QUERYENDSESSION, WM_ENDSESSION 메시지 처리를 통해 가능하다. WM_QUERYENDSESSION 시스템 종료 확인 메시지. 윈도우에선 시스템 종료 또는 로그오프 시 WM_QUERYENDSESSION 메시지를 모든 윈도우에 전송하고, 응용프로그램은 이 메시지를 받아서 준비작업을 수행한 뒤 TRUE를 반환하거나 종료를 취소하기 위해 FALSE를 반환할 수 있다. 만약 모든 응용프로그램이 TRUE를 반환하면 WM_ENDSESSION 전송 단계로 넘어간다. WM_ENDSESSIO.. 2023. 11. 2.
MFC ] 사용자 지정 메시지와 메시지 처리기 만들기, SendMessage, PostMessage 메뉴에서 프로젝트 - 클래스 마법사 - -Dlg클래스 선택 - 사용자 지정 메시지 추가로 추가하는 방법도 있다. 방법 먼저 사용자 지정 메시지를 정의한다. #define MY_MSG1(WM_USER + 1) #define MY_MSG2(WM_USER + 2) Windows API에는 미리 정의된 메시지 상수가 많이 있지만, 애플리케이션의 필요에 따라 추가적인 사용자 지정 메시지를 정의할 수 있는데, 이때 WM_USER를 사용하여 사용자 지정 메시지의 베이스 값을 설정한다. WM_USER의 값은 0x0400으로 (WM_USER + n) 이런식으로 정의하면 다른 시스템 또는 프레임워크 메시지와 충돌하지 않도록 할 수 있다. 다음은 다이얼로그 헤더에 메시지 처리기를 추가한다. afx_msg LRESULT My.. 2023. 9. 15.
MFC ] 리스트박스 스크롤 하단으로 내리는 법 // ... m_listBox.SetCurSel(m_listBox.GetCount() - 1); m_listBox.SetCurSel(-1); // ... 리스트박스의 가장 마지막 인덱스를 선택한다. 포커스를 다시 해제해 파란색으로 표시되지 않게하면 스크롤을 맨 아래로 이동하는 효과만 남는다. 2023. 9. 15.
MFC ] 다이얼로그 생성시 함수 호출 순서 처음 MFC 어플리케이션의 시작점인 WinMain()함수가 실행되고 InitInstance()함수를 호출하여 어플리케이션의 다이얼로그를 생성하고 .DoModal(); 함수를 호출하게 된다. DoModal() PreSubclassWindow() OnNcCreate() OnNcCalcSize() OnCreate() OnSize() OnMove() OnSetFont() OnInitDialog() OnWindowPosChanging() OnMove() OnWindowPosChanged() OnWindowPosChanging() OnNcActivate() OnActivate() OnShowWindow() OnWindowPosChanging() OnNcPaint() OnEraseBkgnd() OnChildNotif.. 2023. 9. 15.
MFC ] 멀티바이트 집합 사용시에도 현대적 UI 적용하기 Framework.h에 #ifdef _UNICODE, #endif 주석 처리 #ifdef _UNICODE #if defined _M_IX86 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_X64 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' v.. 2023. 9. 15.
MFC ] EditBox에서 편집하고 엔터치면 입력되게끔 하기 PreTranslateMessage(MSG* pMsg) 함수 재정의 BOOL AppDlg::PreTranslateMessage(MSG* pMsg) { // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다. // 키보드 입력시 if (pMsg->message == WM_KEYDOWN) { // 엔터키인 경우 if (pMsg->wParam == VK_RETURN) { // 현재 다이얼로그나 윈도우에서 포커스를 가진 컨트롤(윈도우)을 반환 CWnd* pFocusWnd = GetFocus(); // 컨트롤 ID가 에딧박스인 경우 입력처리 if (pFocusWnd != nullptr && pFocusWnd->GetDlgCtrlID() == IDC_EDIT_CMD) { OnBnClicked.. 2023. 9. 15.
MFC ] 클래스 마법사 오류 CCmdTarget 파생 클래스가 아닌 이 클래스에는 명령을 추가할 수 없습니다. 프로젝트 폴더에 가서 .vs 폴더을 다른 이름으로 바꾼 뒤 다시 프로젝트를 열면 .vs 폴더가 다시 생성되면 클래스 마법사가 된다. 리소스에서 구문분석을 하지 못했습니다. 리소스뷰에 다이얼로그에가서 버튼하나 만들어주고 빌드한뒤 다이얼로그랑 Resource.h에서 만들었던 버튼 삭제하면 됨 2023. 9. 15.
MFC ] 엔터, ESC 키 입력시 종료되지 않게하기 엔터키 입력 시 종료되지 않게하기 OnOK 함수 재정의 OnOK() 호출 주석처리 void CRwrTesterDlg::OnOK() { // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다. //CDialogEx::OnOK(); } ESC 키 입력 시 종료되지 않게하기 OnCancel() 함수를 재정의해서 주석처리하면 Alt+F4가 눌리거나 다이얼로그의 X버튼이 눌린 경우에도 종료되지 않기 때문에 다른방법을 쓴다. PreTranslateMessage(MSG* pMsg) 함수 재정의 해당함수는 키보드 및 마우스 메시지를 번역하고 처리하기 전에 호출되는데 ESC키 입력시 바로 리턴하여 어플리케이션이 종료되지 않도록 한다. BOOL CRwrTesterDlg::PreTranslateMes.. 2023. 9. 15.
MFC ] 리스트 컨트롤에 행 단위 색상 입히기 (글자색/배경색) 메시지맵에 다음을 추가한다. BEGIN_MESSAGE_MAP(CdeltaControlDlg, CDialogEx) //... ON_NOTIFY(NM_CUSTOMDRAW, IDC_LIST_MEMORY, OnCustomdrawMyList) END_MESSAGE_MAP() notification code가 NM_CUSTOMDRAW 일 때 내 리스트 컨트롤 ID로 부터 온 WM_NOTIFY 메시지를 핸들 하고 싶다는 뜻이다. 헤더에 메시지 처리함수의 원형을 선언한다. afx_msg void OnCustomdrawMyList(NMHDR* pNMHDR, LRESULT* pResult); 메시지 처리 함수의 정의 void CdeltaControlDlg::OnCustomdrawMyList(NMHDR* pNMHDR, LR.. 2022. 9. 18.
MFC ] 쓰레드의 생성 및 시작, 종료, 일시 중단, 재개 -Dlg.h 파일에 쓰레드 핸들링을 위한 변수 선언 typedef enum { THREAD_STOP, THREAD_RUNNING, THREAD_PAUSE }_ThreadStatus; //... public: CWinThread* m_pThread; _ThreadStatus m_threadStatus; 쓰레드 함수 전역으로 정의 만약 메인 함수로 정의하려면 앞에 static 을 붙여야 한다. 함수 앞에 static을 붙이면 전역으로 취급되지만 해당 소스파일 내에서만 호출할 수 있다. UINT ThreadRepeat(LPVOID LpData) { CdeltaControlDlg* pDlg = (CdeltaControlDlg*)(LpData); vector& refList = pDlg->DC.getList();.. 2022. 9. 18.
MFC ] 새 코드 요소를 반환하지 못했습니다. 구문 오류일 수 있습니다. 해결방법 프로젝트 폴더 내의 .vs 폴더를 지우고 다시 실행시키면 잘 된다. 2022. 9. 18.
Warning: skipping non-radio button in group 경고 제거하는 법 큰 문제는 없지만 보기 거슬리니 제거하는 방법은 다음과 같다. CTRL + D 를 누르면 각 컨트롤의 번호를 볼 수 있고 이 상태에서 클릭을 하면 1부터 순차적으로 다시 지정할 수 있다. 그룹의 라디오 버튼을 순차적으로 눌러주고 마지막 라디오 버튼의 다음 번호인 컨트롤의 속성-그룹을 True 로 바꿔주면 해당 경고문구는 사라진다. 2022. 9. 14.
MFC ] 라디오 버튼 그룹 지정하여 사용하기 + 초기값 지정하기 직관적으로 만들기 위해 그룹 박스를 먼저 그려주고 그 위에 라디오 버튼을 만든다. 라디오 버튼을 MOVE, DELAY, PUMP 이렇게 3개를 만들었다. 내가 생성한 컨트롤에는 각 ID마다 #define으로 숫자값이 부여되는데 이건 Resource.h 에 정의되어 있다. 이 값이 1씩 증가해야 그룹지어 사용할 수 있다. Ctrl+D 를 눌러 중간에 끼어드는 값 없이 번호가 순차적으로 부여되었는지 시각적으로 확인할 수도 있다. 각 라디오 버튼의 속성은 아래처럼 설정한다. 라디오 버튼은 그룹 True 부터 시작해서 다음 True를 만나기 전까지 하나의 그룹으로 묶인다. 이렇게 한 그룹으로 묶이면 클래스 마법사에서 확인해봤을 때 그룹의 첫번째 라디오 버튼만 뜨는 것을 확인할 수 있다. -Dlg.h 파일에 체크.. 2022. 9. 13.
MFC ] 리스트 컨트롤 첫번째 열 가운데 정렬하는 법 BOOL CdeltaControlDlg::OnInitDialog() { //... m_list.SetExtendedStyle( LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); m_list.InsertColumn(0, _T(""), LVCFMT_CENTER, 0); m_list.InsertColumn(1, _T("No."), LVCFMT_CENTER, 40); m_list.InsertColumn(2, _T("Action Type"), LVCFMT_CENTER, 160); m_list.InsertColumn(3, _T("Attributes"), LVCFMT_CENTER, 304); //... } 리스트 컨트롤의 첫번째 열은 왼쪽 정렬밖에 안되는 데 굳이 가운데 정렬를 하고 싶다면 .. 2022. 9. 13.
MFC ] 슬라이더 컨트롤 사용하기 도구 상자 - Slider Control 생성하고 그 옆에 Edit Control을 만든다. ID는 다음과 같이 변경했다. 에디트 컨트롤 속성의 숫자를 True로 하면 숫자만 입력되게끔 할 수 있다. 슬라이더 컨트롤은 범주 컨트롤로 변수 추가하고 에디트 컨트롤은 값 CString으로 변수를 추가한다. OnInitDialog() 에 다음과 같이 추가한다. BOOL CdeltaControlDlg::OnInitDialog() { //... SliderInit(&m_sliderX); SliderInit(&m_sliderY); SliderInit(&m_sliderZ); m_strX.Format(_T("%d"), 0); m_strY.Format(_T("%d"), 0); m_strZ.Format(_T("%d"), -.. 2022. 9. 10.
MFC ] 윈도우 크기 조절 또는 고정하기, 최소/최대 사이즈 지정 1. WM_GETMINMAXINFO 메시지 처리기 함수를 추가한다. 속성 - 메시지 - WM_GETMINMAXINFO 를 찾아서 Add 혹은 프로젝트 - 클래스 마법사 2. OnGetMinMaxInfo 함수 안에서 전달된 파라미러 lpMMI를 사용해 창의 min / max 값을 설정한다. void CdeltaControlDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI) { //lpMMI->ptMinTrackSize.x = 1200; //lpMMI->ptMinTrackSize.y = 800; lpMMI->ptMinTrackSize = CPoint(1200, 800); lpMMI->ptMaxTrackSize = CPoint(1400, 1000); CDialogEx::OnGetMinMax.. 2022. 8. 28.
MFC ] 시리얼 통신으로 LED 제어하기 (3) + MySQL (IoT) STM32 → UART 수신 인터럽트로 '1'이 들어오면 LED를 켜고 '0'이 들어오면 LED를 끈다. MFC → 외부 DB에 접속해 '1' 또는 '0'이 들어있는 1행1열의 테이블을 타이머를 사용해서 0.5초 간격으로 읽어오고 해당 값을 STM32에 시리얼 통신으로 송신한다. STM32 수신 인터럽트 부분 /* USER CODE BEGIN 4 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART3){ if(rx=='1'){ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, 1); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, 1); HAL_GPIO_WritePi.. 2022. 7. 17.
MFC ] 실시간 그래프 그리는 법 Real-Time-Chart sin, cos, tan 그래프를 10ms 마다 그리는 예제파일 다이얼로그의 Picture Control을 아이디 IDC_STATIC_RT_GRAPH 로 추가하고 위치와 크기를 맞춘다. 다이얼로그의 -Dlg.h 파일에서 OScopeCtrl.h 파일을 include 하고 COScopeCtrl 컨트롤의 객체 포인터 _rtGraph를 선언해 둔다. // COScopeCtrl의 헤더 파일 인클루드 #include "OScopeCtrl.h" ... class *Dlg : public CDialog { ... // COScopeCtrl 컨트롤의 객체 포인터를 선언 COScopeCtrl *_rtGraph; ... }; onInitDialog() 함수에서는 IDC_STATIC_RT_GRAPH 컨트롤의 위치와 크기를 얻.. 2022. 7. 17.
MFC ] 다이얼로그 종료시 함수 호출 순서 OnClose, OnDestory, PostNcDestroy X 버튼을 눌러서 다이얼로그를 종료한경우 OnSysCommand start OnClose OnSysCommand end DestroyWindow start OnDestroy DestroyWindow end OnNcDestroy start PostNcDestroy OnNcDestroy end EndDialog(), OnOk(), OnCancel() 등을 이용하여 다이얼로그를 종료한경우 DestroyWindow start OnDestroy DestroyWindow end OnNcDestroy start PostNcDestroy OnNcDestroy end 출처 : https://wendys.tistory.com/117 보다시피 WM_CLOSE 메시지의 핸들러인 OnClose()는 EndDialog(), On.. 2022. 7. 15.
MFC ] CString 문자열 파싱하는 여러 방법 2022.07.14 - [프로그래밍/MFC (C++)] - MFC ] stringstream 사용하여 문자열 파싱하기 일전에 CString 타입을 string 타입으로 바꾸고 stringstream을 사용해서 파싱하는 방법에 대한 글을 적었는데 다른 방법도 있다. 1. AfxExtractSubString 을 사용하는 방법 int lineCount; lineCount = result.Replace('\n',','); for (int i = 0; i < lineCount; i++) { CString tmpID, tmpName, tmpAuthor, tmpPrice, tmpOther; AfxExtractSubString(tmpID, result, 5 * i + 0, ','); AfxExtractSubString.. 2022. 7. 14.
MFC ] 리스트 컨트롤 제일 하단으로 내리는 법 m_list.SendMessage(WM_VSCROLL, SB_BOTTOM); 아래는 리스트 컨트롤 새로고침 시마다 자동으로 아래로 내려가게끔 한 것 2022. 7. 14.
MFC ] stringstream 사용하여 문자열 파싱하기 예제코드 CString result; string str = CT2CA(result); istringstream ss(str); string line; int i = 0; while(getline(ss, line, '\n')) { istringstream linestream(line); string cell; getline(linestream, cell, ','); m_list.InsertItem(i, cell.c_str()); int j = 0; while (getline(linestream, cell, ',')) { m_list.SetItem(i, j, LVIF_TEXT, cell.c_str(), NULL, NULL, NULL, NULL); j++; } i++; } '\n' 와 ',' 로 구분하는 형.. 2022. 7. 14.
MFC ] char* -> CString , CString -> char* 변환하기 char* -> CString 변환 char* h1 = "hello"; CString h2 = h1; 그냥 대입해주면 된다 = 연산자 오버로딩이 되어있기 때문이다. CString -> char* 변환 방법1 char* h1 = "hello"; CString h2 = h1; CString w1 = _T("world"); char* w2 = LPSTR(LPCTSTR(w1)); 방법2 CString w1 = _T("world"); char* w2 = w1.GetBuffer(0); 2022. 7. 14.
MFC ] MySQL 을 활용한 도서 관리 프로그램 (1) 깃허브 주소 : https://github.com/joeteo/bookManagerMFCandMysql.git GitHub - joeteo/bookManagerMFCandMysql Contribute to joeteo/bookManagerMFCandMysql development by creating an account on GitHub. github.com 자료 추가 및 선택 행 삭제 기능 구현 먼저 이전에 쓴 글을 참조해서 데이터 베이스를 생성하고 MySQL 라이브러리를 포함 시킨다. 2022.07.13 - [프로그래밍/MFC (C++)] - MFC ] Visual Studio에서 MySQL 라이브러리 추가하기 2022.07.13 - [데이터베이스] - MySQL ] HeidiSQL 기본 사용법 CM.. 2022. 7. 14.
MFC ] 시리얼 통신으로 LED 제어하기 (2) 이전 버전을 개선하였다. 2022.07.09 - [프로그래밍/MFC (C++)] - MFC ] 시리얼 통신으로 LED 제어하기 (1) MFC ] 시리얼 통신으로 LED 제어하기 (1) 깃허브 주소: https://github.com/joeteo/LEDSerialCMD GitHub - joeteo/LEDSerialCMD Contribute to joeteo/LEDSerialCMD development by creating an account on GitHub. github.com https://github.com/joeteo/.. eteo.tistory.com 깃허브 주소: https://github.com/joeteo/MFC_test01.git GitHub - joeteo/MFC_test01 Contri.. 2022. 7. 13.