참고 링크: https://youtu.be/EoXP_PH0xzA?list=PLlIX4lkC1JdMx-vfK8I-J3-L-GL7TbMf9
github에서 중간단계 파일 받기
위 영상 출처) github에서 gLim-main/mfcExam 검색 후 다운받기
새 다이얼로그 이미지 만들기
헤더 이동 단축키
Ctrl + O + K
DlgImage.h 파일에서 이미지 변수를 만들어 준다.
CImage m_Image; // 이미지 변수를 만든 것
그리고 변수만 선언을 해준것이기 때문에 cpp 파일에서 실체를 만들어줘야 한다.
ctrl + K + O 로 다시 cpp 파일로 돌아가서 initial dialog를 생성해 준다.
다이얼로그가 생성될 때는 항상 initial dialog를 콜(호출)하기 때문에 이 부분이 선행되어야 한다.
클래스 마법사 - 가상함수 - 함수 추가
클래스 마법사 단추기
Ctrl + Shift + X
가상함수 탭에서 OnInitDialog를 찾아 더블클릭한다. 함수 추가를 눌러도 상관없다. 확인을 눌러 코드로 빠져나온다.
아래처럼 함수가 자동으로 추가된다.
BOOL CDlgImage::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 여기에 추가 초기화 작업을 추가합니다.
return TRUE; // return TRUE unless you set the focus to a control
// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}
함수가 제대로 실행되는지를 확인하기 위해 확인용 메세지박스를 넣었다.
BOOL CDlgImage::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 여기에 추가 초기화 작업을 추가합니다.
AfxMessageBox(_T("ready?"));
return TRUE; // return TRUE unless you set the focus to a control
// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}
실행하니 메세지박스가 잘 보여진다.
메세지박스를 지우고, 기존의 코드를 가져온다.
이미지를 생성하는 코드이다.(그리는 부분은 없음)
BOOL CDlgImage::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 여기에 추가 초기화 작업을 추가합니다.
/*AfxMessageBox(_T("ready?"));*/
int nWidth = 640;
int nHeight = 480;
int nBpp = 8;
m_image.Create(nWidth, -nHeight, nBpp);
if (nBpp == 8) {
static RGBQUAD rgb[256];
for (int i = 0; i < 256; i++)
rgb[i].rgbRed = rgb[i].rgbGreen = rgb[i].rgbBlue = i;
m_image.SetColorTable(0, 256, rgb);
}
int nPitch = m_image.GetPitch();
unsigned char* fm = (unsigned char*)m_image.GetBits();
memset(fm, 0xff, nWidth * nHeight);
return TRUE; // return TRUE unless you set the focus to a control
// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}
그리는 부분을 함수로 추가하기 위해 함수를 생성한다.
클래스 마법사(ctrl + K + O)로 그리는 함수로 추가한다.
0, 0 위치에 그리는 명령어를 추가해 준다.
void CDlgImage::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CDialogEx::OnPaint()을(를) 호출하지 마십시오.
if (m_image) {
m_image.Draw(dc, 0, 0);
}
}
코드를 실행하면 0,, 0 위치에 하얗게 그림이 그려진 것을 확인할 수 있다.
모듈화 하기 (=함수 생성하기)
Dlgimage.h
헤더 부분에 함수를 선언해주고
void initImage();
그리고 cpp 파일로 돌아와서 맨 밑에 함수를 생성해준다.
init 밑에 선언되었던 부분을 이 밑으로 옮겨주고
// 이미지 초기화 부분
void CDlgImage::initImage() {
int nWidth = 640;
int nHeight = 480;
int nBpp = 8;
m_image.Create(nWidth, -nHeight, nBpp);
if (nBpp == 8) {
static RGBQUAD rgb[256];
for (int i = 0; i < 256; i++)
rgb[i].rgbRed = rgb[i].rgbGreen = rgb[i].rgbBlue = i;
m_image.SetColorTable(0, 256, rgb);
}
int nPitch = m_image.GetPitch();
unsigned char* fm = (unsigned char*)m_image.GetBits();
memset(fm, 0xff, nWidth * nHeight);
}
init 부분에서는 이 함수만 선언해준다. f12를 누르면 특정 함수로 이동할 수 있다.
창 크기 조절하기
스택오버플로우에서 검색하여 (출처는 아래)
MoveWindow(int x, int y, int Width, int Height);
https://stackoverflow.com/questions/28688653/mfc-modify-the-dialog-size-created-by-resource
창 크기를 조절하는 코드 적용한 부분
부모 파일 안에 나오게 하기
IDD_DLGIMAGE 파일의 리소스에서
다이얼로그 속성 - 스타일 부분을 child로 해주면
실행시 우측사진과 같이 대화상자가 등장한다.
gPrijDlg.cpp(부모 cpp 파일)에서 창 크기를 변환해 주면
아래와 같이 부모 창 안에서만 자식 다이얼로그가 움직이게 할 수 있다.
제목 표시줄(영어로는 title bar) 속성을 False로 하면 타이틀바가 아래와 같이 사라진다.
IDD_GPRJ_DIALOG 에 이 타이틀바 없애는 속성을 적용해 준다.
메인 다이얼로그에서 버튼에 관련된 이벤트 삭제
버튼을 그냥 삭제하면 기존의 코드와 연결된 부분들이 오류가 나오기 때문에
클래스 마법사를 실행 - [메서드] 탭으로 가서 클릭이벤트를 연결하는 메서드를 확인 후 [메서드 삭제]를 통해 삭제한다.
코드를 실행하면 삭제되지 않은 부분을에서 빌드 오류가 나온다.
이 부분들을 찾아 지워주면 된다.
듀얼 다이얼로그 만들기
이미지 그리는 변수와 동일하고 이름만 다르게 변수를 생성해 준다.
gPrijDlg.h 헤더에 먼저 선언만 하고(후에 초기화 부분에서 생성 해줘야 함)
초기화 부분에서 위에 만들었던 부분과 동일하게 생성해 주고(변수만 다르게 해서)
m_pDlgImgResult = new CDlgImage;
m_pDlgImgResult->Create(IDD_DLGIMAGE, this);
m_pDlgImgResult->ShowWindow(SW_SHOW);
MoveWindow 메서드를 사용하여 창 위치를 옮겨준다.
MoveWindow(0, 0, 1280, 800);
m_pDlgImage = new CDlgImage;
m_pDlgImage->Create(IDD_DLGIMAGE, this);
m_pDlgImage->ShowWindow(SW_SHOW);
m_pDlgImage->MoveWindow(0, 0, 640, 480);
m_pDlgImgResult = new CDlgImage;
m_pDlgImgResult->Create(IDD_DLGIMAGE, this);
m_pDlgImgResult->ShowWindow(SW_SHOW);
m_pDlgImgResult->MoveWindow(640, 0, 640, 480);
실행하면 창 2개가 붙어서 나온다.
버튼으로 이미지 띄우기
기본 모달창 IDD_GRPJ_DIALOG 화면에 버튼을 하나 생성하고 ID, 캡션을 변경해 준다.
버튼을 더블클릭하여 버튼클릭 이벤트 함수를 생성한다.
이 버튼을 클릭했을 때 타는 로직은
- 먼저 왼쪽 이미지에 대한 값을 가져오고
- 오른쪽 이미지의 포인터를 사용하여 처리한다
void CgPrjDlg::OnBnClickedBtnTest()
{
// 이미지 가져오기
// 화살표(->)는 포인터, 점(.)은 클래스를 의미
unsigned char* fm = (unsigned char*)m_pDlgImage->m_image.GetBits(); // 리턴값을 unsigned cha로 받는다는 뜻
// 이미지 잘 가져왔는지 테스트
// 뒤의 숫자는 얼만큼 칠할것인지
memset(fm, 0, 640 * 480); // 메모리셋에 fm(이미지포인터), 뒤에오는 것은 값:
// 화면에 업데이트
m_pDlgImage->Invalidate();
}
위의 코드를 실행하면
Test 버튼을 선택했을 때 왼쪽 화면이 어둡게 된다.
랜덤하게 점찍기
위 코드를 수정하여 화면에 랜덤하게 점을 찍어 보자.
아래 코드는 랜덤 함수 rand()를 사용하여 가로값 640, 세로값 480 사이에 랜덤한 좌표 x, y 값을 가져와서 점을 찍는다.
void CgPrjDlg::OnBnClickedBtnTest()
{
// 이미지 가져오기
// 화살표(->)는 포인터, 점(.)은 클래스를 의미
unsigned char* fm = (unsigned char*)m_pDlgImage->m_image.GetBits(); // 리턴값을 unsigned cha로 받는다는 뜻
// 가로 세로 피치 값 가져오기
int nWidth = m_pDlgImage->m_image.GetWidth(); // 가로
int nHeight = m_pDlgImage->m_image.GetHeight(); // 세로
int nPitch = m_pDlgImage->m_image.GetPitch(); // 픽셀마다 행 간격을 나타내는 값
for (int k = 0; k < 100; k++) {
int x = rand() % nWidth;
int y = rand() % nHeight;
fm[y * nPitch + x] = 0;
}
// 이미지 잘 가져왔는지 테스트
// 뒤의 숫자는 얼만큼 칠할것인지
// memset(fm, 0, 640 * 480); // 메모리셋에 fm(이미지포인터), 뒤에오는 것은 값:
// 화면에 업데이트
m_pDlgImage->Invalidate();
}
두번 눌러서 200번 랜덤한 점 찍은 결과
점 갯수 세기
가로에서 세로 폭까지 검은 색의 픽셀이 몇 개인지 세는 for문을 만든다.
// 점 갯수 세기
int nSum = 0; // 합을 셀 변수 설정
for (int j = 0; j < nHeight;j++) {
for (int i = 0; i < nWidth; i++) {
if (fm[j * nPitch + i] == 0)
nSum++;
}
}
std::cout << nSum << std::endl;
std::cout를 사용하여 출력하여
점을 누를 때마다 몇개의 점이 뿌려졌는지 확인할 수 있다.
찍힌 점 좌표 출력하기
using namespace std;
// 점 갯수 세기
int nSum = 0; // 합을 셀 변수 설정
for (int j = 0; j < nHeight;j++) {
for (int i = 0; i < nWidth; i++) {
if (fm[j * nPitch + i] == 0)
cout << i << ","<< j << endl; // 찍힌 좌표 출력
nSum++;
}
}
아래처럼 if문에 {}를 걸어주고 nSum까지 한번에 출력하니
// 점 갯수 세기
int nSum = 0; // 합을 셀 변수 설정
for (int j = 0; j < nHeight;j++) {
for (int i = 0; i < nWidth; i++) {
if (fm[j * nPitch + i] == 0) {
cout << nSum << ":" << i << "," << j << endl; // 찍힌 좌표 출력
nSum++;
}
}
}
이렇게 출력이 되었다.
'개발공부 > C++' 카테고리의 다른 글
[C++] 여러 조건 변경하기, Cpen 색 변경, define (0) | 2023.09.19 |
---|---|
[C++] MFC 다른 윈도우로 포인트 복제하기 (1) | 2023.09.18 |
[C++] MFC 모달리스 다이얼로그 생성하기 (0) | 2023.09.18 |
[C++] MFC Bitmap Image로 버튼 만들기, 클릭시 이미지 전환 (1) | 2023.09.17 |
[C++] MFC CImage 이미지 생성, 저장, 로드, 움직이는 사각형 만들기 (0) | 2023.09.17 |