VBAからGDI+を使う資料集
inet上の達人の方々から御教示いただいたコードを少しアレンジさせてもらっています(切り貼りとも言います)。
  1. ホーム
  2. win32sdk
  3. Copyしたセルを小ウィンドウに最前面表示


Excelでコピーしたセルをクリップボード経由で最前面表示する(番外品のカテから移設)

Excelでコピーしたセルを小ウィンドウで最前面表示するツールを作ってみました
Excelからクリップボードにコピーされる多彩な形式の内、emf形式を利用しています
VisualStudio2005のC++で作っていますが、きっとCの機能しか使っていません。
今まではVixの機能を使っていましたが、もっと軽く簡便なものがほしくなったものです。ファイルサイズ10KBと極軽量です。
基本的なWindow生成のスケルトンは「猫でもわかるWindowsプログラミング2版」と作者のサイトの、
ユニコード対応のコードを利用させてもらっています。
※更新機能を削除して、クリップボードにemfが無いときは終了する仕様に変更しました。


//Excelでコピーしたセル範囲を最前面のウィンドウに表示する
#define STRICT
#include <windows.h>
#include "resource.h"
#include <tchar.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
BOOL PlayEnhMetaFileAtOriginalSize( HDC, HENHMETAFILE);

TCHAR szClassName[] = TEXT("clip02");
HENHMETAFILE hEmf;

//ウィンドウクラス
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
                                   LPSTR lpsCmdLine, int nCmdShow)
{
    MSG msg;
    BOOL bRet;
    
    if (!InitApp(hCurInst))
        return FALSE;
    if (!InitInstance(hCurInst, nCmdShow)) 
        return FALSE;
    while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
        if (bRet == -1) {
            break;
        } else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int)msg.wParam;
}
//ウィンドウ・クラスの登録
ATOM InitApp(HINSTANCE hInst)
{
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;       //プロシージャ名
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;//インスタンス
    wc.hIcon = (HICON)LoadImage(NULL,
        MAKEINTRESOURCE(IDI_ICON1), //IDI_APPLICATION
        IMAGE_ICON,
        0,
        0,
        LR_DEFAULTSIZE | LR_SHARED);
    wc.hCursor = (HCURSOR)LoadImage(NULL,
        MAKEINTRESOURCE(IDC_ARROW),
        IMAGE_CURSOR,
        0,
        0,
        LR_DEFAULTSIZE | LR_SHARED);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = TEXT("MYMENU");       //メニュー名
    wc.lpszClassName = (LPCTSTR)szClassName;
    wc.hIconSm = (HICON)LoadImage(NULL,
        MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON,
        0,
        0,
        LR_DEFAULTSIZE | LR_SHARED);
    return (RegisterClassEx(&wc));
}
//ウィンドウの生成
BOOL InitInstance(HINSTANCE hInst, int nCmdShow)
{
    HWND hWnd;
    
    hWnd = CreateWindow(szClassName,
            TEXT("ClipBoardのEMF表示"), //タイトルバーにこの名前が表示されます
            WS_OVERLAPPEDWINDOW, //ウィンドウの種類
            CW_USEDEFAULT,  //X座標
            CW_USEDEFAULT,  //Y座標
            200,    //幅 CW_USEDEFAULT
            100,    //高さ CW_USEDEFAULT
            NULL, //親ウィンドウのハンドル、親を作るときはNULL
            NULL, //メニューハンドル、クラスメニューを使うときはNULL
            hInst, //インスタンスハンドル
            NULL);
    if (!hWnd)
        return FALSE;
    //
    SetWindowPos( hWnd, HWND_TOPMOST, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE );
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}
//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    HDC hdc;
    PAINTSTRUCT ps;

    switch (msg) {
    case WM_CREATE:
        ENHMETAHEADER   emh;
        HDC hDCdesktop;
        RECT rect_win;
        RECT rect_cli;
        float                   PixelsX, PixelsY;
        int wwidth, wheight;
        int flamewx, flamewy;
        
        if (IsClipboardFormatAvailable(CF_ENHMETAFILE)){
            OpenClipboard(hWnd);
            hEmf = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE);
            // Get the header from the enhanced metafile
            ZeroMemory( &emh, sizeof(ENHMETAHEADER) );
            emh.nSize = sizeof(ENHMETAHEADER);
            GetEnhMetaFileHeader( hEmf, sizeof( ENHMETAHEADER ), &emh );
			hDCdesktop=GetDC(hWnd);
            PixelsX = (float)GetDeviceCaps( hDCdesktop, LOGPIXELSX );
            PixelsY = (float)GetDeviceCaps( hDCdesktop, LOGPIXELSY );
            wwidth = (int)((float)(emh.rclFrame.right - emh.rclFrame.left)  / (100.0f * 25.4f / PixelsX));
            wheight = (int)((float)(emh.rclFrame.bottom - emh.rclFrame.top) / (100.0f * 25.4f / PixelsY));
            ReleaseDC(hWnd , hDCdesktop);
            GetWindowRect(hWnd, &rect_win);
            GetClientRect(hWnd, &rect_cli);
            flamewx = (rect_win.right - rect_win.left) - (rect_cli.right - rect_cli.left );
            flamewy = (rect_win.bottom - rect_win.top ) - (rect_cli.bottom - rect_cli.top );
            MoveWindow(hWnd, rect_win.left , rect_win.top , flamewx + wwidth, flamewy + wheight, 1);
            CloseClipboard();
		} else {
			MessageBox(hWnd,TEXT("クリップボードにEMFがありません"),TEXT("message"),MB_OK);
			PostQuitMessage(0);
		}
        break;                  
    case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		PlayEnhMetaFileAtOriginalSize( hdc, hEmf );
		EndPaint(hWnd, &ps);
    break;
        case WM_COMMAND:
            switch (LOWORD(wp)) {
				case IDM_END:
					SendMessage(hWnd, WM_CLOSE, 0, 0);
					break;
                }
                break;
        case WM_CLOSE:
                DestroyWindow(hWnd);
                break;
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                    return (DefWindowProc(hWnd, msg, wp, lp));
    }
    return 0;
}

// ==========================================================================
/*
  FUNCTION   : PlayEnhMetaFileAtOriginalSize
  Copyright Microsoftです。OpenGL対応は割愛させていただきました。
*/
BOOL PlayEnhMetaFileAtOriginalSize( HDC hDC, HENHMETAFILE hMeta )
{
        BOOL                    bFlag;
        ENHMETAHEADER   emh;
        RECT                    Rect;
        float                   PixelsX, PixelsY, MMX, MMY;
        // Do we have a metafile? If not, consider it drawn!
        if( hMeta == NULL )
                return TRUE;
        // Get the header from the enhanced metafile
        ZeroMemory( &emh, sizeof(ENHMETAHEADER) );
        emh.nSize = sizeof(ENHMETAHEADER);
        if( GetEnhMetaFileHeader( hMeta, sizeof( ENHMETAHEADER ), &emh ) == 0 )
                return FALSE;
        // Get the characteristics of the output device
        PixelsX = (float)GetDeviceCaps( hDC, HORZRES );
        PixelsY = (float)GetDeviceCaps( hDC, VERTRES );
        MMX = (float)GetDeviceCaps( hDC, HORZSIZE );
        MMY = (float)GetDeviceCaps( hDC, VERTSIZE );
        // Calculate the rect in which to draw the metafile based on the
        // intended size and the current output device resolution
        // Remember that the intended size is given in 0.01mm units, so
        // convert those to device units on the target device
        Rect.top = (int)((float)(emh.rclFrame.top) * PixelsY / (MMY*100.0f));
        Rect.left = (int)((float)(emh.rclFrame.left) * PixelsX / (MMX*100.0f));
        Rect.right = (int)((float)(emh.rclFrame.right) * PixelsX / (MMX*100.0f));
        Rect.bottom = (int)((float)(emh.rclFrame.bottom) * PixelsY / (MMY*100.0f));
        // Play the metafile in that rectangle
        bFlag = PlayEnhMetaFile( hDC, hMeta, &Rect );
        return bFlag;
}
// End PlayEnhMetaFileAtOriginalSize
// ==========================================================================