#include <windows.h>
#include <stdio.h>
#include <GdiPlus.h>
#include "resource.h"
#pragma comment(lib, "GdiPlus.lib")
using namespace Gdiplus;
GdiplusStartupInput gdiSI;
ULONG_PTR gdiToken;
Bitmap *Bmp2;
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
Status Get_ClipBoard_DIB();
Status Set_ClipBoard_DIB();
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
GdiplusStartup(&gdiToken,&gdiSI,NULL); // GDI+オブジェクト初期化
break;
case WM_PAINT:
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hWnd,&ps);
Graphics MyGraphics(hDC);
if(Bmp2)
MyGraphics.DrawImage(Bmp2, 0, 0);
EndPaint(hWnd,&ps);
}
break;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDM_COPY:
if(Bmp2){
Set_ClipBoard_DIB();
}
break;
case IDM_PASTE:
delete Bmp2;
Bmp2 = NULL;
if(Get_ClipBoard_DIB() == Ok){
InvalidateRect(hWnd,NULL,TRUE);
}
break;
}
break;
case WM_CLOSE:
delete Bmp2;
Bmp2 = NULL;
DestroyWindow(hWnd);
GdiplusShutdown(gdiToken);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}// CALLBACK WndProc
Status Get_ClipBoard_DIB()
{
HANDLE hMem;
BITMAPINFO *pbmi;
BYTE *pbits; // ピクセルデータ
UINT nColors; // パレットの色数
UINT nBitFields = 0; // ピクセルフォーマットマスクのサイズ
if(!OpenClipboard(NULL)){
MessageBox(NULL,"クリップボードを開けません",MYWNDTITLE,MB_OK | MB_ICONWARNING);
return GenericError;
}
hMem = (HANDLE) GetClipboardData (CF_DIB);
if(!hMem) return GenericError;
pbmi = (LPBITMAPINFO) GlobalLock (hMem);
if(!pbmi){
GlobalUnlock(hMem);
return GenericError;
}
// パレットの色数
if(pbmi->bmiHeader.biClrUsed != 0 )
nColors = pbmi->bmiHeader.biClrUsed;
else if(pbmi->bmiHeader.biBitCount <= 8)
nColors = 1 << pbmi->bmiHeader.biBitCount;
else
nColors = 0;
if(pbmi->bmiHeader.biCompression == BI_BITFIELDS)
nBitFields = sizeof(DWORD) * 3;
pbits = ((LPBYTE)pbmi + sizeof(BITMAPINFOHEADER)
+ nBitFields + nColors * sizeof(RGBQUAD));
if(!pbmi || !pbits){
GlobalUnlock(hMem);
return GenericError;
}
Bitmap Bmp1 (pbmi, pbits);
Status st;
int wdh = Bmp1.GetWidth();
int hgt = Bmp1.GetHeight();
PixelFormat format = Bmp1.GetPixelFormat();
if(Bmp2){
delete Bmp2;
Bmp2 = NULL;
}
Bmp2 = new Bitmap(wdh, hgt, format);
st = Bmp2->GetLastStatus();
if(st == Ok){
// パレット
if(format & PixelFormatIndexed){
ColorPalette *ppal = NULL;
int p_sz = Bmp1.GetPaletteSize();
ppal = (ColorPalette *) new BYTE [p_sz];
if(ppal){
st = Bmp1.GetPalette(ppal, p_sz);
if(st == Ok){
st = Bmp2->SetPalette(ppal);
}
}
delete [] (LPBYTE) ppal;
ppal = NULL;
}
}
if(_winmajor >= 6 || !(format & PixelFormatIndexed) && format != PixelFormat32bppRGB){
// _winmajor 6 は Windows7。 32bpp は 透明度が含まれる場合があるため。
Graphics gBmp(Bmp2);
gBmp.DrawImage(&Bmp1, 0, 0, wdh, hgt);
}
else{
BitmapData bitmapData;
int bpp = pbmi->bmiHeader.biBitCount;
Rect rect(0, 0, wdh, hgt);
st = Bmp2->LockBits(&rect, ImageLockModeWrite, format, &bitmapData);
if (st == Ok)
{
int y,y2;
LPBYTE pixels = (LPBYTE) bitmapData.Scan0;
int stride = abs(bitmapData.Stride);
if(bpp <= 0 || bpp > 32){
ZeroMemory(pixels, stride * hgt);
}
else{
for(y=0;y<hgt;y++){
if(pbmi->bmiHeader.biHeight >= 0){
y2 = hgt - y - 1;
}
else{
y2 = y;
}
if(bpp >= 8){
memcpy(&pixels[y2 * stride], &pbits[y * stride], wdh * (bpp / 8));
}
else{
memcpy(&pixels[y2 * stride], &pbits[y * stride], wdh / (8 / bpp));
}
}
}
st = Bmp2->UnlockBits(&bitmapData);
}
if(st != Ok){
MessageBox(GetFocus(),"Bmp2 Lock or Unlock Error","Clipboard Error",MB_OK);
if(Bmp2){
delete Bmp2;
Bmp2 = NULL;
}
return st;
}
}
return Ok;
}// Get_ClipBoard_DIB
// クリップボードに画像データを置く
Status Set_ClipBoard_DIB()
{
Status st;
HANDLE hMem = NULL;
BITMAPINFO *pbmi;
BYTE *pbits,*buf;
BitmapData bitmapData;
int wdh = Bmp2->GetWidth();
int hgt = Bmp2->GetHeight();
PixelFormat format = Bmp2->GetPixelFormat();
int bpp = (BYTE)(format >> 8); // カラーデプス
int pbmi_sz = 0;
int pbits_sz= 0; // 画像サイズ
UINT nColors = 0; // パレットの最大色数
UINT nBitFields = 0; // 16-R5G6B5 マスクのサイズ
Rect rect(0, 0, wdh, hgt);
if(bpp <= 8) nColors = 1 << bpp;
if(format == PixelFormat16bppRGB565)
nBitFields = sizeof(DWORD) * 3;
pbmi_sz = sizeof(BITMAPINFOHEADER)+nBitFields+nColors*sizeof(RGBQUAD);
pbmi = (LPBITMAPINFO) new BYTE [pbmi_sz];
ZeroMemory(&pbmi->bmiColors, nBitFields+nColors*sizeof(RGBQUAD));
ZeroMemory(&pbmi->bmiHeader, sizeof(BITMAPINFOHEADER));
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = wdh;
pbmi->bmiHeader.biHeight = hgt;
pbmi->bmiHeader.biBitCount = bpp;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biClrUsed = 0; // 互換性のため
if(format == PixelFormat16bppRGB565)
pbmi->bmiHeader.biCompression = BI_BITFIELDS;
else
pbmi->bmiHeader.biCompression = BI_RGB;
if(format == PixelFormat16bppRGB565){
DWORD mask[3] = {0xF800, 0x07E0, 0x001F};
memcpy(&pbmi->bmiColors, mask, sizeof(mask));
}
else if(bpp <= 8){
int p_sz = Bmp2->GetPaletteSize();
ColorPalette *pal;
pal = (ColorPalette*) new BYTE [p_sz];
st = Bmp2->GetPalette(pal, p_sz);
if(st == Ok){
for(UINT i=0;i<pal->Count;i++){
pbmi->bmiColors[i].rgbRed = (BYTE) (pal->Entries[i] >> 16);
pbmi->bmiColors[i].rgbGreen = (BYTE) (pal->Entries[i] >> 8);
pbmi->bmiColors[i].rgbBlue = (BYTE) pal->Entries[i];
pbmi->bmiColors[i].rgbReserved = 0;
}
}
delete[] (LPBYTE) pal;
pal = NULL;
if(st != Ok){
MessageBox (NULL,"パレットを設定できません",MYWNDTITLE,MB_OK);
delete [] (LPBYTE) pbmi;
pbmi = NULL;
return st;
}
}
st = Bmp2->LockBits(&rect, ImageLockModeRead, format, &bitmapData);
if (st == Ok)
{
BYTE *pixels1;
int x,y,y2;
pixels1 = (LPBYTE) bitmapData.Scan0;
int stride1 = abs(bitmapData.Stride);
pbits_sz = stride1 * hgt * sizeof(BYTE);
pbmi->bmiHeader.biSizeImage = pbits_sz;
pbits = new BYTE [pbits_sz];
for(y=0;y<hgt;y++){
if(bitmapData.Stride < 0){
y2 = y;
}
else{
y2 = hgt - y - 1;
}
if(bpp >= 8){
for(x=0;x<wdh*(bpp/8);x++){
pbits[y*stride1+x] = pixels1[y2*stride1+x];
}
}
else{
for(x=0;x<wdh;x++){
pbits[y*stride1+x/(8/bpp)] = pixels1[y2*stride1+x/(8/bpp)];
}
}
}
st = Bmp2->UnlockBits(&bitmapData);
}
if(st != Ok){
MessageBox (NULL,"Bmp Lock or Unlock Error",MYWNDTITLE,MB_OK);
delete [] (LPBYTE) pbits;
pbits = NULL;
delete [] (LPBYTE) pbmi;
pbmi = NULL;
return st;
}
OpenClipboard(NULL);
hMem = GlobalAlloc(GMEM_MOVEABLE, pbmi_sz + pbits_sz);
buf = (LPBYTE) GlobalLock(hMem);
memcpy(buf, pbmi, pbmi_sz);
memcpy(buf + pbmi_sz, pbits, pbits_sz);
EmptyClipboard ();
SetClipboardData(CF_DIB, hMem);
GlobalUnlock(hMem);
CloseClipboard();
delete [] (LPBYTE) pbits;
pbits = NULL;
delete [] (LPBYTE) pbmi;
pbmi = NULL;
return Ok;
}// Set_ClipBoard_DIB
|