반응형

① 유니코드&MBCS

선그리기 v.combo를 보면 

iCurrentPenWidth = _ttoi(str);

이런 코드가 있다.

_ttoiatoi는 C언어에서 텍스트를 정수로 바꿔주는 함수 atoi와 똑같은 역할을 한다.

그러면 atoi와 다른 점은 무엇일까? 

atoi는 멀티바이트코드를 읽는 멀티바이트 코드이고

_ttoi는 멀티바이트+유니코드 모두 읽을 수 있는 중립코드이다. 

유니 코드는 _wtoi가 있다.

v.combo에서 쓰이는 모습을 찾아보자

iCurrentPenWidth = _ttoi(str); //Neutral Code
iCurrentPenWidth = atoi(str);//C-MBCS		
iCurrentPenWidth = _wtoi(str); //C-유니코드 

 

_ttoi를 사용하기 위해서는 라이브러리

#include <tchar.h>

tchar.h를 불러와야 한다.

_ttoi는 문자집합이 유니코드이면 _wtoi로 str을 변환하고 아니라면 atoi로 str을 변환한다.

이전에 C를 배울때는 C는 디폴트 문자집합이 MBCS라 atoi를 사용했지만 그 상태로 문자집합이 유니코드인 환경에서는 오류가 뜨기 때문에 어떤 문자집합에도 읽을 수 있는 Neutral Code를 사용하는 것이 좋다.

2주차에 만든 WM_CHAR에

	len=lstrlen(str);

 

 

 

lstrlen도 Neutral Code이다.

lstrlen의 정의

정의를 확인하면 UNICODE이면 lstrlenW로 읽고 else(MBCS)이면 lstrlenA로 읽는걸 확인 할 수 있다. 

 

② 대화상자

②-1. About

About Dialog

Dialog는 리소스에서 Dialog를 추가하고 도구상자에서 

도구를 선택해 Dialog에 바로 넣을 수 있다.

About Diolog에서 사용하는 도구는 "Button"과 "Static Text"이다. 

Static Text의 텍스트 값 바꾸기

리소스는 이 정도로 끝이다.

소스 코드

#include "resource.h"
BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	switch (iMessage) {
	case WM_INITDIALOG:
		return TRUE;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDOK:
			EndDialog(hDlg,IDOK);
			return TRUE;
		case IDCANCEL:
			EndDialog(hDlg,IDCANCEL);
			return TRUE;
		}
		break;
	}
	return FALSE;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	switch (iMessage) {
	case WM_LBUTTONDOWN:
		DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG1),hWnd,AboutDlgProc);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

Dlglog를 사용하고 싶으면 대화상자 프로시져를 생성 해줘야한다.

BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)

메인 윈도우와 똑같이 콜백함수로 선언하고 인자역시 같다.

하지만 리턴 값이 다르다 대화상자 프로시져는 BOOL형의 값을 리턴한다.

메시지를 제대로 처리했다면 TRUE를 리턴하고 그렇지 못하면 FALSE를 리턴한다. 

AboutDlgProc 내부

switch (iMessage) {
	case WM_INITDIALOG: // 1
		return TRUE;
	case WM_COMMAND: //2
		switch (LOWORD(wParam)) {
		case IDOK: //3
			EndDialog(hDlg,IDOK);
			return TRUE;
		case IDCANCEL: //4
			EndDialog(hDlg,IDCANCEL);
			return TRUE;
		}
		break;
    	return FALSE;

1. WM_INITDIALOG는 대화상자가 처음 만들어 질때 딱 한번만 실행되는 메인 윈도우의 WM_CREATE와 같은 이벤트

2. WM_COMMAND는 메인 윈도우와 똑같이 작동한다. 대화상자에서는 여기서는 대화상자가 부모 윈도우이고 버튼이 자식 윈도우이다.

3, 4. 확인, 취소를 눌렀을 때 return TRUE까지 실행 EndDialog 대화상자를 종료한다.

WndProc

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	switch (iMessage) {
	case WM_LBUTTONDOWN:
		DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG2),hWnd,AboutDlgProc);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

왼버튼 클릭시

-DialogBox(인스턴스 핸들, 열고싶은 대화상자ID, 대화상자를 띄울 윈도우, 대화상자가 있는 프로시져)

②-2. InfoDlg

InfoDlg는 대화상자에서 x y값을 입력하고 문자열을 입력하면

x y값 + 문자열 입력

문자열을 출력하는 프로그램이다.

x y위치에 문자열 출력

소스코드

#include "resource.h"
BOOL CALLBACK InfoDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	switch (iMessage) {
	case WM_INITDIALOG://대화 상자가 한번 떴을떄
		SetDlgItemText(hDlg,IDC_STR,str); //읽기
		SetDlgItemInt(hDlg,IDC_X,x,FALSE);
		SetDlgItemInt(hDlg,IDC_Y,y,FALSE);
		return TRUE;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDOK:
			GetDlgItemText(hDlg,IDC_STR, str,128); //쓰기
			x=GetDlgItemInt(hDlg,IDC_X,NULL,FALSE);
			y=GetDlgItemInt(hDlg,IDC_Y,NULL,FALSE);
			EndDialog(hDlg,IDOK);
			return TRUE;//ok누르면 ok리턴
		case IDCANCEL:
			EndDialog(hDlg,IDCANCEL);
			return TRUE;//clancel을 누르면 clancel을 리턴
		}
		break;
	}
	return FALSE;
}


LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	switch (iMessage) {
	case WM_CREATE:
		hWndMain=hWnd;
		x=100;
		y=100;
		lstrcpy(str,TEXT("String"));
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd, &ps);
		TextOut(hdc,x,y,str,lstrlen(str));
		EndPaint(hWnd, &ps);
		return 0;
	case WM_LBUTTONDOWN:
		if (DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG1),
			hWnd,InfoDlgProc)==IDOK) //
			InvalidateRect(hWnd, NULL, TRUE);//WM_PAINT로 IDD_DIALOG1 전역변수를 
            바꿔서 새로운 위치에 새로운 텍스트를 그림
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

InfoDlgProc

int x;
int y;
TCHAR str[128];

BOOL CALLBACK InfoDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	switch (iMessage) {
	case WM_INITDIALOG:// 1. 대화 상자가 한번 떴을떄 
		SetDlgItemText(hDlg,IDC_STR,str); //읽기
		SetDlgItemInt(hDlg,IDC_X,x,FALSE);
		SetDlgItemInt(hDlg,IDC_Y,y,FALSE);
		return TRUE;
	case WM_COMMAND: 
		switch (LOWORD(wParam)) {
		case IDOK: //2
			GetDlgItemText(hDlg,IDC_STR, str,128); //쓰기
			x=GetDlgItemInt(hDlg,IDC_X,NULL,FALSE);
			y=GetDlgItemInt(hDlg,IDC_Y,NULL,FALSE);
			EndDialog(hDlg,IDOK);
			return TRUE;//ok누르면 ok리턴
		case IDCANCEL:
			EndDialog(hDlg,IDCANCEL);
			return TRUE;//clancel을 누르면 clancel을 리턴
		}
		break;
	}
	return FALSE;
}

1. 대화 상자가 켜졌을 때 한번

  • SetDlgItemText은 문자열 전역변수 str에 있는 문자열을 IDC_STR에 쓴다.
  • SetDlgITemInt은 정수 전역변수 x에 값을 읽는다. 4번째 인수가 TRUE이면 무조건 부호가 있는 정수형 값을 읽고 FALSE일때는 무조건 양수로 읽는다.

2. IDOK 이벤트 발생

  • GetDlgItemText(hDlg,IDC_STR, str,128) IDC_STR의 텍스트 값을 str문자열에 넣는다.
  • x=GetDlgItemInt(hDlg,IDC_X,NULL,FALSE) x에 lDC의 값을 전달한다.

WndProc

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	switch (iMessage) {
	case WM_CREATE://1
		hWndMain=hWnd;
		x=100;
		y=100;
		lstrcpy(str,TEXT("String"));
		return 0;
	case WM_PAINT://2
		hdc=BeginPaint(hWnd, &ps);
		TextOut(hdc,x,y,str,lstrlen(str));
		EndPaint(hWnd, &ps);
		return 0;
	case WM_LBUTTONDOWN://3
		if (DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG1),
			hWnd,InfoDlgProc)==IDOK) //
			InvalidateRect(hWnd, NULL, TRUE);//WM_PAINT로 IDD_DIALOG1 전역변수를 
            바꿔서 새로운 위치에 새로운 텍스트를 그림
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

1. 윈도우 첫 생성시

  • 전역변수 x, y를 초기화
  • str문자열에 "String"복사해서 넣음

2. 윈도우 최소화시 

  • 문자열 str을 전역변수 x, y 위치에 그림

3. 왼쪽버튼클릭시

  • 대화상자를 열고 OK값이 리턴되면 WM_PAINT 이벤트를 발생시킨다.

②-3. 스크롤바 맛보기

MyScrollBar

소스코드

#define ID_SCRRED 100
#define ID_SCRGREEN 101
#define ID_SCRBLUE 102
HWND hRed,hGreen,hBlue;
int Red,Green,Blue;
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	HBRUSH MyBrush, OldBrush;
	int TempPos;
	switch (iMessage) {
	case WM_CREATE:
		hRed=CreateWindow(TEXT("scrollbar"),NULL,WS_CHILD | WS_VISIBLE | SBS_HORZ,
			10,10,400,20,hWnd,(HMENU)ID_SCRRED,g_hInst,NULL);
		hGreen=CreateWindow(TEXT("scrollbar"),NULL,WS_CHILD | WS_VISIBLE | SBS_HORZ,
			10,40,400,20,hWnd,(HMENU)ID_SCRGREEN,g_hInst,NULL);
		hBlue=CreateWindow(TEXT("scrollbar"),NULL,WS_CHILD | WS_VISIBLE | SBS_HORZ,
			10,70,400,20,hWnd,(HMENU)ID_SCRBLUE,g_hInst,NULL);
		SetScrollRange(hRed,SB_CTL,0,255,TRUE); //스크롤바의 범위 0~255까지
		SetScrollPos(hRed,SB_CTL,0,TRUE);
		SetScrollRange(hGreen,SB_CTL,0,255,TRUE);

		SetScrollPos(hGreen,SB_CTL,0,TRUE);
		SetScrollRange(hBlue,SB_CTL,0,255,TRUE);
		SetScrollPos(hBlue,SB_CTL,0,TRUE);
		return 0;
	case WM_HSCROLL:
		if ((HWND)lParam == hRed) TempPos = Red;//레드를 만졌다면 TempPos는 
		if ((HWND)lParam == hGreen) TempPos = Green;
		if ((HWND)lParam == hBlue) TempPos = Blue;
		switch (LOWORD(wParam)) {
		case SB_LINELEFT:
			TempPos=max(0,TempPos-1); //0보다는 크다 최소제어
			break;
		case SB_LINERIGHT:
			TempPos=min(255,TempPos+1);//최대제어
			break;
		case SB_PAGELEFT://스크롤의 오른쪽빈바
			TempPos=max(0,TempPos-10);
			break;
		case SB_PAGERIGHT:
			TempPos=min(255,TempPos+10);
			break;
		case SB_THUMBTRACK://끌었을때
			TempPos=HIWORD(wParam);
			break;
		}
		if ((HWND)lParam == hRed) Red=TempPos;
		if ((HWND)lParam == hGreen) Green=TempPos;
		if ((HWND)lParam == hBlue) Blue=TempPos;
		//SetScrollPos((HWND)lParam,SB_CTL,TempPos,TRUE);//스크롤 바의 위치 조정
		InvalidateRect(hWnd,NULL,FALSE);
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd,&ps);
		MyBrush=CreateSolidBrush(RGB(Red,Green,Blue));
		OldBrush=(HBRUSH)SelectObject(hdc,MyBrush);
		Rectangle(hdc,10,100,410,300);
		SelectObject(hdc,OldBrush);
		DeleteObject(MyBrush);
		EndPaint(hWnd,&ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

sadas간단하게 보고 다음시간에 자세하게 알아보자dasㄱ

 

전역변수

#define ID_SCRRED 100
#define ID_SCRGREEN 101
#define ID_SCRBLUE 102
HWND hRed,hGreen,hBlue;
int Red,Green,Blue;

1~3까지는 스크롤바의 ID값을 정의했다

다른 색을 가지는 윈도우 핸들 3가지

RGB색상의 숫자를 정의하는 정수

switch (iMessage) {
	case WM_CREATE:
		hRed=CreateWindow(TEXT("scrollbar"),NULL,WS_CHILD | WS_VISIBLE | SBS_HORZ,
			10,10,400,20,hWnd,(HMENU)ID_SCRRED,g_hInst,NULL);
		hGreen=CreateWindow(TEXT("scrollbar"),NULL,WS_CHILD | WS_VISIBLE | SBS_HORZ,
			10,40,400,20,hWnd,(HMENU)ID_SCRGREEN,g_hInst,NULL);
		hBlue=CreateWindow(TEXT("scrollbar"),NULL,WS_CHILD | WS_VISIBLE | SBS_HORZ,
			10,70,400,20,hWnd,(HMENU)ID_SCRBLUE,g_hInst,NULL);
		SetScrollRange(hRed,SB_CTL,0,255,TRUE); //스크롤바의 범위 0~255까지
		SetScrollPos(hRed,SB_CTL,0,TRUE);
		SetScrollRange(hGreen,SB_CTL,0,255,TRUE);
		SetScrollPos(hGreen,SB_CTL,0,TRUE);
		SetScrollRange(hBlue,SB_CTL,0,255,TRUE);
		SetScrollPos(hBlue,SB_CTL,0,TRUE);
  • hRed=CreateWindow(TEXT("scrollbar"),NULL,WS_CHILD | WS_VISIBLE | SBS_HORZ, 10,10,400,20,hWnd,(HMENU)ID_SCRRED,g_hInst,NULL); hRed핸들에 scrollbar클래스를 지정하고 , 스크롤바는 캡션이 필요없다 , 스타일 지정 , 위치 , 부모 윈도우 , ID , 인스턴스 핸들).
  • SetScrollRange(hRed,SB_CTL,0,255,TRUE); 스크롤바의 범위 0~255까지
    SetScrollPos(hRed,SB_CTL,0,TRUE); 스크롤의 초기 위치

WM_HSCROLL

case WM_HSCROLL:
		if ((HWND)lParam == hRed) TempPos = Red;//레드를 만졌다면 TempPos는 
		if ((HWND)lParam == hGreen) TempPos = Green;
		if ((HWND)lParam == hBlue) TempPos = Blue;
		switch (LOWORD(wParam)) {
		case SB_LINELEFT:
			TempPos=max(0,TempPos-1); //0보다는 크다 최소제어
			break;
		case SB_LINERIGHT:
			TempPos=min(255,TempPos+1);//최대제어
			break;
		case SB_PAGELEFT://스크롤의 오른쪽빈바
			TempPos=max(0,TempPos-10);
			break;
		case SB_PAGERIGHT:
			TempPos=min(255,TempPos+10);
			break;
		case SB_THUMBTRACK://끌었을때
			TempPos=HIWORD(wParam);
			break;
		}
		if ((HWND)lParam == hRed) Red=TempPos;
		if ((HWND)lParam == hGreen) Green=TempPos;
		if ((HWND)lParam == hBlue) Blue=TempPos;
		SetScrollPos((HWND)lParam,SB_CTL,TempPos,TRUE);//스크롤 바의 위치 조정
		InvalidateRect(hWnd,NULL,FALSE);
		return 0;

스크롤을 만졌을 때 발생하는 이벤트

 

 

반응형

+ Recent posts