クリップボードから画像データを取得して表示すると反転する

[戻る]
あお 2004/07/09(金) 09:39:35
いつもお世話になっています。

クリップボードがから画像データを取り出して、
取り出した画像データをメタファイルに表示するプログラムを
作成しています。
以下のコードを組んだのですが表示される画像が上下反転して
表示されます。
反転しないようにしたいのですがどうしたらよいのでしょうか?
おわかりになる方がいらっしゃいましたら教えてください。

-----------ソース----------------
// クリップボードから画像データを取得
// 画像データがクリップボードにあるとき
if (IsClipboardFormatAvailable(CF_BITMAP)){
    OpenClipboard(NULL); // クリップボードを開く
    hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP); // 画像データの取得
    // hDCは作成したいメタファイルのデバイスコンテキストのハンドル
    memhDC = CreateCompatibleDC(hDC); // メモリデバイスコンテキストの作成
    SelectObject(memhDC, hBitmap);
    // グラフィックオブジェクトの情報を取得
    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
    // 画像の転送
    // x,yは転送先の位置。描画したい位置の値が入っていることは確認済
    BitBlt(hDC, x, y, 
    bm.bmWidth, bm.bmHeight, memhDC, 0, 0, SRCCOPY);
    DeleteDC(memhDC); // デバイスコンテキストを削除
    CloseClipboard(); // クリップボードを閉じる
}
-------------ここまで----------------

このときhDCのモードをSetMapMode(hDC, MM_LOMETRIC);で指定してあります。

開発環境 Windows2000・VS6SP5・Win32 Dynamic-Link Libraryで作成

シャノン 2004/07/09(金) 11:28:36
ご自分で書いてらっしゃるじゃないですか。
> SetMapMode(hDC, MM_LOMETRIC);
って。

これが何かわからずにやってるわけじゃないですよね?
MSDN には
> x の正の値は右方向、y の正の値は上方向を指します。
とあります。
つまり、座標原点が左下なんですよ。

対して、SetMapMode をやらないと、既定のマッピングモードは MM_TEXT 。
これは
> x 座標の正方向は右、y 座標の正方向は下になります。 
座標原点は左上です。

これを考慮してやらないと、反転しちゃいます

あお 2004/07/09(金) 13:06:13
シャノン様 返信ありがとうございます。

おっしゃる通りSetMapMode(hDC, MM_LOMETRIC);のせい
だとはわかるのですが、どのよう考慮してやれば
反転せずにすむかがわかりません。

BitBltでhDCに転送する際に何か設定があるのかとも
思ったんですが、見つけることはできませんでした。
hBitmapの内容を変えてあげないといけないのでしょうか?

PATIO 2004/07/09(金) 13:18:36
なぜ、MM_LOMETRICにしないといけないのかという説明が無いので
コメントしにくいのですが、MM_LOMETRICにする理由が無いのであれば、
MM_TEXT(つまりSetMapModeを変えない)で描画すれば良いと思うのですが。

あお 2004/07/09(金) 13:50:46
PATIO様返信ありがとうございます。

ある画像データ(線のデータや円のデータも含む)からメタファイル
を作成しているのですが、この画像データがmm単位で存在しています。
Xmm×Ymmの用紙である点から5mmの線を引けというようなデータです。
画像データの位置や長さを一致させるためと計算を楽にするために、
設定をMM_LOMETRICに変更しています。
MM_LOMETRICを設定しない方法は使えません。

MM_LOMETRICの設定のまま反転をどうにかしたいと思っているのですが
おわかりになられる方がいらっしゃいましたら教えてください。

PATIO 2004/07/09(金) 15:16:43
MM_LOMETRICでどうしてもやりたいのであれば、
BitBltでは駄目でしょう。
他の関数を探してみた方が良いと思います。

メタファイルをMM_LOMETRICで作成しているからと言う理屈はわかるんですが、
ビットマップが絡むとなると話は別な気もしますね。
座標変換の計算がそこまで複雑な物だとは思えませんし、
むしろ、メタファイルの方をMM_TEXTにあわせて作成した方が
他のGDIオブジェクトとの親和性は良いと思います。
なにせ、デフォルトのモードがMM_TEXTであると言うのは、
それば一番自然に描画できるモードだからな訳で、
GDIの各関数もその状態で描画するのが一番効率よく動くように
なっていると思いますので。

シャノン 2004/07/09(金) 15:49:43
こんな感じ?

if( IsClipboardFormatAvailable( CF_BITMAP ) )
{
    OpenClipboard( NULL );
    hBitmap = ( HBITMAP )GetClipboardData( CF_BITMAP );

    memhDC = CreateCompatibleDC( hDC );
    SelectObject( memhDC, hBitmap );

    GetObject( hBitmap, sizeof( BITMAP ), &bm );

    // 座標変換
    POINT pt = { bm.bmWidth, bm.bmHeight };
    DPtoLP( hDC, &pt, 1 );

    // 鏡像描画
    StretchBlt( hDC, x, y, pt.x, pt.y,
        memhDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY );

    DeleteDC( memhDC );
    CloseClipboard();
}

あお 2004/07/09(金) 16:12:48
PATIO様、シャノン様返信ありがとうございます。

できました。

    // 座標変換
    POINT pt = { bm.bmWidth, bm.bmHeight };
    DPtoLP( hDC, &pt, 1 );

    // 鏡像描画
    StretchBlt( hDC, x, y, pt.x, pt.y,
        memhdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY );

と返信の通りに変更することで表示できました。
座標を変換することで対応するんですね。
ありがとうございます。

あお 2004/07/09(金) 16:13:11
[[解決]]
すみません。解決で。チェック付け忘れたので

古いスレッドには追加発言できません。