2012년 3월 26일 월요일

[WINAPI] 이미지 출력 함수 GdiTransparentBlt(), GdiAlphaBlend()

아래 두 함수는 비트맵의 일부를 투명하게 출력하는데 이용되는 함수들이다.



TransparentBlt()

AlphaBlend()



자세한 사용법에 대해서는 다른 블로그나 책에 많이 나와있으니 생략하고...

위 두 함수를 사용하려면 MsImg32.lib 라이브러리를 링크시켜 사용해야 한다.

그런데 WINAPI를 공부하면서 위 함수들에 대해서 찾다가 이런 것들을 발견했다.



GdiTransparentBlt()

GdiAlphaBlend()



보는 바와 같이 앞에 Gdi 가 붙은 형태이다.

이 함수들은  윈도우 2000 버전 이상의 Gdi32.lib 에 정의되어 있고 받는 인자나 사용법, 기능 등은 Gdi가 안붙은 버전과 완전히 동일하다.

다만 특별한 라이브러리 추가 없이 Windows.h를 인클루드 하면 그냥 사용가능하다는 것이 가장 큰 차이점이다.

단점은 윈도우 98 이하에서는 위 함수를 사용한 코드가 호환되지 않는다는 점이다.





또 다른 Gdi 형제로는 GdiGradientFill() 이라는 함수도 있다.

기존 FloodFill() 함수나 윈도우가 기본 제공하는 브러시, 펜 등을 이용해서는 단색 밖에 그릴 수가 없으므로 그라데이션으로 색을 칠할 수 있다고 하니 처음 함수 이름을 봤을때는 대박이라고 생각했다.

다만 자세히 들여다보니 아쉽게도 삼각형과 사각형 만을 지원한다고 하여 실망했던 기억이 있다.

몇개의 점 좌표와 각 점에 RGB 값을 인자로 주면 아래처럼 그라데이션 색으로 채워진 삼각형이나 사각형을 그려주는 방식이다.






개인적으로는 그다지 활용방법이 떠오르지 않아서 더이상 깊이는 조사해보지 않았다.

관심이 있다면 MSDN에서 검색해보자. (영어로) 자세히 설명되어 있다.




참고로 이 함수들을 한국어로 된 기존 책이나 블로그에서는 본 기억이 없다.

아마도 이 글이 최초 소개가 아닐까 싶다.


2012년 3월 21일 수요일

역시 언제나 인간관계가 가장 힘든것같다...

명확한 답도 없는것같고...


중요한건,

어느 정도 상황에 맞춰가는것도 있어야 하겠지만

이게 아니다 싶은 경우에는 자기 중심을 지켜야한다는것.

색깔있는 사람이 멋진거다...


그리고 단점이 아니라 장점에 주력하자...

내가 능력있고 성공하면

사실 이런 고민들도 저절로 해결될 문제일것이다......








2012년 3월 17일 토요일

[C++][WINAPI] GetKeyState()와 GetAsyncKeyState()의 차이점


예전에 인터넷에서 두 함수의 차이점을 검색해보았을때 잘못된 정보로 인해 혼란을 겪은 적이 있기 때문에 직접 정리해보기로 하였다.

일단 두 함수의 설명을 MSDN에서 찾아서 직접 번역해보았다.
이해하기 쉽도록 약간 의역 + 수정하였음을 밝혀둔다.


1.

SHORT GetKeyState( 
   int nVirtKey 
); 


이 함수는 특정 가상키의 상태를 찾아온다(retrieves). 키의 상태란 UP / DOWN / 토글 ON / OFF 상태를 말한다.

리턴값은,
키가 DOWN(눌린) 상태일때 최상위비트(high-order bit, 0x8000)가 1이고, UP이면 0이다.
토글 ON 이면 최하위비트(high-order bit, 0x0001)가 1이고, OFF이면 0이다.
(※ 참고로 GetKeyState는 Num Lock, Caps Lock 같은 토글키 이외에도 모든 키에 대하여 누를때마다 리턴값이 1과 0으로 토글된다.)

이 함수가 리턴하는 키의 상태는 특정 스레드가 그 메시지 큐로부터 키 메시지를 읽으면 변한다. 즉, 하드웨어 인터럽트 레벨에서의 키 상태를 반영하지는 못한다. 더 즉각적인 정보를 위해서는 GetAsyncKeyState 함수를 이용하는 것이 좋다.

응용프로그램은 키보드 입력 메시지에 대하여 GetKeyState를 호출한다. 이 함수는 입력 메시지가 생성되었을 때의 키의 상태를 반영한다.



2.

SHORT GetAsyncKeyState( 
  int vKey 
); 

이 함수는 함수 호출 시점에 특정키가 눌렸는지를 확인하며(determine) 바로 전의 호출과 이번 호출 사이에 키가 눌린 적이 있는지도 확인해준다.

키가 눌린 상태이면 최상위비트(most significant bit, 0x8000)가 셋(1)되고, 바로 전 호출 이후에 키가 눌린적이 있으면 최하위비트(least significant bit, 0x0001)가 셋된다.
GetAsyncKeyState()는 다른 스레드나 프로세스의 윈도우가 키보드 포커스를 가지고 있어도 값을 리턴해준다.




ps. 스타일러스 스크린이 눌렸을때 VK_LBUTTON 가상키로 감지할 수 있다.
ps2. GetAsyncKeyState가 검출하는 VK_LBUTTON 가상키 상태는 물리적인 마우스의 왼쪽 버튼 상태를 반영한다. 즉, 왼손잡이용으로 좌우 설정을 바꿔놨어도 상관없이 마우스 기계의 왼쪽 버튼 상태를 리턴한다. 참고로 GetSystemMetrics(SM_SWAPBUTTON) 연산을 사용하면 마우스 버튼이 스왑되어 있을 경우 참을 리턴한다.




GetKeyState()와 GetAsyncKeyState()는 아래 가상키를 처리할 수 있다.

VK_CONTROL   /// 좌우 상관없이 처리됨
VK_RCONTROL
VK_LCONTROL
VK_SHIFT
VK_LSHIFT
VK_RSHIFT
VK_MENU
VK_RMENU
VK_LMENU





3. 정리

GetKeyState()는 메시지 큐를 읽어서 리턴하고, GetAsyncKeyState()는 메시지 큐와 비동기적(asynchronized)으로, 즉 메시지 큐와 상관없이 기계입력에 즉각적으로 반응한다.
따라서 게임과 같은 즉각적인 키보드 반응이 필요한 경우 GetAsyncKeyState()가 더 좋다고 할 수 있다. GetKeyState()를 사용하면 만약에 메시지 큐에 메시지가 많이 밀렸을 경우 렉 현상이 생길 수 있기 때문이다.

사실 요즘은 하드웨어 성능이 워낙 빨라서 GetKeyState()를 써도 왠만해선 큰 차이가 느껴지지는 않는다. 그리고 토글키의 상태를 얻어오려면 어차피 반드시 GetKeyState()를 사용해야 한다.



ps. 다른 블로그에서 GetKeyState()는 윈도우 프로시저의 메시지큐 처리 루틴에서만 사용해야 한다는 글이 있었는데 이는 잘못된 정보이다. 영문 해석 과정에서의 실수로 보인다.

2012년 3월 14일 수요일

[C++] const 지정자


아래 두 표현의 차이는 무엇일까?




1.          const int* p;




2.          int* const p; 




스크롤을 내리기 전에 함께 생각해보자 :D












------------- 정답 -------------


1번은 const int 를 가리키는 포인터.
즉, 정수 변수의 값이 변하지 않는다는 뜻이다.

int            a = 5;
const int* p = &a;
*p = 10;           //// 값을 바꾸려 하므로 에러발생




2번은 정수를 가리키는 const 포인터 p이다.
즉, p가 가진 값(주소)가 변하지 않는다는 것을 보장한다.

int            a, b;
int* const p = &a;
p = &b;               //// 저장된 주소를 바꾸려 하므로 에러 발생





아예 둘 다 변하지 않도록 이렇게 써도 된다.

const int* const p;






내 생각에 const를 붙여주는 이유는, 물론 안정성을 높여주는 코딩 습관인 것도 있지만 코드의 가독성을 높이는 것도 큰 이유인 듯 하다.
코드를 읽을때 const가 붙어있으면 아, 이 함수는 이런 일을 하겠구나 라고 이해하기가 더 쉬워지는 것 같다.





※ 클래스에서의 const

예전 포스트에서도 언급했지만,

void ClassName:: FunctionName(void) const;

이처럼 멤버 함수의 선언부 마지막에 const가 붙은 함수를 const 함수라고 하는데,
이것은 컴파일러에게 멤버 변수의 값을 바꾸지 않겠다는 보장을 한 것이다.
예를 들어 어떤 함수에서 인자로 const형 변수를 받아왔을때 내부에서 const 함수 이외의 함수로 처리하려고 하면 에러가 발생한다.
예시는 이전 포스트 참고.

2012년 3월 1일 목요일

[C] 파일 입출력




일단 파일 쓰기 예제



#include <stdio.h>


int main(void)
{
///< 파일 포인터 선언 
FILE* fp = NULL;


int i = 1;
//char c = 'a';
float f = 3.14f;
char pTest[256] = "TEST";
__int64 longlongint = 12345678910;




///< 파일 쓰기 모드로 열기 
fp = fopen("현규바보.txt", "w");


///< 파일 포인터 확인 ( 제대로 열었는지 )
if( fp == NULL )
{
printf("파일 열기 실패\n");
return 0;
}


///< 데이터 쓰기 
fprintf(fp, "%d\t%f\t%s\t%I64d\n", i, f, pTest, longlongint);


///< 파일 포인터 닫기 
fclose(fp);


return 0;
}




fp라는 파일 포인터를 통해 프로그래머가 파일에 접근, 컨트롤하게 된다.

fopen() 에서 파일명만 적어주었는데(파일 이름은 신경쓰지 말자ㅡ,.ㅡ)
이 경우 상대경로로서 작업폴더를 기준으로 파일을 찾는다.
절대 경로를 적어줘도 된다.

그 다음 인자인 "w"는 쓰기 모드로 파일을 연다는 뜻이다.
모드는 아래와 같은 것들이 있다.


rt(또는 r+t)         텍스트 화일 읽기용
wt( " w+t) 쓰기
at( " a+t) 추가붙이기
rb( " r+b) 이진파일 읽기
wb( " w+b) 이진파일 쓰기
ab( " a+b) 이진파일 붙이기



그리고 __int64 자료형은 이름 그대로 64비트 짜리 정수형 타입이다. 기존 long int가 32비트(약 40억) 까지 담을 수 있었던 것에 비해 그보다 훨씬 큰 숫자도 담을 수 있다.
또한 fprintf() 로 쓸 때 이 자료형을 %I64d 로 받아주는 것을 볼 수 있다(대문자 I 이다).

char 형을 일단 주석으로 막아놓은 이유는, 입출력시 char 형을 따로 처리하면 탭문자, 공백문자, 개행문자 등도 하나의 문자로 인식하여 처리가 번잡해지기 때문이다.



결과물 텍스트 파일을 열어서 확인해보고 닫은 뒤

이제는 읽기코드를 실행해보자.





#include <stdio.h>


int main(void)
{
///< 파일 포인터 선언 
FILE* fp = NULL;


int i;
//char c;
float f;
char pTest[256];
__int64 longlongint;




///< 파일 쓰기 모드로 열기 
fp = fopen("현규바보.txt", "r");


///< 파일 포인터 확인 ( 제대로 열었는지 )
if( fp == NULL )
{
printf("파일 열기 실패\n");
return 0;
}


///< 데이터 읽기 
fscanf(fp, "%d%f%s%I64d", &i, &f, pTest, &longlongint);


        ///< 잘 읽었는지 확인
        printf("%I64d", longlongint);
///< 파일 포인터 닫기 
fclose(fp);


return 0;
}





몇가지 눈여겨 볼 점은,
일단 파일을 열 때 읽기 모드로 열었다는 것.
그리고 fscanf() 는 인자를 주소형식으로 받는다는 것..(필자는 C 코딩에 익숙하지 않아서 이런게 아직 신기하다..)
그리고 scanf()는 공백문자, 탭문자, 개행문자 등을 기준으로 자동으로 Tokening을 해준다는 것이다.





마지막으로 아래는 .cpp 파일을 자동으로 생성하는 코드이다.





  FILE* fp = NULL;


  fp = fopen("mainTestFile.cpp", "w");

  ///< 데이터 쓰기 
fprintf(fp, "#include <stdio.h>\n");
fprintf(fp, "int main(void)\n");
fprintf(fp, "{\n");
fprintf(fp, " printf(\"\%%d,1,2\\n\");\n");
fprintf(fp, "}\n");


  ///< 파일 포인터 닫기 
  fclose(fp);





여기서 눈여겨볼 점은 따옴표(")나 역슬레쉬(\) 같은 특수문자를 쓰기 위해서 앞에 역슬레쉬를 붙여줬다는 점.
그리고 % 문자는 특이하게 \%를 앞에 붙여줬다는 점이다.

생성된 cpp 파일을 열어 내용을 확인해 보면 아래와 같다.




#include <stdio.h>
int main(void)
{
printf("%d,1,2\n");
}