관리 메뉴

Bull

[C언어] 콘솔창 현재 커서의 좌표 알아내기 본문

Computer Language/C

[C언어] 콘솔창 현재 커서의 좌표 알아내기

Bull_ 2022. 9. 8. 19:58

오목을 만들기 위해 마우스 좌표값을 얻어내어 그 위치에 바둑알을 두게 하고 싶어서 인터넷을 뒤져봤다.

자료도 거의 없고 비슷한 블로그에서 따온 게 많아 계속 헤맷다. 그 중 괜찮아 보이는 녀석(코드)를 정밀하게 관찰해 보았다. 나도 역시 다른 블로그에서 가져온 코드이다. 우선, 나는 이해력이 딸리니 설명할 수 있는 녀석의 코드는 자세히 설명해보겠다.

      * 필요 라이브러리 : #include <Windows.h>

#include <stdio.h>
#include <Windows.h>

typedef struct cursor {
	int x;
	int y;
}Cursor;

int main() {	
	Cursor cs;
	INPUT_RECORD rc;
	DWORD dw;
	COORD pos={ 0,0 };
	
	while (1) {
		SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
		// 콘솔 입력 버퍼의  출력모드 설정
		ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &rc, 1, &dw);
		// 콘솔 정보 읽어들임

		cs.x = rc.Event.MouseEvent.dwMousePosition.X;
		cs.y = rc.Event.MouseEvent.dwMousePosition.Y;
		// 마우스 위치 값

		FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), ' ', 100, pos, &dw);
		// 화면 지우기
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
		// 특정위치 (0,0)에 좌표이동
		printf("%d, %d\n",cs.x,cs.y );
	}
}

SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);

콘솔의 입력 버퍼의 입력 모드나 출력모드를 설정하겠다는 뜻이다.

BOOL WINAPI SetConsoleMode(
  _In_ HANDLE hConsoleHandle,
  _In_ DWORD  dwMode
);

정의로 가보았다. HANDLE과 DWORD를 가진 구조체가 인자로 필요해 보인다.
문서에 보면 인자들의 종류가 나와있다.

ENABLE_PROCESSED_INPUT : Ctrl + C를 칠 수 있게 하도록 해주는 녀석이다.

ENABLE_MOUSE_INPUT : 마우스의 위치만으로도 입력을 받게 된다.

그렇다면 위 두 녀석은 매크로함수인 거 같은데 왜 DWORD구조체가 인자로 들어가지 않고 매크로함수가 들어가는 것일까?

typedef unsigned long       DWORD;

정의를 봐도 모르겠어 인터넷에 쳐봤더니, WORD는 cpu가 한번에 처리할 수 있는 양을 말한다고 한다.

16비트 환경에선 WORD, 32비트 환경에선 DWORD를 사용한다고 한다.

뭔말인지 모르겠으니, 나는 숫자는 숫자인데 비트들의 경계를 구분지어주는 구조체라고 생각하겠다.

 

GetStdHandle은 Handle을 반환해준다. STD_INPUT_HANDLE은 아마 입력핸들을 도와주는 친구같다.

우리가 알아야 할 건 매크로 함수에 ~OUTPUT~이 아니라 INPUT이라는 단어를 넣어야한다는 것에 주의해야한다.


 

ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &rc, 1, &dw);

입력버퍼에 데이터를 읽고 버퍼의 내용을 삭제한다.

 

BOOL WINAPI ReadConsoleInput(
  _In_  HANDLE        hConsoleInput,
  _Out_ PINPUT_RECORD lpBuffer,
  _In_  DWORD         nLength,
  _Out_ LPDWORD       lpNumberOfEventsRead
);

HANDLE    GetStdHandle(STD_INPUT_HANDLE) : 컨트롤을 도와주는 녀석이다. 입력모드를 설정한다.

INPUT_RECORD    &rc : 버퍼에 있는 내용들을 구조체가 INPUT_RECORD인 친구한테 저장한다.
DWORD    1 : rc에 저장할 배열 크기이다. 우리는 입력받을 장치가 마우스 하나 뿐이니 1개면 된다.

(LP)DWORD    &dw : 버퍼에 입력된 수를 받는 변수에 대한 포인터이다. 왜 있는진 모르겠다.

 


FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), ' ', 100, pos, &dw);

화면을 지운다라고 되어 있지만, 공백을 채운다고 보면된다.

 

BOOL WINAPI FillConsoleOutputCharacter(
  _In_  HANDLE  hConsoleOutput,
  _In_  TCHAR   cCharacter,
  _In_  DWORD   nLength,
  _In_  COORD   dwWriteCoord,
  _Out_ LPDWORD lpNumberOfCharsWritten
);

TCHAR '  ' : 공백을 채우겠다는 뜻, 얼만큼?
DWORD  100 : 100만큼, 어디서 부터?
COORD pos : 부터. COORD는 구조체를 보면 x좌표와, y좌표를 나타낼 수 있는 구조체인데 통상 이벤트 발생 시 인자로 자주 사용하는 거 같다.


SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);

설명이 필요 없어보인다. 커서의 위치를 바꿔주는 코드이다.


참고로, 속성에 들어가 저 빨간 공간안에 옵션은 체크를 해제해주어야 한다.

 

 

나는 마우스 커서가 올려져 있어도 좌표가 나오는 게 아니라 클릭 시 좌표가 나타나도록 하려한다.....
하지만 덕분에 하나 알았기 때문에 글로 기록해봄.

+++

if (rc.EventType == MOUSE_EVENT) 
if (rc.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)

를 버퍼값을 rc에 입력 받은 후(ReadConsoleInput)에 넣어주면 끝!

 

 

참고 블로거 (여기는 SetConsoleMode함수 인자에 OUTPUT으로 돼있어서 처음에 안됐었음. 어쩌면 이 사람이 내게 준 과제가 아니었을까...?)

https://steemit.com/kr-dev/@codingman/c14--1558052700204

 

'Computer Language > C' 카테고리의 다른 글

정보과목용 C언어 정리  (0) 2023.09.28
C언어 연산자 우선순위 및 결합방향 표  (0) 2023.09.14