윈도우 32비트 프로그래밍 21 |
안녕하세요.....돌팔이 황동준입니다.... 이번에는 여러분들이 관심을 가질만한 비트맵 여러분들한테 묻고자 하는 것은 제가 하는 강좌가 실제로 도움이 되는지 제가 궁금하다는 여기까지 쓸데없는 얘기였습니다. 그러면 본격적으로 강좌를 시작해 보겠습니다. 윈도우즈에서 비트맵 그림을 출력하는 방법은 생각 외로 간단합니다. 그런데 이 루틴을 가지고 이런 단점을 보완해서 나온 것이 WinG라고 하는 그래픽 출력 라이브러리인데 그나마 속력이 자 그러면 먼저 일반적인 출력 방법부터 알아 봅시다. 일반적으로 비트맵을 다루기 위해서는 여기까지 이해가 된다면 이제 추가된 새로운 방법을 알아 봅시다. 먼저 비트맵 그림을 출력하기 HDC CreateCompatibleDC(HDC hDC); 위 함수를 이용해서 메모리에 디바이스 컨텍스트 핸들을 생성할 수 있습니다. 파라미터로 현재 BOOL DeleteDC(HDC hDC); 위 함수를 이용해서 해제해주면 됩니다. 파라미터로 메모리 디바이스 컨텍스트 핸들을 지정해 자 이번에는 비트맵 그림의 크기를 얻는 방법을 알아 봅시다. 우리가 출력할 비트맵 그림이야 int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID 위 함수를 이용해서 비트맵 그림에 대한 정보를 얻을 수 있습니다. 첫번째 파라미터로 비트맵 아래는 BITMAP 구조체의 원형입니다. typedef struct tagBITMAP { 위 구조체의 맴버중 bmWidth, bmHeight에 그 크기의 정보가 저장됩니다. BOOL BitBlt(HDC hdcDest, int nXDest, int nYDest, 위 함수를 이용해서 메모리에 있는 그림을 현 디바이스 컨텍스트 핸들로 복사할 수 있습니다. 첫번째 파라미터가 출력할 현 디바이스 컨텍스트 핸들을 의미하는 것입니다. 두번째 파라미터와 그러면 일곱번째와 여덟번째 파라미터는 뭘 의미할까요? 바로 메모리 디바이스 컨텍스트 핸들의 SRCCOPY 메모리의 내용을 그대로 복사한다. 자 그러면 대략적으로 어떤 식으로 되는지 알아 보았으니 실제로 이것을 이용한 예제를 봅시다. 먼저 리소스 파일입니다. #include <windows.h> MyBitmap BITMAP "test.bmp" 프로그램 소스입니다. #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, int WINAPI WinMain WndClass.style = hWnd = hBitmap = LoadBitmap(hInstance, ShowWindow(hWnd, while(GetMessage(&msg, NULL, 0, return msg.wParam; LRESULT CALLBACK switch(message) hDC = BeginPaint(hWnd, case WM_DESTROY : PostQuitMessage(0); 먼저 리소스 파일을 보면 알겠지만 비트맵 파일을 정의하죠? hBitmap = LoadBitmap(hInstance, "MyBitmap"); 정의한 비트맵 그림을 로드하는 함수입니다. 이미 설명을 드렸을 겁니다. 자 그러면 실제로 case WM_PAINT : hDC = BeginPaint(hWnd, &ps); 메모리에 디바이스 컨텍스트 핸들을 얻는 과정입니다. SelectObject(hMemDC, hBitmap); 메모리 디바이스 컨텍스트 핸들로 앞에서 로드한 비트맵 핸들을 취하는 과정입니다. GetObject(hBitmap, sizeof(BITMAP), (BITMAP 비트맵 핸들을 이용해서 비트맵에 관한 정보를 BITMAP 구조체에 넣는 과정입니다. nX = bitmap.bmWidth; 비트맵의 크기를 선언한 변수에 저장하고 있습니다. 이게 왜 필요한지는 아래 함수 BitBlt(hDC, 0, 0, nX, nY, hMemDC, 0, 0, 메모리 디바이스 컨텍스트 핸들을 이용해서 메모리에 출력했던 것을 현 디바이스 DeleteDC(hMemDC); 메모리 디바이스 컨텍스트 핸들을 이용한후에는 반드시 해제 해 주어야 한다고 했 EndPaint(hWnd, &ps); 자 이번에는 그래픽 출력을 빨리 해 준다는 WinG를 이용한 비트맵 그림의 출력에 대해 알아 HDC WINGAPI WinGCreateDC( void ); 위 함수를 이용해서 디바이스 컨텍스트 핸들을 생성하면 됩니다. 파라미터를 요구하지 BOOL WINGAPI WinGBitBlt( HDC hdcDest, int 위 함수를 이용해서 실제 화면에 복사하면 됩니다. 앞에서 알아본 BitBlt()함수와 간단하죠? 그러면 소스를 보도록 합시다. 아래는 리소스 파일입니다. #include <windows.h> MyBitmap BITMAP "test.bmp" 프로그램 소스입니다. #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, int WINAPI WinMain WndClass.style = hWnd = hBitmap = LoadBitmap(hInstance, ShowWindow(hWnd, while(GetMessage(&msg, NULL, 0, return msg.wParam; LRESULT CALLBACK switch(message) hDC = BeginPaint(hWnd, case WM_DESTROY : PostQuitMessage(0); 뭐 특별한 부분은 없죠? #include "wing.h" 헤더 파일에 WinG 라이브러리를 사용하기 위한 헤더 파일을 선언했습니다. case WM_PAINT : hDC = BeginPaint(hWnd, &ps); 실제로 출력하는 부분인데 정말 간단하죠? 이 프로그램을 컴파일 할려면 wing32.lib 오늘은 여기까지 |
윈도우 32비트 프로그래밍 22 |
안녕하세요........돌팔이 황동준입니다..... 이번시간에도 역시 비트맵 그림을 출력하는 예제를 볼건데 이것은 그림의 크기에 관계없이 역시 같은 방법으로 API 함수를 이용해서 하는 방법과 WinG 그래픽 라이브러리를 이용해서 보면 알겠지만 앞에서 그림출력하는 과정을 잘 이해하셨다면 이번 부분은 특별하게 새로 배울 그러면 먼저 API 함수를 이용해서 해보도록 합시다. 작업영역의 크기만큼의 그림으로 BOOL StretchBlt(HDC hdcDest, int nXDest, int 위 함수를 이용해서 축소하거나 확대할 수 있는데 네번째, 다섯번째 파라미터에 유저가 값을 자 그러면 예제를 보도록 합시다. 아래는 리소스 파일의 소스입니다. #include <windows.h> MyBitmap BITMAP "test.bmp" 프로그램 소스입니다. #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, int WINAPI WinMain WndClass.style = hWnd = hBitmap = LoadBitmap(hInstance, ShowWindow(hWnd, while(GetMessage(&msg, NULL, 0, return msg.wParam; LRESULT CALLBACK switch(message) hDC = BeginPaint(hWnd, case WM_DESTROY : PostQuitMessage(0); 머리가 좋으신분은 이미 다 이해했을 겁니다. 너무 쉽죠. case WM_PAINT : hDC = BeginPaint(hWnd, &ps); 작업 영역의 크기를 얻은뒤 그 크기만큼 그림을 화면에 출력하는 과정입니다. DeleteDC(hMemDC); 별로 설명 드릴부분은 없군요. 이번에는 WinG 그래픽 라이브러리를 이용해서 똑같은 기능을 BOOL WINGAPI WinGStretchBlt( HDC hdcDest, int 파라미터의 의미는 StretchBlt() 함수와 같습니다. 단지 마지막 파라미터에 있던 것이 #include <windows.h> MyBitmap BITMAP "test.bmp" #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, int WINAPI WinMain WndClass.style = hWnd = hBitmap = LoadBitmap(hInstance, ShowWindow(hWnd, while(GetMessage(&msg, NULL, 0, return msg.wParam; LRESULT CALLBACK switch(message) hDC = BeginPaint(hWnd, case WM_DESTROY : PostQuitMessage(0); 간단하죠? case WM_PAINT : hDC = BeginPaint(hWnd, &ps); 작업영역의 크기를 알아 낸뒤 그 크기만큼 그림을 출력하는 과정입니다. DeleteDC(hMemDC); 오늘는 여기까지 ps> 다음 시간에는 DIB에 대해서 알아 보겠습니다. 아마 이제껏 배운 것중 가장 |
윈도우 32비트 프로그래밍 23 |
안녕하세요.......돌팔이 황동준입니다............... 이번 시간에는 DIB에 대해서 알아 보겠습니다. 이번 강좌는 조금 어려울 겁니다. 이번 강좌를 통해서 여러분들은 부수적으로 파일 입출력과 자 그러면 먼저 DIB가 무엇인지 알아 봅시다. 윈도우즈에서 사용하는 비트맵 그림은 크게 두가지로 나눌 수 있습니다. 바로 장치 독립적인 예를 들어 그림을 그린 후에 256컬러로 저장했다면 그 그림은 장치 독립적인 그림이 됩니다. 우리는 비트맵 그림을 출력하기 위해서 리소스 파일을 이용했을 겁니다. 리소스 라는 것은 이 리소스 파일을 이용해서 그림 파일을 출력하게 되면 장치 독립적인 비트맵 그림이 장치 자 그러면 앞에서 배운 비트맵 그림 출력 결과를 생각해 봅시다. 그림은 256컬러인데 출력된 장치 의존적인 비트맵 그림은 윈도우즈의 컬러수에 의존하게 됩니다. 즉 윈도우즈의 색깔을 자 그러면 이제부터 장치 독립적인 비트맵 컬러를 그대로 출력해 봅시다. 그러면 아마 앞에서 먼저 전체적으로 어떻게 돌아가는지 알아 봅시다. 우선 비트맵 파일의 구조를 알아 봅시다. 1)파일헤더 비트맵 파일 하나가 위와 같이 구성되어 있다고 이해하면 됩니다. 그리고 2번부터 4번을 한번 하나씩 알아봅시다. 아마 다른 윈도우즈 프로그래밍 책에서 이 DIB 부분을 보고 쉽게 먼저 비트맵 그림파일을 열어야 겠죠? 드디어 파일 입출력 부분이 나오는군요. 파일을 열기 HFILE _lopen( 첫번째 파라미터로 열 파일이름을 지정하고 두번째 파라미터에는 지정된 예약어를 지정하면 OF_READ 읽기 전용을 연다 파일 여는데 실패하면 -1을 리턴합니다. 파일을 성공적으로 열었으면 읽어야 할 겁니다. 먼저 UINT _lread( _lopen()함수를 이용해서 얻은 파일 핸들을 첫번째 파라미터로 지정하면 됩니다. 두번째 파일 헤더 부분을 뽑아 내기 위한 구조체의 원형은 다음과 같습니다. typedef struct tagBITMAPFILEHEADER 여기서 다른 멤버는 알 필요없고 단지 첫번째 멤버인 bfType과 두번째 멤버인 이 구조체를 이용해서 이 크기만큼의 자료를 뽑아내면 이 구조체에 비트맵 파일에 대한 기본적인 파일헤더를 읽어 왔을 때 우리는 bfType이라는 멤버를 이용해서 이 파일이 비트맵 파일인지 먼저 BITMAPINFO라는 구조체로 선언한 변수에 기억시켜 놓아야 하고 아래는 이 두 구조체의 원형입니다. typedef struct tagBITMAPINFO 두번째 맴버인 RGBQUAD란 자료형은 팔레트 데이처를 의미하는 것입니다. 아래는 이 typedef struct _RGBQUAD { 멤버 이름만 봐도 어떤 의미를 가지는지 쉽게 짐작할 수 있죠? typedef struct tagBITMAPINFOHEADER{ 무지하게 복잡하죠? 몇개의 의미만 알면 됩니다. 첫번째 멤버인 biSize는 그림정보 헤더의 자 다시 생각해 봅시다. 비트맵 정보부분 전체를 읽은 후에 그 시작주소를 팔레트를 생성할 때에는 아래 함수를 이용해서 할 수 있습니다. HPALETTE CreatePalette( 파라미터는 가상 팔레트 구조체를 의미합니다. 물론 조작이 다 끝난 가상 팔레트죠. 위 함수를 이용해서 팔레트 핸들을 얻으면 이것을 실제로 디바이스 컨텍스트 핸들로 선택해 HPALETTE SelectPalette( 첫번째, 두번쩨 파라미터가 뭔지는 짐작이 가죠? 세번째 파라미터에는 보통 FALSE 를 이제 진짜로 사용하겠다는 것을 알려주면 됩니다. UINT RealizePalette( 위 함수를 사용하면 됩니다. int StretchDIBits( 위 함수를 이용해서 화면에 복사할 수 있습니다. 두번째, 세번째 파라미터는 화면에 출력될 그러면 이것을 구현한 실제 소스를 보도록 합시다. #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, int WINAPI WinMain WndClass.style = hWnd = ShowWindow(hWnd, while(GetMessage(&msg, NULL, 0, return msg.wParam; LRESULT CALLBACK switch(message) hDC = BeginPaint(hWnd, case WM_DESTROY : PostQuitMessage(0); BOOL PrintDIBFormat(HDC hDC, char static int n; if(-1 != (hFile = _lopen(szBitmapFile, nColorNumber = if(BitmapInfoHeader->biSizeImage == ldPalette = SelectPalette(hDC, hPalette, 자 오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~~ 다음시간에는 위 소스를 분석해 보도록 하겠습니다. 그전까지 각자 분석해 보시기 바랍니다. |
윈도우 32비트 프로그래밍 24 |
안녕하세요...........돌팔이 황동준입니다........ 이번시간에는 저번시간에 알아 본 프로그램을 분석해 보겠습니다. 이 프로그램은 리소스를 이용해서 비트맵 그림을 출력하는 것이 아니기 때문에 리소스 파일에서 그러면 먼저 윈도우가 처음생성될 때 그리는 부분인 WM_PAINT 메시지 처리 부분을 보도록 case WM_PAINT : hDC = BeginPaint(hWnd, 못보던 함수가 하나 있군요. 이것은 장치 독립적인 비트맵 그림을 출력하기 위해서 필자가 BOOL PrintDIBFormat(HDC hDC, char 파일을 다루기 위해서 파일 핸들을 선언해준 것입니다. HPALETTE hPalette, hOldPalette; 파레트를 조작하고 다시 원래 팔레트로 돌아가기 위해서 위 변수를 선언했습니다. BITMAPFILEHEADER 위 4개의 구조체에 대한 것은 이미 앞에서 설명을 드렸습니다. char *szBits, *Dib; 우리가 앞에서 알아본 CreatePalette()함수의 파라미터에 LOGPALETTE라는 static int n; if(-1 != (hFile = _lopen(szBitmapFile, 비트맵 파일을 열어서 파일 헤더 부분을 읽는 구문입니다. if(BitmapFileHeader.bfType != 이 파일이 비트맵 파일인지 조사하는 구문입니다. else 이 안의 루틴은 이 파일이 비트맵 파일일 때 수행되는 부분이겠죠? nRealSize = 파일 전체 크기에서 파일헤더 부분을 빼서 파일 헤더 부분을 제외한 크기를 얻고 있는 Dib = (char *)GlobalAllocPtr(GMEM_MOVEABLE, 위에서 얻은 크기만큼 메모리를 할당하는 구문입니다. 우리가 도스에서 메모리를 할당한 _lread(hFile, Dib, 파일헤더 부분을 제외한 나머지 부분을 읽어 그 시작주소를 Dib에 저장하고 있습니다. 그리고 BitmapInfo = (BITMAPINFO 앞에서 이 시작주소를 두가지 변수에 기억 시켜 놓아야 한다고 했을 겁니다. RgbQuad = (RGBQUAD 나머지 부분 즉 비트맵 정보의 시작 주소가 Dib인데 이 부분에서 포인터를 그림정보 헤더 if((BitmapInfoHeader->biClrUsed == 0) 우리가 출력할 그림의 컬러수를 구하는 구문인데 쉬프트 연산이 있군요. 이것의 의미는 만약에 if(BitmapInfoHeader->biSizeImage == 그림의 크기가 0으로 되어 있으면 그림의 가로 크기와 세로 크기를 곱해서 크기를 구하는 dwTableSize = 하나의 컬러는 하나의 팔레트 정보를 갖고 있으므로 이 전체 크기를 알기 위해서는 컬러수와 이 szBits = 자 위와 같은 포인터 연산의 결과로 szBis는 어떤 정보의 주소를 가지게 됩니까? 바로 LOGICALPALETTE.version = 현재 팔레트 데이터의 정보를 가상 팔레트에 저장하는 구문입니다. hPalette = 가상 팔레트를 이용해서 팔레트를 생성하고 있습니다. hOldPalette = SelectPalette(hDC, hPalette, 팔레트를 선택하고 실제로 사용하겠다는 것을 알려 주고 있습니다. StretchDIBits(hDC, 0, 0, 화면에 출력하고 있습니다. 이 함수는 위에서 설명드렸을 겁니다. SelectPalette(hDC, hOldPalette, FALSE); 출력이 끝난후에 원래 팔레트로 다시 맞춰주고 있습니다. DeleteObject(hPalette); 사용한 팔레트 핸들을 반환하고 할당한 메모리를 해제하는 구문입니다. } 어때요? 이제껏 알아본 것 중에 그래도 가장 복잡한 구조를 띄죠? 잘 이해가 되지 않으면 |
윈도우 32비트 프로그래밍 25 |
안녕하세요....돌팔이 황동준입니다.......... 이번 시간부터는 멀티미디어에 대해 알아 보도록 하겠습니다. 아마 여러분들도 상당히 흥미있는 윈도우즈 프로그래밍에서는 보기보다 간단하게 이것을 구현할 수 있습니다. 자 그러면 간단하게 먼저 함수 하나를 알아 보죠. 이 함수 하나로 간단하게 wav파일을 들을수 있습니다. BOOL sndPlaySound( 첫번째 파라미터는 wav파일을 지정해 주면 되고 두번째 파라미터는 디음과 같은 예약어를 SND_SYNC 비동기적으로 플레이 해줍니다. 아주 간단하죠? 위 함수 하나만 이용해서 쉽게 구현이 되는 것입니다. 그러면 실제로 구현한 #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, int WINAPI WinMain WndClass.style = hWnd = ShowWindow(hWnd, while(GetMessage(&msg, NULL, 0, return msg.wParam; LRESULT CALLBACK switch(message) if(LOWORD(wParam) == case WM_DESTROY : PostQuitMessage(0); 자 그러면 프로그램 소스를 자세히 보도록 합시다. 먼저 헤더 파일을 보게되면 못보던 것이 #include <mmsystem.h> 바로 위와 같이 선언되어 있는데 이 헤더 파일은 멀티미디어를 구현하기 위한 함수들이 정의되어 Enter키가 눌릴 때마다 플레이되고 플레이되지 않는다고 했으니 그 부분을 보도록 case WM_KEYDOWN : if(LOWORD(wParam) == VK_RETURN) Enter키가 눌렸는지 확인하는 구문이죠? Enter키의 토글을 체크하기 위해서 아래 { 계속해서 wav파일을 연주하는 구문이 되겠네요. 만약에 위 두번째 파라미터 대신에 else 첫번째 파라미터를 NULL로 지정하고 두번째 파라미터를 0으로 지정하면 연주가 bCheck = !bCheck; 이 프로그램을 컴파일하려면 lib디랙토리내에 있는 winmm.lib 파일을 프로젝트 파일에 자 이번에는 다른 방법을 사용해서 구현해 봅시다. 이 방법으로 구현하면 플레이도중에 이 방법을 알아 보기 위해서는 먼저 MCI 디바이스에 대해 알아야 합니다. MCI라는 것은 [mci] 필자같은 경우에는 위와 같이 되어 있군요. 어떤 문자열이 특수한 디바이스 파일로정의 되어 이제 부터 우리가 알아볼 함수로 장치 이름을 지정하여 그 핸들(아이디)을 얻어 각종 파일들을 자 그러면 구체적으로 어떤 함수를 이용해서 이러한 것들을 구현할수 있는지 알아봅시다. 우리가 MCIERROR mciSendCommand( 앞으로 우리는 이 함수를 많이 사용할 것입니다. 위 함수의 두번째 파라미터에 어떤 예약어를 먼저 첫번째 파라미터에는 MCI 장치의 아이디를 지정하면 되는데 만약에 처음에 여 두번째 파라미터에 지정해주는 예약어에 따라 어떤 작업을 할 것인지 구분된다고 했는데 이 MCI_OPEN MCI 장치를 엽니다. 세번째 파라미터는 두번째 파라미터에 어떤 것이 지정되느냐에 따라 그 의미가 달라지므로 이 다시 원래대로 돌아와서 MCI 장치를 어떻게 여는지 봅시다. MCI 장치를 열 때 위 함수의 첫번째 파라미터는 NULL을 지정하면 됩니다. 그리고 두번째 자 위의 설명을 잘 생각해 봅시다. 마지막 파라미터에 오는 구조체에 지정된 정보를 typedef struct { 바로 위 구조체가 오게됩니다. 위 구조체 변수를 선언한 다음 파라미터중 MCI 장치를 여는 방법을 알았으니 닫는 방법도 알아 봅시다. MCI장치를 닫을 때에는 typedef struct { 자 이번에는 플레이하는 방법을 알아 봅시다. 역시 이것도 mciSendCommand() typedef struct { 그러면 플레이되고 있는 것을 잠시 중단하려면 어떻게 할까요. 더 간단합니다. mciSendCommand() 함수의 첫번째 파라미터에 장치 아이디를 지정하고 두번째 다시 플레이하려면 두번째 파라미터에 MCI_RESUME를 지정해서 사용하면 됩니다. 아예 다 그러면 실제로 이러한 함수를 가지고 구현한 프로그램을 보도록 합시다. 아차! 한가지 먼저 첫번째 파라미터에 장치의 아이디를 지정하고 두번째 파라미터에 그리고 마지막 파라미터에 아래와 같은 구조체 변수의 주소를 지정하면 되는데 특별한 곳으로 typedef struct { 오늘은 여기까지 |