---
title: "클립보드 기능 구현"
id: "693"
type: "post"
slug: "406"
published_at: "2011-01-07T16:28:34+00:00"
modified_at: "2025-12-12T04:16:43+00:00"
url: "https://dworld.deios.kr/406/"
markdown_url: "https://dworld.deios.kr/406.md"
excerpt: "이번에는 자주 사용하는 기능인 C&P(Copy & Paste)를 구현해 보도록 하겠습니다. C&P를 구현하기 위해서는 이미지를 DIB(장치 독립 비트맵;Device Independent Bitmap)으로 변환하여 클립보드 영역에 넘겨주거나, 클립보드 영역에서 데이터를 받아오면 됩니다. 클립보드 영역으로 데이터를 넘겨주기 위하여 CopyClipBoard맴버함수, CopyToHandle 맴버 함수를 추가하여, ID_EDIT_COPY이벤트 핸들러에..."
taxonomy_category:
  - "Study"
taxonomy_post_tag:
  - "MFC"
  - "OpenCV 2.1"
  - "vs 2010"
---

이번에는 자주 사용하는 기능인 C&P(Copy & Paste)를 구현해 보도록 하겠습니다.

C&P를 구현하기 위해서는 이미지를 DIB(장치 독립 비트맵;Device Independent Bitmap)으로 변환하여 클립보드 영역에 넘겨주거나, 클립보드 영역에서 데이터를 받아오면 됩니다.

클립보드 영역으로 데이터를 넘겨주기 위하여 CopyClipBoard맴버함수, CopyToHandle 맴버 함수를 추가하여, ID_EDIT_COPY이벤트 핸들러에 등록합니다.

먼저 CopyClipBoard 맴버 함수를 Doc Class에 작성하겠습니다.

반환 형식 : void

함수 이름 : CopyClipBoard

매개 변수 형식 : IplImage *

매개 변수 이름 : m_pCopyImage

다음과 같이 코딩합니다.

```
HANDLE hDIB = CopyToHandle(m_pCopyImage);

if(::OpenClipboard(AfxGetMainWnd()->GetSafeHwnd())){

        if(::EmptyClipboard()){

                if(NULL == ::SetClipboardData(CF_DIB, hDIB)){

                        AfxMessageBox(TEXT("클립보드에 영상을 저장하는 도중 오류가 발생했습니다."));

                }

        }

}

::CloseClipBoard();
```

이번에는 아까와 같은 방법으로 CopyToHandle 맴버 함수를 작성합니다.

반환 형식 : HANDLE

함수 이름 : CopyToHandle

매개 변수 형식 : IplImage *

매개 변수 이름 : image

다음과 같이 코딩합니다. (출처 : 오픈소스 OpenCV를 이용한 컴퓨터 비전 실무 프로그래밍 p237)

```
       int nChannels = image->nChannels;  

        int bpp = 8*nChannels;  

        IplImage *flip_image = cvCloneImage( image );  

        cvFlip( image, flip_image, 0 );   

        int bmpDataSize = flip_image->imageSize;  

        // 비트맵 헤더 구성   

        BITMAPINFOHEADER bmpHeader;  

        bmpHeader.biSize = sizeof(BITMAPINFOHEADER); // 이 구조체의 크기  

        bmpHeader.biHeight = image->height; // 영상의 높이  

        bmpHeader.biWidth = image->width;   // 영상의 너비  

        bmpHeader.biPlanes = 1; // 비트 플레인 수 (항상 1임)  

        bmpHeader.biBitCount = bpp; // 한 화소당 비트 개수   

        bmpHeader.biCompression = BI_RGB; // BI_RGB : 압축하지 않음  

        bmpHeader.biSizeImage = bmpDataSize; // 영상의 크기  

        if(8 == bpp) bmpHeader.biClrUsed = bmpHeader.biClrImportant  = 256;   

        else if(24 == bpp) bmpHeader.biClrUsed = bmpHeader.biClrImportant  = 0;

        int bmpAllSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256 + bmpDataSize*sizeof(char);  

        HGLOBAL hDIB = (HGLOBAL)::GlobalAlloc(GMEM_MOVEABLE| GMEM_ZEROINIT,  

                                                                                  bmpAllSize );  

        if(NULL == hDIB) return NULL;  

        LPSTR pDIB = (LPSTR)::GlobalLock((HGLOBAL)hDIB);  

        memcpy( pDIB, &bmpHeader, sizeof(BITMAPINFOHEADER) );  

 

        if(8 == bpp){  

                RGBQUAD palette[256];  

                memcpy( pDIB+sizeof(BITMAPINFOHEADER), palette, sizeof(RGBQUAD)*256 );  

                memcpy( pDIB+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256,   

                                flip_image->imageData, bmpDataSize );  

        }   

        else if(24 == bpp){  

                memcpy( pDIB+sizeof(BITMAPINFOHEADER),   

                                flip_image->imageData, bmpDataSize );  

        } 

        ::GlobalUnlock((HGLOBAL)hDIB);  

        cvReleaseImage( &flip_image );  

   

        return hDIB;
```

이제 ID_EDIT_COPY에 대한 이벤트 핸들러만 수정해 주면 끝입니다.

이벤트 핸들러를 수정하기 위해 다음과 같이 합니다.

```
void CMFC_OpenCVView::OnEditCopy()

{

        // TODO: 여기에 명령 처리기 코드를 추가합니다.

        CMFC_OpenCVDoc* pDoc = GetDocument();  

        ASSERT_VALID(pDoc);

        pDoc->CopyClipBoard( pDoc->m_CvvImage.GetImage() ); 

}
```

프로그램에서 Copy하여 그림판 같은 곳에 Paste했을 때 정상적으로 동작한다면 성공.

이번에는 Paste기능을 구현해 보도록 하겠습니다. Paste는 Copy의 역순입니다.

CreateFromHandle맴버 함수를 작성하고, ID_EDIT_PASTE에 이벤트 핸들러를 등록하고, 마지막으로 클립보드 영역에 DIB 데이터가 존재할 경우에만 ID_EDIT_PASTE가 동작하도록 하기 위해서 OnUpdateEditPaste 맴버 함수를 작성하겠습니다. 이번에는 모든 함수가 App Class에서 작성될 것이고, 코드만 첨부합니다.

```
void CMFC_OpenCVApp::OnEditPaste()

{

        // TODO: 여기에 명령 처리기 코드를 추가합니다.

        POSITION pos = GetFirstDocTemplatePosition();  

        CDocTemplate *pTemplate = GetNextDocTemplate(pos);  

        CMFC_OpenCVDoc *pDoc = (CMFC_OpenCVDoc* )pTemplate->OpenDocumentFile(NULL);   

  

        if( pDoc ){  

                HANDLE hDIB = NULL;  

                if (::OpenClipboard(AfxGetMainWnd()->GetSafeHwnd())) hDIB = ::GetClipboardData(CF_DIB);  

  

                if( hDIB ){  

                        IplImage *image = CreateFromHandle( hDIB );  

          

                        pDoc->m_CvvImage.CopyOf( image, image->nChannels*8 );  

  

                        POSITION pos = pDoc->GetFirstViewPosition();  

                        CMFC_OpenCVView *pView = (CMFC_OpenCVView *)pDoc->GetNextView(pos);  

  

                        CSize sizeTotal = CSize(pDoc->m_CvvImage.Width(),  

                        pDoc->m_CvvImage.Height());  

  

                        pView->SetScrollSizes(MM_TEXT, sizeTotal);  

                        pView->ResizeParentToFit(FALSE);  

                }  

  

                ::CloseClipboard();  

        } 

}
```

```
IplImage * CMFC_OpenCVApp::CreateFromHandle(HANDLE hDIB)

{

    LPSTR pDIB = (LPSTR)::GlobalLock((HGLOBAL)hDIB);    

    BITMAPINFOHEADER bmpHeader;   

    memcpy( &bmpHeader, pDIB, sizeof(BITMAPINFOHEADER) );    

      

    int height = bmpHeader.biHeight;  

    int width = bmpHeader.biWidth;  

    int nChannels = bmpHeader.biBitCount/8;  

    int bmpDataSize = bmpHeader.biSizeImage;  

    char *imageData = (char *)calloc( bmpDataSize, sizeof(char) );  

  

    if(8 == bmpHeader.biBitCount)

        memcpy( imageData, pDIB+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256,   

                bmpDataSize );

    else if(24 == bmpHeader.biBitCount)

        memcpy( imageData, pDIB+sizeof(BITMAPINFOHEADER), bmpDataSize );  

 

    IplImage *flip_image = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, nChannels);  

    memcpy( flip_image->imageData, imageData, bmpDataSize );  

 

    IplImage *recover_image = cvCloneImage( flip_image );  

    cvFlip( flip_image, recover_image, 0 );  

  

    ::GlobalUnlock((HGLOBAL)hDIB);    

 

    free(imageData);  

    cvReleaseImage( &flip_image );  

  

    return recover_image;  

}
```

```
void CMFC_OpenCVApp::OnUpdateEditPaste(CCmdUI *pCmdUI)

{

        // TODO: 여기에 명령 업데이트 UI 처리기 코드를 추가합니다.

        if( !IsClipboardFormatAvailable(CF_DIB) ) pCmdUI->Enable( FALSE );

}
```

**App Class의 헤더 파일에 #include 를 추가해 줘야 합니다.**

cfile25.uf.19311C444D273F25031758.pdfcfile7.uf.1227C1444D273F261C4D3D.zip

### 이 글 공유하기:

- [Facebook으로 공유하기 (새 창에서 열림)Facebook](https://dworld.deios.kr/406/?share=facebook)
- [X에 공유 (새 창에서 열림)X](https://dworld.deios.kr/406/?share=x)
-

### 이것이 좋아요:

좋아하기로드 중...

### *관련*

### 관련된 글:

1. [OpenCV 파일 저장기능 구현](https://dworld.deios.kr/401/)
2. [OpenCV 파일 저장기능 구현2](https://dworld.deios.kr/402/)
3. [Drag and Drop 지원하기](https://dworld.deios.kr/404/)
4. [모든 창 닫기 구현](https://dworld.deios.kr/405/)

## Similar Posts

- [https://dworld.deios.kr/430/](https://dworld.deios.kr/430/) 예전에 한번 했던거지만… ARToolkit 리빌드 기념으로 모토글램에 올려봤다… 뭐 역시… 일본인의 집념에 찬사를… 관련된 글: Visual Studio 2010에서 OpenCV 라이브러리 빌드하기 Cam 영상 출력해보기 영상 복원(Image Restoration) Wavelet Transform ### 이 글 공유하기: - [Facebook으로 공유하기 (새 창에서 열림)Facebook](https://dworld.deios.kr/430/?share=facebook) - [X에 공유 (새 창에서 열림)X](https://dworld.deios.kr/430/?share=x) - ### 이것이 좋아요: 좋아하기로드 중...
- [https://dworld.deios.kr/407/](https://dworld.deios.kr/407/) 이번에는 본격적으로 OpenCV를 사용하여 영상처리를 해 보겠습니다. 그 첫 단계로 메뉴기반 정지영상 처리를 해 볼 것이며, cvSplit함수를 사용하여 RGB 컬러공간을 분리하는 예제를 구현해 보겠습니다. 먼저 OpenCV 2.1 C API Reference에서 cvSplit함수를 찾아보면 다음과 같습니다. cvSplit함수는 다중 채널(Multi-channel)배열을 여러 개의 단일 채널(Single-channel) 배열로 분할하거나, 배열에서 단일 채널을 추출 할 수 있음을 알 수 있습니다. 또한,… ### 이 글 공유하기: - [Facebook으로 공유하기 (새 창에서 열림)Facebook](https://dworld.deios.kr/407/?share=facebook) - [X에 공유 (새 창에서 열림)X](https://dworld.deios.kr/407/?share=x) - ### 이것이 좋아요: 좋아하기로드 중...
- cfile10.uf.134020484F5BB4033946D3.pdf 관련된 글: [VS2010]LPCTSTR에서 char*로 형 변환하기 Visual Studio 2010에서 OpenCV MFC 프로젝트 만들기 HVR-2000 Series 이용하기 MFC – Cam 영상 출력해보기 ### 이 글 공유하기: - [Facebook으로 공유하기 (새 창에서 열림)Facebook](https://dworld.deios.kr/457/?share=facebook) - [X에 공유 (새 창에서 열림)X](https://dworld.deios.kr/457/?share=x) - ### 이것이 좋아요: 좋아하기로드 중...
- [https://dworld.deios.kr/420/](https://dworld.deios.kr/420/) 이번 시간에는 MFC프로젝트에서 Cam 영상을 받아오는 부분을 구현해 보겠습니다. “동영상 처리” → “영상 보기”메뉴를 추가하고, 해당 메뉴를 클릭했을 때, 영상을 뿌려주는 Dialog를 띄웁니다. Dialog에서 “시작” 버튼을 클릭했을 경우 Caption이 “중지”로 바뀌고, Static 영역에 영상을 뿌려주게 만들어 보겠습니다. 먼저 사용할 다이얼로그부터 만들어야겠죠? [리소스 뷰]에서 [리소스 추가]를 선택합니다. [Dialog]가 선택된 것을 확인하고 [새로 만들기]를… ### 이 글 공유하기: - [Facebook으로 공유하기 (새 창에서 열림)Facebook](https://dworld.deios.kr/420/?share=facebook) - [X에 공유 (새 창에서 열림)X](https://dworld.deios.kr/420/?share=x) - ### 이것이 좋아요: 좋아하기로드 중...
- [https://dworld.deios.kr/409/](https://dworld.deios.kr/409/) 이번 시간에는 Dialog Box기반으로 OpenCV를 이용하는 방법에 대해서 알아보겠습니다. 공간 필터링(Spatial Filtering)이란 영상에 있는 공간 주파수 대역을 제거하거나 강조하는 필터 처리입니다. 사용되는 필터의 계수에 따라 특정 주파수를 제거하거나 강조하게 되며, 필터 마스크(Filter Mask)또는 회선 마스크의 가중치 선택이 공간 필터의 행동을 결정하게 됩니다. 영상처리에 사용되는 회선 마스크는 홀수 차원의 정방형 마스크가 사용되게 됩니다. 필터는… ### 이 글 공유하기: - [Facebook으로 공유하기 (새 창에서 열림)Facebook](https://dworld.deios.kr/409/?share=facebook) - [X에 공유 (새 창에서 열림)X](https://dworld.deios.kr/409/?share=x) - ### 이것이 좋아요: 좋아하기로드 중...
- [https://dworld.deios.kr/423/](https://dworld.deios.kr/423/) 이번 시간은 MFC와 OpenCV의 기본 사용법 마지막 내용이 되겠습니다. Cam 영상을 Dialog에 뿌려주는 부분에서 기본 사용법이 끝났어야 하지만… 조금 아쉬운 관계로 더 진행해 봤죠… 저도 아직 초보단계지만, MFC와 OpenCV의 기본 사용법은 뭐 없습니다… MFC야… GUI프로그래밍을 위해서 그냥 쓴 것이고… OpenCV는 영상을 받아오고, 출력하는 부분만 하면 기본은 끝난거 아닌가요? 지금까지 “오픈소스 OpenCV를 이용한 컴퓨터 비전… ### 이 글 공유하기: - [Facebook으로 공유하기 (새 창에서 열림)Facebook](https://dworld.deios.kr/423/?share=facebook) - [X에 공유 (새 창에서 열림)X](https://dworld.deios.kr/423/?share=x) - ### 이것이 좋아요: 좋아하기로드 중...

### 댓글 남기기[응답 취소](/406/?t=1784851319#respond)
