본문 바로가기
코스웨어/15년 스마트컨트롤러

2015.11.20_개인업무일지_[Win32API #7]_이량경_윈도우 비트맵 뷰어

by 알 수 없는 사용자 2015. 11. 22.
728x90
반응형
<Win32API>✔ 
================================================================
✔ createfile
- 윈32에서는 파일을 호출할때, 파일을 만들때, 열때도 사용한다
- 저수준으로 open와 동급이다.

✔ ReadFile
- 저수준  read와 동급이다. 
- 윈도우 전용함수다.

✔ closeHandle
- 닫기

<윈도우 비트맵처리>

- 도스에서 만든 비트맵을 옮길것이다. 저장안하고, 비트맵함수 보여주는 프로그램을 만든다.



1. 에러 처리
----------------------------------------------------------------------
#include <windows.h>

LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM );
HINSTANCE g_hInst;
LPSTR lpszClass = TEXT ("smart" );

typedef struct _msgmap
{
        UINT uiMsg;
        LRESULT(*fp)( HWND, WPARAM, LPARAM);
} stMsgMap;


LRESULT OnPaint(HWND , WPARAM , LPARAM );
LRESULT OnCreate(HWND , WPARAM , LPARAM );
LRESULT OnDestroy(HWND , WPARAM , LPARAM );
LRESULT OnKeydown(HWND , WPARAM , LPARAM );

/*** MsgMap ***/
stMsgMap MsgMap[] =
{
       { WM_PAINT, OnPaint },
       { WM_CREATE, OnCreate },
       { WM_DESTROY, OnDestroy },

       { WM_NULL, 0 }
};


int APIENTRY WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance
       , LPSTR lpszCmdParam, int nCmdShow )
{
        HWND hWnd;
        MSG Message;
        WNDCLASS WndClass;
       g_hInst = hInstance;

       WndClass.cbClsExtra = 0;
       WndClass.cbWndExtra = 0;
       WndClass.hbrBackground = ( HBRUSH)GetStockObject( WHITE_BRUSH);
       WndClass.hCursor = LoadCursor(NULL , IDC_ARROW );
       WndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION);
       WndClass.hInstance = hInstance;
       WndClass.lpfnWndProc = ( WNDPROC)WndProc;
       WndClass.lpszClassName = lpszClass;
       WndClass.lpszMenuName = NULL;
       WndClass.style = CS_HREDRAW | CS_VREDRAW ;
        RegisterClass(&WndClass);

       hWnd = CreateWindow(
              lpszClass,
              lpszClass,
               WS_OVERLAPPEDWINDOW,
              500,   
              100,
              400,
              400,
               NULL, ( HMENU) NULL, hInstance, NULL);
       ShowWindow(hWnd, nCmdShow);

        while ( GetMessage(&Message, 0, 0, 0)) {
              TranslateMessage(&Message);
               DispatchMessage(&Message);
       }
        return Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd , UINT iMessage , WPARAM wParam , LPARAM lParam )
{
        HDC hdc;
        PAINTSTRUCT ps;

        stMsgMap *stpMap = MsgMap;

        while ( WM_NULL != ((*stpMap).uiMsg))
       {
               if ( iMessage == ((*stpMap).uiMsg)) //dest가 들어오면
              {
                      return (((*stpMap).fp)( hWnd, wParam, lParam));
              }
              ++stpMap;
       }

        return( DefWindowProc(hWnd , iMessage , wParam , lParam ));
}
LRESULT OnDestroy(HWND hWnd , WPARAM wParam , LPARAM lParam )
{
       
       PostQuitMessage(0);
        return 0;
}
LRESULT OnCreate(HWND hWnd , WPARAM wParam , LPARAM lParam )
{
        HDC hdc;
        PAINTSTRUCT ps;
       hdc = GetDC( hWnd);

        HANDLE hFile;
       hFile = CreateFile(TEXT ("1.bmp" ),
               GENERIC_READ,
              0, NULL,
               OPEN_EXISTING,
               FILE_ATTRIBUTE_NORMAL,
               NULL );

        if ( INVALID_HANDLE_VALUE == hFile)
       {
               MessageBox(hWnd , TEXT ("파일을 열수 없습니다." ), TEXT ("밝명 ㄴㄴ" ), MB_OK);
               return 0;
       }
        else
       {
              CloseHandle(hFile);
               MessageBox(hWnd , TEXT ("파일이 성공적으로 열렸다." ), TEXT ("밝명 ㅇㅋ" ), MB_OK );
       }


       ReleaseDC( hWnd, hdc);
        return 0;
}
LRESULT OnPaint(HWND hWnd , WPARAM wParam , LPARAM lParam )
{
        HDC hdc;
        PAINTSTRUCT ps;

       hdc = BeginPaint( hWnd, &ps);

       EndPaint( hWnd, &ps);
        return 0;
}


----------------------------------------------------------------------

✔ read :
- 동적할당부터 받아야 한다,

- 파일을 못연다 = 아무것도 안했다.
- DESTROY에서 동적할당받으면 제거를 해야한다.
- 파일을 열기만 했는데 동적할당받으면 제거를 해야 하므로. DESTROY는 거치면 안된다.

- 윈도우가 만든 윈도우기 때문에 WM_PAINT가 들어있다. 여긴 윈도우다. 알아서 다 그린다.

- 윈도우 안에 그린다. 우리의 그림과 개념자체가 다르다.우리는 그림을그리면 계속 다시그리는데 
윈도우는 알아서그린다.
- 다이얼로그 박스, 버튼 텍스트 모두 윈도우다.

7-1-가. 컨트롤의 정의


- 제목: static (좌) / 컨트롤 : 에디트

좌) 사용하는 사람이 직접 수정 안된다.

우)에디트: 사람이 수정이 된다.

에디트 컨트롤 사용법 숙지



7-3-가. 에디트

* 에디트는 문자열을 직접 입력받고자 할 때 사용하는데 버튼과 마찬가지로 윈도우즈에서 가장 흔하게 볼 수 있는 컨트롤이다

"edit" 윈도우 클래스를 사용하며 생성시에 다음과 같은 스타일을 사용할 수 있다. 물론 이 스타일들은 CreateWindow 함수의 세번째 인수로 지정한다


스타일설명
ES_AUTOHSCROLL수평 스크롤을 지원한다.
ES_AUTOVSCROLL여러줄 편집시 수직 스크롤을 지원한다.
ES_LEFT왼쪽 정렬한다.
ES_CENTER중앙 정렬한다.
ES_RIGHT오른쪽 정렬한다.
ES_LOWERCASE소문자로 변환하여 표시한다.
ES_UPPERCASE대문자로 변환하여 표시한다.
ES_MULTILINE여러줄을 편집할 수 있도록 한다.
ES_NOHIDESEL포커스를 잃더라도 선택된 영역을 표시한다.
ES_READONLY읽기전용으로 만들어 편집을 금지한다.


- 자신의 변화에 대해 다음과 같은 통지 메시지를 부모 윈도우로 보내준다. 부모 윈도우는 이 메시지를 받았을 때 적절한 처리를 해 주면 된다.

메시지설명
EN_CHANGE문자열이 변경되었다.
EN_ERRSPACE메모리가 부족하다.
EN_HSCROLL사용자가 수평 스크롤 바를 클릭하였다.
EN_VSCROLL사용자가 수직 스크롤 바를 클릭하였다.
EN_KILLFOCUS포커스를 잃었다.
EN_SETFOCUS포커스를 얻었다.
EN_MAXTEXT지정한 문자열 길이를 초과하였다.
EN_UPDATE문자열이 변경되기 직전이다.

- EN_UPDATE는 문자열이 변경된 후 화면에 출력하기 전에 보내주는 메시지이며 이 메시지가 발생했을 때 사용자는 문자열 길이에 따라 에디트의 폭을 늘리거나 별도의 조치를 취할 수 있다.

- EN_CHANGE는 문자열이 화면으로 출력되고 난 후 보내지는 메시지이다. 
-  에디트는 문자열이 변경된 후 EN_UPDATE 메시지를 보내고 화면에 그린 후 다시 EN_CHANGE 메시지를 보낸다.
----------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd , UINT iMessage , WPARAM wParam , LPARAM lParam )
{
        switch ( iMessage)
       {
        case WM_CREATE:
              hEdit = CreateWindow(TEXT ("edit" ), NULL 
                    , WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
                    , 10, 10, 200, 25
                    , hWnd , (HMENU )ID_EDIT , g_hInst, NULL);
               return 0;

        case WM_COMMAND:
               switch ( LOWORD( wParam))
              {
               case ID_EDIT:
                      switch ( HIWORD( wParam))
                     {
                      case EN_CHANGE:
                            GetWindowText(hEdit, str, 128);
                            SetWindowText(hWnd , str);
                     }
              }
               return 0;

        case WM_DESTROY:
              PostQuitMessage(0);
               return 0;
       }
        return ( DefWindowProc(hWnd , iMessage , wParam , lParam ));
}

생성된 에디트 컨트롤의 윈도우 핸들값을 hEdit에 저장해 두었다. WM_COMMAND에서 EN_CHANGE 통지 메시지가 전달될 때 에디트의 텍스트를 읽어 메인 윈도우의 타이틀바로 출력하였다.


----------------------------------------------------------------------

7-1-나. Button

7-5-나. 스태틱

----------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd , UINT iMessage , WPARAM wParam , LPARAM lParam )
{
        switch ( iMessage)
       {
        case WM_CREATE:
              hEdit = CreateWindow(TEXT ("edit" ), NULL 
               , WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
               , 10, 10, 200, 25
               , hWnd , (HMENU )ID_EDIT , g_hInst, NULL);

               CreateWindow(TEXT ("button" ), TEXT ("Click Me" )
               , WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON
               ,40, 50, 100, 25
               , hWnd, ( HMENU)0, g_hInst, NULL);

               CreateWindow(TEXT ("button" ), TEXT ("Me Two" )
               , WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON
               ,40, 80, 100, 25
               , hWnd, ( HMENU)1, g_hInst, NULL);

               CreateWindow(TEXT ("static" ), TEXT ("Only Text" )
               , WS_CHILD | WS_VISIBLE
               ,20, 110, 100, 25
               , hWnd, ( HMENU)-1, g_hInst, NULL);
               return 0;

        case WM_COMMAND:
               switch ( LOWORD( wParam))
              {
               case ID_EDIT:
                      switch ( HIWORD( wParam))
                     {
                      case EN_CHANGE:
                            GetWindowText(hEdit, str, 128);
                            SetWindowText(hWnd , str);
                            break;
                     }
                      break;
               case 0:
                      MessageBox(hWnd , TEXT ("First Button Clicked" ), TEXT("Button" ), MB_OK );
                      break;
               case 1:
                      MessageBox(hWnd , TEXT ("Second Button Clicked" ), TEXT("Button" ), MB_OK );
                      break;
              }
               return 0;

        case WM_DESTROY:
              PostQuitMessage(0);
               return 0;
       }
        return ( DefWindowProc(hWnd , iMessage , wParam , lParam ));

}


----------------------------------------------------------------------
- ES_AUTOHSCROLL 스타일을 주어 수평 스크롤이 가능하도록 하였다.

- 생성된 에디트 컨트롤의 윈도우 핸들값을 hEdit에 저장해 두었다. 
----------------------------------------------------------------------
#include <windows.h>

#defineXPOS   20     
#defineYPOS   20
#define SW     100
#define SH     25
#define YGAP   5

HWND hWnd;

typedef struct _msgmap
{
        UINT uiMsg;
        LRESULT(*fp)( WPARAM, LPARAM);
} stMsgMap;

LRESULT OnPaint(WPARAM , LPARAM );
LRESULT OnCreate(WPARAM , LPARAM );
LRESULT OnDestroy(WPARAM , LPARAM );

stMsgMap MsgMap[] =
{
       { WM_PAINT, OnPaint },
       { WM_CREATE, OnCreate },
       { WM_DESTROY, OnDestroy },

       { WM_NULL, 0 }
};

//동적 할당을 위한 변수
UCHAR *ucpData;

void print_Bmp_Info(BITMAPFILEHEADER * stfH, BITMAPINFOHEADER * stiH);

LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM );
HINSTANCE g_hInst;
LPSTR lpszClass = TEXT ("smart" );

int APIENTRY WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance
       , LPSTR lpszCmdParam, int nCmdShow )
{
        MSG Message;
        WNDCLASS WndClass;
       g_hInst = hInstance;

       WndClass.cbClsExtra = 0;
       WndClass.cbWndExtra = 0;
       WndClass.hbrBackground = ( HBRUSH)GetStockObject( WHITE_BRUSH);
       WndClass.hCursor = LoadCursor(NULL , IDC_ARROW );
       WndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION);
       WndClass.hInstance = hInstance;
       WndClass.lpfnWndProc = ( WNDPROC)WndProc;
       WndClass.lpszClassName = lpszClass;
       WndClass.lpszMenuName = NULL;
       WndClass.style = CS_HREDRAW | CS_VREDRAW ;
        RegisterClass(&WndClass);

       hWnd = CreateWindow(
              lpszClass,
              lpszClass,
               WS_OVERLAPPEDWINDOW,
              500,   
              100,
              400,
              400,
               NULL, ( HMENU) NULL, hInstance, NULL);
       ShowWindow(hWnd, nCmdShow);

        while ( GetMessage(&Message, 0, 0, 0))
       {
              TranslateMessage(&Message);
               DispatchMessage(&Message);
       }
        return Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWpWnd , UINT iMessage , WPARAM wParam , LPARAM lParam )
{
        stMsgMap *stpMap = MsgMap;
       hWnd = hWpWnd;
        //HDC hdc;

        while ( WM_NULL != ((*stpMap).uiMsg))
       {
               if ( iMessage == ((*stpMap).uiMsg)) //dest가 들어오면
              {
                     (((*stpMap).fp)( wParam, lParam));
                      return 0;
              }
              ++stpMap;
       }
        return( DefWindowProc(hWnd, iMessage , wParam , lParam ));
}
LRESULT OnDestroy( WPARAM wParam , LPARAM lParam )
{
       PostQuitMessage(0);
        return 0;
}
LRESULT OnCreate( WPARAM wParam , LPARAM lParam )
{
        HDC hdc;

        HANDLE hFile;
        BITMAPFILEHEADER stBfhead;
        BITMAPINFOHEADER stBfInfo;

        //hdc = GetDC(hWnd);
        BOOL bRet;
        DWORD dwCnt;

       hFile = CreateFile(TEXT ("1.bmp" ),
               GENERIC_READ,
              0, NULL,
               OPEN_EXISTING,
               FILE_ATTRIBUTE_NORMAL,
               NULL );

        if ( INVALID_HANDLE_VALUE == hFile)
       {
               MessageBox(hWnd, TEXT ("CreatFile 에 실패." ), TEXT ("밝명 Error" ), MB_OK);
              PostQuitMessage(0);
               return 0;
       }

       bRet = ReadFile(hFile, &stBfhead, sizeof(stBfhead), &dwCnt, NULL);
        if ( FALSE == bRet)    // 파일 읽기 실패
       {
               MessageBox(hWnd, TEXT ("stBFHead구조체 ReadFile 실패." ), TEXT ("밝명 Error"), MB_OK);
              CloseHandle(hFile);
              PostQuitMessage(0);
       }
       bRet = ReadFile(hFile, &stBfInfo, sizeof(stBfInfo), &dwCnt, NULL);
        if ( FALSE == bRet)
       {
               MessageBox(hWnd, TEXT ("stBfInfo구조체 ReadFile 실패." ), TEXT ("밝명 Error"), MB_OK);
              CloseHandle(hFile);
              PostQuitMessage(0);
       }

       print_Bmp_Info(&stBfhead, &stBfInfo);

       CloseHandle(hFile);
        return 0;
}
void print_Bmp_Info(BITMAPFILEHEADER * stfH , BITMAPINFOHEADER * stiH )
{
        CreateWindow(TEXT ("static" ), TEXT ("MAGIC NUM : " )
          , WS_CHILD | WS_VISIBLE 
          ,XPOS, YPOS, SW, SH
          , hWnd, ( HMENU)-1, g_hInst, NULL);
        return;
}


LRESULT OnPaint(WPARAM wParam , LPARAM lParam )
{
        PAINTSTRUCT ps;

       BeginPaint(hWnd, &ps);

       EndPaint(hWnd, &ps);
        return 0;

}


----------------------------------------------------------------------

7-3-나. 컨트롤도 윈도우다

1. 2차원배열

2. 구조체한개 글자짝고 

우선 좌만 for문 돌리면  우 좌표 값을 일일이 잡아줘야 하고, 좌우 모두 돌리면 텍스트가 일정해져서, 셋윈도우 텍스트로 문자를 바꿔준다.


1. sprintf를 수작업하고 포문을 돌리는 방법 
2. 헨들러 배열을 만들고 출력. (크기만큼 사용한 만큼 용량을 차지한다.)

* 글자를 모두 출력해놓고 버퍼를 선언해서 (1개) 문자열을 밀어넣고 SetWindow를 이용한다. 
배열한줄만 있으면 된다. 용량이 달다.
----------------------------------------------------------------------
UINT iyCnt;
        HWND hHandle;
        TCHAR *ucTitle[] =
       {
               TEXT( "MAGIC NUM")
               ,  TEXT( "Size of File")
               ,  TEXT( "Data Position")
               ,  TEXT( "Size of BITMAPINFOHEADER")
               ,  TEXT( "Width of Image")
               ,  TEXT( "Height of Image")
               ,  TEXT( "Bit Plane Number")
               ,  TEXT( "Bit Count")
               ,  TEXT( "Compression")
               ,  TEXT( "Size of Image")
               ,  TEXT( "Resolution of Width")
               ,  TEXT( "Resolution of Height")
               ,  TEXT( "Number of Used Color")
               ,  TEXT( "Index of Important Color")
       };

        iyCnt = 0;
        //for (iyCnt = 0; iyCnt < 14; iyCnt++)
       {
               CreateWindow(TEXT ("static" ), ucTitle[iyCnt]
               , WS_CHILD | WS_VISIBLE
               , XPOS, ( YPOS*(iyCnt+1))+ YGAP*iyCnt
               , SW, SH, hWnd, ( HMENU)-1, g_hInst, NULL);
              
               hHandle = CreateWindow(TEXT ("edit" ), TEXT ("test" )
               , WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY
               , XPOS+ SW+ XGAP, ( YPOS*(iyCnt + 1)) + YGAP*iyCnt
               , SW, SH, hWnd, (HMENU)-1, g_hInst, NULL );
       }

        SetWindowText(hHandle, TEXT ("S" ));
        return;
}


----------------------------------------------------------------------


728x90