MFC파일 입출력

작성자: 김동영

작성일: 2011.02.28

제목 : MFC 그림판

 

1.  클래스 다이어그램

 

기본적으로 생성되는 MainWnd, App, ViewWnd를 제외한 클래스에 대해 설명하겠습니다.

DiagramManager View 클래스에서 너무 많은 일을 하게 되니깐 DiagramManager에서 실질적인 처리를 하게됩니다.  View 클래스는 어떤 일이 발생하게 되면 DiagramManager의 메시지를 호출 하게됩니다. Document Diagram을 관리합니다. Pen2, Rectangle2, Ellipse2, Line2 Diagram을 상속받았습니다. MyFile 클래스는 packettizingserialrize를 하기 위한 클래스입니다.

 

 

 

 

 

 =================================================================================

 

 

2.시퀀스 다이어그램 및 소스

 

2-1. 도형 선택

 

도형 선택 버튼을 클릭 하였을 때, DiagramManager 클래스의 ChangeDiagram 메소드를 호출 하여 DiagramManager에서 도형의 타입을 관리해줍니다. Diagram을 생성 할 때, 어떤 타입의 도형인지 알아야 하기 때문입니다. 저는 Rectangle 1,Ellipse2,Line 3으로, Pen 4로 값을 주었습니다.

void DiagramManager::ChangeDiagram(int _dtype)

{

        dtype=_dtype;

}

 

 

 

 

 

 

 

 

  =================================================================================

 

2-2. 마우스 왼쪽 버튼 클릭

 

 

마우스 왼쪽 버튼을 클릭 하였을 때는 도형의 시작점을 관리해주어야합니다. 마우스 왼쪽 버튼을 클릭 하고 마우스를 이동하여 버튼에서 손을 떼는 순간 도형이 그려지기 때문에, 마우스 왼쪽 버튼을 눌렀을 때의 위치를 관리해주고 readymove true값을 줍니다.

void DiagramManager::StartPoint(CPoint point,bool _readymove)

{

        C그림판Doc *doc=C그림판Doc::GetDocument();

        if(dtype==4)

        {

               did=1;

               doc->MakePolyLine(did,point,did);

               did=0; 

        }

        startpoint=point;

        readymove=_readymove;

}

 

 

 

 

 

 

펜을 제외한 나머지 도형들은 시작점만 관리해주면 되지만, 펜의 경우 클릭 하였을 때 객체를 생성하게 하였습니다.
 did
1이면 객체를 생성하고 0이면 펜 객체의 벡터에 점을 추가 하도록 하였습니다.

int C그림판Doc::MakePolyLine(int did,CPoint spt,CPoint npt)

{

        if(did)

        {

               vt.push_back(new Pen2(spt));

               count++;

        }

        else

        {

               vt[vt.size()-1]->AddPoint(npt);

        }

        return did;

}

 

 

 

=================================================================================

 

2-3. 마우스 이동

 

 

StateReadyMove는 클릭한 상태인지를 확인하는 메소드입니다. 만약 true라면 MouseMove메소드를 호출합니다. WM_PAINT에서 그리는게 아니니 CDC값과 이동한 위치를 인자로 넘겨줍니다. 그리고 이동전의 점을 가져온후 점을 펜에 보관해주고 그려줍니다.MakePolyLine은 클릭 하였을 때 did 0으로 변경해주었으므로 AddPoint메소드만 호출하여 펜의 벡터에 점을 보관해줍니다.

void DiagramManager::MouseMove(CDC *dc,CPoint point)

{

        if(dtype==4)

        {

               C그림판Doc *doc=C그림판Doc::GetDocument();

              

               CPoint oldpoint = doc->GetOldPoint();

               doc->MakePolyLine(did,startpoint,point);

               dc->MoveTo(oldpoint);

               dc->LineTo(point)

        }

}

 

 

=================================================================================

 

2-4. 마우스 왼쪽 버튼 UP

 

 

마우스 왼쪽 버튼을 클릭하고, 마우스를 이동하고, 마우스의 버튼을 떼었을 때, 펜을 제외한 나머지 도형들은 생성되어야합니다. 버튼이 UP 되었을때 DiagramManager EndPoint 메소드를 호출하는데, InvalidateRect의 영역을 지정해주기 위해 RECT의 주소값을 넘겨주었습니다. 도형을 만들려면 타입과 시작점과 끝점을 알아야 하기 때문에  MakeDiagram의 인자로 넘겨주었습니다.

도형의 타입에 따라 해당 개체를 생성해줍니다.

 

 

  

================================================================================= 

 

2-4. OnPaint

도형을 생성하고 실질적으로 보여주는 부분입니다. WM_PAINT가 발생하면 DrawAll메시지에 CPaintDC 의 주소값을 인자로 넘겨줍니다. GetDiagramCnt는 도형의 개수를 리턴해주며 GetDiagramType은 벡터의 해당 인덱스의 타입을 리턴한 후 도형의 개수만큼 반복문을 실행합니다. 펜을 제외한 나머지 도형의 RECT 값을 GetDiagram메소드를 통해 가져와서 각각의 타입에 맞게 그려줍니다. 펜의 경우 펜의 점의 개수를 GetPointCnt메소드를 통해가져와 그 개수만큼 GetPoint메소드를 통해 그려줍니다.

void DiagramManager::DrawAll(CPaintDC *dc)

{

        C그림판Doc *doc=C그림판Doc::GetDocument();

        int count=doc->GetDiagramCnt();

 

        for(int i=0;i<count;i++)

        {

               int type=doc->GetDiagramType(i);

               RECT rect=doc->GetDiagram(i);

               switch(type)

               {

               case 1:        DrawRect(dc,rect);break;

               case 2:        DrawEllipse(dc,rect);break;

               case 3:        DrawLine(dc,rect);break;

               case 4:        DrawPen(dc,i);break;

               }

        }

}

 

 

 

void DiagramManager::DrawPen(CPaintDC *dc,int i)

{

        C그림판Doc *doc=C그림판Doc::GetDocument();

        int pointcnt=doc->GetPointCntDoc(i);

       

        CPoint startpoint;

        CPoint endpoint;

        int j=0;

        int a=0;

        for(j=1;j<pointcnt;j++)

        {

               doc->GetPointDoc(i,a,&startpoint);

               doc->GetPointDoc(i,j,&endpoint);

               dc->MoveTo(startpoint);

               dc->LineTo(endpoint);

 

               a++;

        }

}

 

 

void DiagramManager::DrawLine(CPaintDC *dc,RECT rect)

{

        dc->MoveTo(rect.left,rect.top);

        dc->LineTo(rect.right,rect.bottom);

}

 

 

void DiagramManager::DrawRect(CPaintDC *dc,RECT rect)

{

        CBrush* pBrOld = (CBrush*)dc->SelectStockObject(NULL_BRUSH);

        CPen* pPenOld = (CPen*)dc->SelectStockObject(BLACK_PEN);

 

        dc->Rectangle(&rect);

 

        dc->SelectObject(pPenOld);

        dc->SelectObject(pBrOld);

}

 

 

void DiagramManager::DrawEllipse(CPaintDC *dc,RECT rect)

{

        CBrush* pBrOld = (CBrush*)dc->SelectStockObject(NULL_BRUSH);

        CPen* pPenOld = (CPen*)dc->SelectStockObject(BLACK_PEN);

 

        dc->Ellipse(&rect);

 

        dc->SelectObject(pPenOld);

        dc->SelectObject(pBrOld);

}

 

 

 

나머지 Undo,Redo와 파일저장,파일 로드 부분은 Reference를 참고해주시길 바랍니다.



숏메시지,파일전송 구현
문제점 : 파일전송 중 1024용량 만큼 전송 후 FD_WRITE가 발생안함

'기타 > 소켓통신' 카테고리의 다른 글

예비과정 발표점수  (0) 2011.02.14
서버와 클라이언트 tcp,udp사용  (0) 2011.01.20
메신저(동시 메시지,파일 전송)  (0) 2011.01.17
다중파일전송  (0) 2011.01.17
파일입출력(쓰레드구현)  (0) 2011.01.10

'기타 > 소켓통신' 카테고리의 다른 글

WSAAsyncSelect  (0) 2011.02.21
서버와 클라이언트 tcp,udp사용  (0) 2011.01.20
메신저(동시 메시지,파일 전송)  (0) 2011.01.17
다중파일전송  (0) 2011.01.17
파일입출력(쓰레드구현)  (0) 2011.01.10

RECT rt;
GetClientRect(hDlg,&rt); //hDlg==핸들값

'기타 > API' 카테고리의 다른 글

wchar->double ,char->double 캐스팅  (1) 2011.02.07
주소록  (0) 2011.01.10
똑딱이  (0) 2011.01.05
[예비 21기 김동영] 주간 과제물 1차  (0) 2010.10.28
[예비 21기 김동영] 주간 계획서 1차  (0) 2010.10.27

strtod, wcstod

Convert strings to a double-precision value.
 
double strtod(
   const char *nptr,
   char **endptr 
);
double wcstod(
   const wchar_t *nptr,
   wchar_t **endptr 
);

Parameters

nptr
Null-terminated string to convert.
endptr
Pointer to character that stops scan.

Return Value

strtod returns the value of the floating-point number, except when the representation would cause an overflow, in which case the function returns +/–HUGE_VAL. The sign of HUGE_VAL matches the sign of the value that cannot be represented. strtod returns 0 if no conversion can be performed or an underflow occurs.

wcstod returns values analogously to strtod. For both functions, errno is set to ERANGE if overflow or underflow occurs.

See _doserrno, errno, _sys_errlist, and _sys_nerr for more information on this and other return codes.

Remarks

Each function converts the input string nptr to a double. The strtod function converts nptr to a double-precision value. strtod stops reading the string nptr at the first character it cannot recognize as part of a number. This may be the terminating null character. wcstod is a wide-character version of strtod; its nptr argument is a wide-character string. Otherwise, these functions behave identically.

Generic-Text Routine Mappings

TCHAR.H routine _UNICODE & _MBCS not defined _MBCS defined _UNICODE defined
_tcstod strtod strtod wcstod

The LC_NUMERIC category setting of the current locale determines recognition of the radix character in nptr; for more information, see setlocale. If endptr is not NULL, a pointer to the character that stopped the scan is stored at the location pointed to by endptr. If no conversion can be performed (no valid digits were found or an invalid base was specified), the value of nptr is stored at the location pointed to by endptr.

strtod expects nptr to point to a string of the following form:

[whitespace] [sign] [digits] [.digits] [ {d | D | e | E}[sign]digits]

A whitespace may consist of space and tab characters, which are ignored; sign is either plus (+) or minus (); and digits are one or more decimal digits. If no digits appear before the radix character, at least one must appear after the radix character. The decimal digits can be followed by an exponent, which consists of an introductory letter (d, D, e, or E) and an optionally signed integer. If neither an exponent part nor a radix character appears, a radix character is assumed to follow the last digit in the string. The first character that does not fit this form stops the scan.

Requirements

Routine Required header Compatibility
strtod <stdlib.h> ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP
wcstod <stdlib.h> or <wchar.h> ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP

For additional compatibility information, see Compatibility in the Introduction.

Libraries

All versions of the C run-time libraries.

Example

// crt_strtod.c
/* This program uses strtod to convert a
 * string to a double-precision value; strtol to
 * convert a string to long integer values; and strtoul
 * to convert a string to unsigned long-integer values.
 */

#include <stdlib.h>
#include <stdio.h>

int main( void )
{
   char   *string, *stopstring;
   double x;
   long   l;
   int    base;
   unsigned long ul;
   string = "3.1415926This stopped it";
   x = strtod( string, &stopstring );
   printf( "string = %s\n", string );
   printf("   strtod = %f\n", x );
   printf("   Stopped scan at: %s\n\n", stopstring );
   string = "-10110134932This stopped it";
   l = strtol( string, &stopstring, 10 );
   printf( "string = %s\n", string );
   printf("   strtol = %ld\n", l );
   printf("   Stopped scan at: %s\n\n", stopstring );
   string = "10110134932";
   printf( "string = %s\n", string );
   /* Convert string using base 2, 4, and 8: */
   for( base = 2; base <= 8; base *= 2 )
   {
      /* Convert the string: */
      ul = strtoul( string, &stopstring, base );
      printf( "   strtol = %ld (base %d)\n", ul, base );
      printf( "   Stopped scan at: %s\n", stopstring );
   }
}

Output

string = 3.1415926This stopped it
   strtod = 3.141593
   Stopped scan at: This stopped it

string = -10110134932This stopped it
   strtol = -2147483648
   Stopped scan at: This stopped it

string = 10110134932
   strtol = 45 (base 2)
   Stopped scan at: 34932
   strtol = 4423 (base 4)
   Stopped scan at: 4932
   strtol = 2134108 (base 8)
   Stopped scan at: 932



출처 : http://msdn.microsoft.com/en-us/library/kxsfc1ab(VS.71).aspx

'기타 > API' 카테고리의 다른 글

창 크기 알아오기  (0) 2011.02.07
주소록  (0) 2011.01.10
똑딱이  (0) 2011.01.05
[예비 21기 김동영] 주간 과제물 1차  (0) 2010.10.28
[예비 21기 김동영] 주간 계획서 1차  (0) 2010.10.27

불러온 wave파일의 데이터를 사용자가 입력한 숫자만큼 곱하여
새로 wave파일을 쓴다.
음성이 증폭되기보다 잡음이 증폭되는거같다....
좀더 알아봐야겠다

v1.1 
 음성 변경시 double형으로 받아 감소 가능
             wchar->double 캐스팅하는 방법바로가기

'기타 > 메신저' 카테고리의 다른 글

Wave분석 최종  (0) 2011.03.04
워크샵 가기전 파일 백업  (0) 2011.01.26
Wave파형분석및데이터출력(예광탄)  (1) 2011.01.25
개인 주간 계획서 1주차  (0) 2011.01.20
개인 일일 보고서 1일차  (0) 2011.01.20

'기타 > 메신저' 카테고리의 다른 글

Wave분석 최종  (0) 2011.03.04
Wave 버젼  (0) 2011.02.06
Wave파형분석및데이터출력(예광탄)  (1) 2011.01.25
개인 주간 계획서 1주차  (0) 2011.01.20
개인 일일 보고서 1일차  (0) 2011.01.20

예광탄 프로그램

: 2

작성자 : 김동영

작성일 : 2011. 1. 24

제목 : Wave 포맷 분석 및 데이터 출력

 

 

Wave Format

1) RIFF chunk

type

byte

내용

의미

char

4

“RIFF”

파일의 종류가 RIFF 파일을 의미

DWORD

4

FILE SIZE

현재부터 끝까지의 파일 크기

char

4

“WAVE”

Wave 파일을 의미

2) FMT sub-chunk

type

byte

내용

의미

char

4

“fmt”

Chunk ID

DWORD

4

16 | 18

Chunk Size

short

2

wFormatTag

PCMWAVEFORMAT의 값(1:PCM )

short

2

nChannels

채널수(1:모노, 2:스테레오)

DWORD

4

nSamplesPerSec

샘플링 수

DWORD

4

nAvgBytesperSec

초당 샘플 바이트

short

2

BlockAlign

샘플당 바이트

short

2

wBitsPerSample

샘플당 비트수

3) Data sub-chunk

type

byte

내용

의미

char

4

“data”

데이터 청크의 시작

DWORD

4

DATA SIZE

데이터의 크기

 

 

DATA

데이터

 

 

SoundInfo 클래스는 RIFF Chunk(ParentChunk 클래스) FMT Sub-Chunk(SubChunk 클래스) Data Sub-Chunk(DataChunk) 관리해주는 클래스이다.

 

 

 

SoundInfo.cpp

생성자에서 각각의 Chunk별로 데이터들을 얻는다.

 

 

 

SoundInfo::SoundInfo(HANDLE hFile)

{

             parent_chunk=new ParentChunk(hFile);

             sub_chunk=new SubChunk(hFile);

             data_chunk=new DataChunk(hFile);

}

 

 

ParentChunk 데이터를 얻어온다.

 

 

 

char *SoundInfo::GetFiletype()

{

             return parent_chunk->GetFiletypeC();

}

int SoundInfo::GetFilesize()

{

             return parent_chunk->GetFilesizeC();

}

char *SoundInfo::GetMediatype()

{

             return parent_chunk->GetMediatypeC();

}

 

 

 

Chunk별로 Wave파일의 속성이 맞는지 확인한다.

 

bool SoundInfo::CheckParentChunk()

{

             return parent_chunk->IsAvailChunk();

}

bool SoundInfo::CheckSubChunk()

{

             return sub_chunk->IsAvailChunk();

}

bool SoundInfo::CheckDataChunk()

{

             return data_chunk->IsAvailChunk();

}

 

 

 

SubChunk 데이터를 얻어온다.

 

  

char *SoundInfo::GetMagic()//매직

{

             return sub_chunk->GetMagicC();

}

int SoundInfo::GetPt()

{

             return sub_chunk->GetPtC();

}

short SoundInfo::GetFormat()//포맷

{

             return sub_chunk->GetFormatC();

}

short SoundInfo::GetChannelcnt()//채널수

{

             return sub_chunk->GetChannelcntC();

}

int  SoundInfo::GetSamples_persec()//초당샘플수

{

             return sub_chunk->GetSamples_persecC();

}

int  SoundInfo::GetBytes_persec() //초당바이트수- 평균값임

{

             return sub_chunk->GetBytes_persecC();

}

short  SoundInfo::GetSize_sample() //샘플1개의사이즈

{

             return sub_chunk->GetSize_sampleC();

}

short  SoundInfo::GetBits_persample()//샘플한개의비트수

{

             return sub_chunk->GetBits_persampleC();

}

short *SoundInfo::GetSize_extend()//옵션의사이즈

{

             return sub_chunk->GetSize_extendC();

}

 

 

 

DataChunk 데이터를 얻어온다.

  

char *SoundInfo::GetDataMagic()

{

             return data_chunk->GetDataMagicC();

}

int SoundInfo::GetDataSize()

{

             return data_chunk->GetDataSizeC();

}

short* SoundInfo::GetData()

{

             return data_chunk->GetDataC();

}

 

 

 

 

 

ParentChunk.cpp

Filetype,filesize,mediatype 읽어온다.

 

  

ParentChunk::ParentChunk(HANDLE hFile)

{

             DWORD dwRead;

             ReadFile(hFile,filetype,4,&dwRead,0);

             filetype[4]=0;

             ReadFile(hFile,&filesize,4,&dwRead,0);

             ReadFile(hFile,mediatype,4,&dwRead,0);

             mediatype[4]=0;

}

 

 

 

만약 filetype “RIFF” 아니거나 mediatype “WAVE” 아닌 경우 0 리턴한다

 

bool ParentChunk::IsAvailChunk()

{

           return (strcmp(MAGIC_FILE_TYPE,filetype)==0)&&(strcmp(MAGIC_WAVE_TYPE,mediatype)==0);

}

 

char *ParentChunk::GetFiletypeC()

{

             return filetype;

}

int ParentChunk::GetFilesizeC()

{

             return filesize;

}

char *ParentChunk::GetMediatypeC()

{

             return mediatype;

}

 

 

SubChunk.cpp

 

ChunkID,ChunkSize, PCMWAVEFORMAT의 값,채널수,샘필링수,초당 샘플 바이트,샘플당 바이트, 샘플당 비트수를 얻어온다.

 *, pt(ChunkSize) 18일 경우에는 SubChunk 2바이트 이후 DataChunk사이와 SubChunk 사이에 ChunkData가 한 개 더 있다. 그래서 ChunkIDChunkSizeChunk데이터를 얻어왔다.

 

 

SubChunk::SubChunk(HANDLE hFile)

{

             DWORD dwRead;

             ReadFile(hFile,magic,4,&dwRead,0);

             magic[4]=0;

             ReadFile(hFile,&pt,4,&dwRead,0);

             ReadFile(hFile,&format,2,&dwRead,0);

             ReadFile(hFile,&channelcnt,2,&dwRead,0);

             ReadFile(hFile,&samples_persec,4,&dwRead,0);

             ReadFile(hFile,&bytes_persec,4,&dwRead,0);

             ReadFile(hFile,&size_sample,2,&dwRead,0);

             ReadFile(hFile,&bits_persample,2,&dwRead,0);

            

             //pt1618이아닌경우는배제

             if(pt==18 )

             {

                           size_extend = (short *)malloc(2);

                           ReadFile(hFile,size_extend,2,&dwRead,0);

                           char fmagics[5]={0,};

                           ReadFile(hFile,fmagics,4,&dwRead,0);

                           int next;

                           ReadFile(hFile,&next,4,&dwRead,0);

                           char foo[4096];

                           ReadFile(hFile,foo,next,&dwRead,0);

             }         

}

 

 

 

 

ChunkID(magic)“fmt”이 아니거나 format(PCMWAVEFORMAT)값이 1(Wave Format PCM 방식) 이 아닐 때 0을 리턴한다.

 

 

bool SubChunk::IsAvailChunk()

{

             return (strcmp(MAGIC_SUB_TYPE,magic)==0)&&(format==PCMWAVE_FORMAT);

}

 

 

 

 

 

 

 

 

char *SubChunk::GetMagicC()//ChunkID

{

             return magic;

}

int SubChunk::GetPtC()//ChunkSize

{

             return pt;

}

short SubChunk::GetFormatC()//포맷

{

             return format;

}

short SubChunk::GetChannelcntC()//채널수

{

             return channelcnt;

}

int  SubChunk::GetSamples_persecC()//초당샘플수

{

             return samples_persec;

}

int  SubChunk::GetBytes_persecC() //초당바이트수- 평균값임

{

             return bytes_persec;

}

short  SubChunk::GetSize_sampleC() //샘플1개의사이즈

{

             return size_sample;

}

short  SubChunk::GetBits_persampleC()//샘플한개의비트수

{

             return bits_persample;

}

short *SubChunk::GetSize_extendC()

{

             return size_extend;

}

 

 

 

DataChunk.cpp

 

ChunkID,DataSize,Data 얻어온다.

 

 

DataChunk::DataChunk(HANDLE hFile)

{

             DWORD dwRead;

             ReadFile(hFile,magic,4,&dwRead,0);

             magic[4]=0;

             ReadFile(hFile,&datasize,4,&dwRead,0);

            

             data=(short *)malloc(datasize);

             ReadFile(hFile,data,datasize,&dwRead,0);

}

 

 

 

ChunkID“DATA”아니면 0을 리턴한다.

 

 

bool DataChunk::IsAvailChunk()

{

             return (strcmp(MAGIC_DATA_TYPE,magic)==0);

}

 

char *DataChunk::GetDataMagicC()

{

             return magic;

}

int DataChunk::GetDataSizeC()

{

             return datasize;

}

short* DataChunk::GetDataC()

{

             return data;

}

 

 

  

 

입력받은 Chunk들을 Edit박스에 나타내었고, 데이터들을 Lineto함수로 출력해주었다.

 

 

 

 

 

 

 

'기타 > 메신저' 카테고리의 다른 글

Wave분석 최종  (0) 2011.03.04
Wave 버젼  (0) 2011.02.06
워크샵 가기전 파일 백업  (0) 2011.01.26
개인 주간 계획서 1주차  (0) 2011.01.20
개인 일일 보고서 1일차  (0) 2011.01.20

'기타 > 소켓통신' 카테고리의 다른 글

WSAAsyncSelect  (0) 2011.02.21
예비과정 발표점수  (0) 2011.02.14
메신저(동시 메시지,파일 전송)  (0) 2011.01.17
다중파일전송  (0) 2011.01.17
파일입출력(쓰레드구현)  (0) 2011.01.10

'기타 > C++' 카테고리의 다른 글

Native C++에서 C++/CLR 클래스 사용하기(CLR 옵션)  (0) 2015.03.06
Native C++에서 C++/CLR 클래스 사용하기  (0) 2015.03.06
비트학생관리  (0) 2011.01.20

+ Recent posts