読者です 読者をやめる 読者になる 読者になる

プログラミング C# - 翔ソフトウェア (Sho's)

C#/.NET/ソフトウェア開発など

ドキュメントの内容をクリップボードへ (MFC版)

SyntaxHighlighter を使って C++ソースコードに色を付けてみる実験。

// MFC版
// ドキュメントの内容を:
// ・クリップボードへメタファイルと独自形式でコピー
// ・クリップボードから独自形式でペースト
// ※ MyDocument::Serialize と MyView::OnDraw でのドキュメントの描画を実装しておくこと

// MyView.h

class MyView : public CView
{
    DECLARE_DYNCREATE(MyView)
    DECLARE_MESSAGE_MAP()

    HGLOBAL globalMemoryHandle;

protected:
    MyView() : globalMemoryHandle(NULL)
    {}

    MyDocument* GetDocument() const
    { return reinterpret_cast<MyDocument*>(m_pDocument); }

    virtual void OnDraw(CDC* pDC)
    {
        if (GetDocument() != NULL)
            /* ドキュメントの描画 */ ;
    }

    afx_msg void OnEditCopy()
    {
        if (GetDocument() == NULL)
            return;

        // ドキュメントが空なら何もしない
        // 例.
        // if (GetDocument()->IsEmpty())
        //     return;

        // 拡張メタファイルの作成
        CClientDC   clientDC(this);
        CMetaFileDC metaDC;
        metaDC.CreateEnhanced(&clientDC, NULL, NULL, NULL);
        OnDraw(&metaDC);
        const HENHMETAFILE enhancedMetaFileHandle = metaDC.CloseEnhanced();

        // メモリへのシリアライズ
        CSharedFile sharedFile;
        {
            CArchive ar(&sharedFile, CArchive::store);
            GetDocument()->Serialize(ar);
        }
        globalMemoryHandle = sharedFile.Detach();

        // クリップボードへの書き込み
        if (OpenClipboard()) {
            ::EmptyClipboard();
            ::SetClipboardData(CF_ENHMETAFILE, CopyEnhMetaFile(enhancedMetaFileHandle, NULL));
            ::SetClipboardData(CF_PRIVATEFIRST, globalMemoryHandle);
            ::CloseClipboard();
        }

        ::DeleteEnhMetaFile(enhancedMetaFileHandle);
    }

    afx_msg void OnEditPaste()
    {
        if (GetDocument() == NULL)
            return;

        if (OpenClipboard()) {
            const HANDLE clipboardData = ::GetClipboardData(CF_PRIVATEFIRST);
            if (clipboardData != NULL) {
                CSharedFile sharedFile;
                sharedFile.SetHandle(clipboardData);
                {
                    CArchive ar(&sharedFile, CArchive::load);
                    GetDocument()->Serialize(ar);
                }
                sharedFile.Detach();
                GetDocument()->SetModifiedFlag();
                Invalidate();
            }
            ::CloseClipboard();
        }
    }

    afx_msg void OnDestroyClipboard()
    {
        CView::OnDestroyClipboard();

        // WM_DESTROYCLIPBOARD 時に CF_PRIVATEFIRST で確保したメモリを開放する必要がある
        if (globalMemoryHandle != NULL) {
            ::GlobalUnlock(globalMemoryHandle);
            ::GlobalFree  (globalMemoryHandle);
            globalMemoryHandle = NULL;
        }
    }
};

// MyView.cpp

#include "MyView.h"

IMPLEMENT_DYNCREATE(MyView, CView)

BEGIN_MESSAGE_MAP(MyView, CView)
    ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
    ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
    ON_WM_DESTROYCLIPBOARD()
END_MESSAGE_MAP()