コンテンツにスキップ

Clipboard

クリップボード

Win32APIを利用してTexture2Dをクリップボードに読み書きする

c++
#include "pch.h"
#include <Windows.h>

# define DLL_API extern "C" __declspec(dllexport)

//  Read Clipboard
DLL_API bool hasClipboardImage() {
    bool isOpened = OpenClipboard(NULL);
    bool result = false;
    if (isOpened) {
        result = IsClipboardFormatAvailable(CF_DIB);
    }
    CloseClipboard();
    return result;
}

static BITMAPINFO* getLockedBitmapInfoPtr() {
    HANDLE hClipboardData = GetClipboardData(CF_DIB);
    LPVOID clipboardDataPtr = GlobalLock(hClipboardData);
    return static_cast<BITMAPINFO*>(clipboardDataPtr);
}

DLL_API void getClipboardImageSize(int* width, int* height, int* bitsPerPixel) {
    bool IsOpened = OpenClipboard(NULL);
    if (IsOpened && IsClipboardFormatAvailable(CF_DIB)) {
        BITMAPINFO* bmpInfoPtr = getLockedBitmapInfoPtr();
        if (bmpInfoPtr != nullptr) {
            *width = bmpInfoPtr->bmiHeader.biWidth;
            *height = bmpInfoPtr->bmiHeader.biHeight;
            *bitsPerPixel = bmpInfoPtr->bmiHeader.biBitCount;
        }
        GlobalUnlock(bmpInfoPtr);
    }
    CloseClipboard();
}

DLL_API bool getClipboardImage(unsigned char* buffer) {
    bool isOpened = OpenClipboard(NULL);
    bool result = false;
    if (!isOpened) {
        CloseClipboard();
        return false;
    }
    if (IsClipboardFormatAvailable(CF_DIB)) {
        BITMAPINFO* bmpInfoPtr = getLockedBitmapInfoPtr();
        if (bmpInfoPtr != nullptr) {
            int width, height, bitsPerPixel;
            getClipboardImageSize(&width, &height, &bitsPerPixel);

            //  Only24bit(JPEG), 32bit(PNG-32)
            if (bitsPerPixel == 24 || bitsPerPixel == 32) {
                unsigned char* pixelData = (unsigned char*)bmpInfoPtr + bmpInfoPtr->bmiHeader.biSize;
                int bytesPerPixel = bitsPerPixel / 8;
                if (bmpInfoPtr->bmiHeader.biCompression == BI_BITFIELDS) {
                    pixelData += 4 * 3;
                }

                int bytesPerLine = width * bytesPerPixel;
                if (bytesPerLine % 4 != 0) {
                    bytesPerLine += 4 - (bytesPerLine % 4);
                }

                unsigned char* dst = buffer;
                unsigned char* src = pixelData;
                for (int h = 0; h < height; h++) {
                    memcpy(
                        dst + (width * h * bytesPerPixel),
                        src + (h * bytesPerLine),
                        width * bytesPerPixel
                    );
                }
                result = true;
            }
        }
        GlobalUnlock(bmpInfoPtr);
    }
    CloseClipboard();
    return result;
}

//  Write Clipboard
DLL_API bool setClipboardImage(unsigned char* data, int width, int height) {
    HANDLE hMem;
    int size = width * height * 4;

    if (!OpenClipboard(NULL)) {
        CloseClipboard();
        return false;
    }

    HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, sizeof(BITMAPINFOHEADER) + size);
    BITMAPINFO* pInfo = (BITMAPINFO*)GlobalLock(hg);

    pInfo->bmiHeader.biSize = sizeof(BITMAPINFO);
    pInfo->bmiHeader.biWidth = width;
    pInfo->bmiHeader.biHeight = height;
    pInfo->bmiHeader.biPlanes = 1;
    pInfo->bmiHeader.biBitCount = 32;
    pInfo->bmiHeader.biCompression = BI_RGB;
    pInfo->bmiHeader.biSizeImage = width * height * 4;
    pInfo->bmiHeader.biXPelsPerMeter = 0;
    pInfo->bmiHeader.biYPelsPerMeter = 0;
    pInfo->bmiHeader.biClrUsed = 0;
    pInfo->bmiHeader.biClrImportant = 0;

    memcpy(pInfo->bmiColors, data, size);
    GlobalUnlock(hg);

    EmptyClipboard();
    SetClipboardData(CF_DIB, hg);
    //SetClipboardData(CF_BITMAP, hg);

    CloseClipboard();
    return true;
}
C# DLLImport
[DllImport("libycpp")] private static extern bool hasClipboardImage();
[DllImport("libycpp")] private static extern void getClipboardImageSize(ref int width, ref int height, ref int bitsPerPixel);
[DllImport("libycpp")] private static extern bool getClipboardImage(IntPtr buffer);
[DllImport("libycpp")] private static extern bool setClipboardImage(IntPtr data, int width, int height);
C# Read
Material mat;

if (GetClipboardImage(out Texture2D tex)){
    mat.mainTexture = tex;
}
C# Write
Texture2D tex;

//  Prepare Data
byte[] btex = tex.GetRawTextureData();
for (int i = 0; i < btex.Length; i += 4) {
    //  RGBA -> BGRA
    byte colR = btex[i + 0];
    btex[i + 0] = btex[i + 2];
    btex[i + 2] = colR;
}

//  Set Data
IntPtr dataPtr = Marshal.AllocHGlobal(btex.Length);
Marshal.Copy(btex, 0, dataPtr, btex.Length);
setClipboardImage(dataPtr, tex.width, tex.height);

最終更新日: August 14, 2023
作成日: August 14, 2023