[VB6][GDI+]表示サイズが大きいときに出るエラーの条件・回避法は?


A.K  2008-02-01 11:15:52  No: 100202

GdipCreateFromHDCを使用した際、
「480  AutoRedraw イメージを作成できません。」
というエラーが発生して、イメージの描画が行えない

こんばんは。
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200709/07090026.txt
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200710/07100010.txt
で質問させていただいた者です。

GDI+を使って、イメージファイルを開くユーザーコントロールを作成しています。
今回は、完成したユーザーコントロールの動作テストを行っていたときに、不可解なエラーが出てしまい
どうにも進めなくなったので  お知恵を拝借したく書き込みさせていただきました。

イメージを開いた時に、ファイルの描画サイズ(容量ではなくサイズ)が一定以上のものだと
Err.Number : 480
Err.Description : AutoRedraw イメージを作成できません。
というエラーが発生して、描画処理が失敗します。
サイズが一定以下で普通に開けるものでも、描画時サイズを大きくして(拡大して)いくと、同様のエラーが出ます。

以下に、関係あると思われる部分のソースを挙げます

環境:
XP  VB6SP6
GDI+ Type Library 1.31使用
gtypGPInput.GdiplusVersion = 1  で動作

描画の流れ
GDIスタート(GdiplusStartup)
ファイルイメージ取得(魔界弁士ロジック
イメージサイズ取得(GdipGetImageHeight、GdipGetImageWidth)
拡大時サイズ取得・変数に格納
コンテナオブジェクト(ピクチャボックス:UCImage)のサイズ変更
イメージ描画

イメージ描画の関数
Private Function UCSubDrawImage(Img As Long, ByVal lngImgWidth As Long, ByVal lngImgHeight As Long, _
                                    Optional ByVal X As Long = 0, Optional ByVal Y As Long = 0, Optional Clear As Boolean = True) As GpStatus
'イメージ実描画  開始位置を指定することで二つのファイルを描画できる
    Dim Graphics As Long
    Dim ret As GpStatus
    
On Error GoTo UCSubDrawImageErr:
    
    UCSubDrawImage = Ok
    If Clear Then UCImage.Picture = LoadPicture("")   '画面初期化
    'PictureBoxのhDCからGraphicsオブジェクトの生成
    ret = GdipCreateFromHDC(UCImage.hDC, Graphics)  '*******←エラー発生
    If (ret <> Ok) Then
        UCSubDrawImage = ret
        Err.Raise 1001, "GdipCreateFromHDC", "Graphicsを作成できません"
        Exit Function
    End If

    ret = GdipSetInterpolationMode(Graphics, InterpolationModeDefault) 
    
  '描画
    ret = GdipDrawImageRectI(Graphics, Img, X, Y, lngImgWidth, lngImgHeight)
    If (ret <> GdiPlus.GpStatus.Ok) Then
        UCSubDrawImage = ret
        Err.Raise 1002, "GdipDrawImageRectI", "描画できません"
        Exit Function
    End If

    '生成したオブジェクトの解放
    ret = GdipDeleteGraphics(Graphics)
    '表示画像の定着
    UCImage.Refresh
    
    Exit Function
UCSubDrawImageErr:
    '最大サイズをオーバーした場合?
    UCSubDrawImage = ValueOverflow
    Debug.Print Err.Number & "  " & Err.Description
    'Call MsgBox(Err.Description & vbCrLf & lngImgHeight & " : " & lngImgWidth, , "UCSubDrawImage")
End Function

GdipCreateFromHDCは、戻り値を返さずにエラーを出すため、その下の
If (ret <> Ok) Then  に処理が渡りません。
やむなくOn Errorで処理を飛ばして、ValueOverflowを返すようにしています。

GdipCreateFromHDC  の時点でエラーが出るということは、コンテナオブジェクト(UCImage)のサイズが関係しているのかと思いますが、具体的にどんなサイズの時にエラーが出るのかがよくわかりません。
例えばこのエラーがGDI+の限界なのだとすれば、最大サイズの制限を設けてエラーを回避することもできますが、
そのサイズがどうなっているのかもよく分からない状態です。

実際に調べてみた所、
縦6800  横6800でエラー
縦6700  横6700 は正常

縦2820  横169200でエラー
縦2810  横168600は正常

という結果でした。
最初は縦*横のサイズで上限値が決まるのかと思っていましたが、この結果ですと
6800*6800  =46240000
2820*169200  =477144000
で、総ピクセル数には10倍近い差がでています。

手元のファイル描画ソフト「Susie」では、一辺32767ピクセルくらいまでは拡大できるようなので
それくらいで制御しようと考えていたのですが…  一辺6800ではいかにも不満です。
GDI+の限界であるなら仕方ないですけど  多分そんなことはないだろうと思うので
何か有効な対策をご存じの方がおりましたら(エラーが出る際の条件でも)、ご教授頂ければ幸いです。
それではよろしくお願いします。


K.J.K.  2008-02-07 01:49:12  No: 100203

これはGDI+とは関係のないVB6側の制限に引っかかっているからでしょう。
AutoRedrawプロパティをTrueにした場合、その大きさには「おそらく16bit OS
時代からの仕様」を引きずった制限があります。

で、描画はAutoRedraw=Trueに頼らないで行うのが無難かと。


A.K  2008-02-07 02:50:40  No: 100204

K.J.K様
ご回答ありがとうございます。
VB6の制限となると回避のしようがないですね…
AutoRedrawを使用した描画を行っているのは、画像がフォームよりも大きかった場合に、ドラッグやスクロールバーで画像をスクロールさせるのを想定しているからなのですが(後は単純に楽だからですが)
これを使わずに描画を行うとなると  根本からの大改造が必要ですね…(涙

コンテナにピクチャボックスを使わなければいいのでしょうか…
またいろいろ調べてみます。

〜以下蛇足〜
今日、前回の書き込みを読み返してみたら  個人的なメモ書きがそのまま表示されていて血の気が引きました(修正できません
今度はもう少し落ち着いて書き込みします m(_ _)m


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加