らんたいむ ますこっと スクリプト Part 2


2回目は、ウインドウをくりぬくための準備。


指定したビットマップのうちの、指定した範囲からウインドウリージョンを取得するメソッドです。
なお、ウインドウハンドルを取得するメソッドと同様、実際には専用のクラス内で定義しておりますが、その部分は省略しております。

def createRgn(bitmap, x, y, width, height)
  rgn = createRectRgn(0, 0, width, height)

  for yi in 0 ... height
    x0 = -1
    for xi in 0 ... width
      c = bitmap.get_pixel(x + xi, y + yi)
      a = c.alpha
      if x0 >= 0
        if a >= 255
          diffRgn(rgn, x0, yi, xi, yi + 1)
          x0 = -1
        end
      else
        if a < 255
          x0 = xi
        end
      end
    end
    if x0 >= 0
      diffRgn(rgn, x0, yi, width, yi + 1)
    end
  end

  return rgn
end


内部で使っている、ウインドウリージョンからある範囲を外すメソッドです。

def diffRgn(rgn, left, top, right, bottom)
  diff_rgn = createRectRgn(left, top, right, bottom)
  combineRgn(rgn, rgn, diff_rgn, RGN_DIFF)
  deleteObject(diff_rgn)
end


使っているWindows APIの定義はコレ。RGN_DIFFとかの定数は適当に調べて使って下さい。

def createRectRgn(left, top, right, bottom)
  api = Win32API.new("gdi32.dll", "CreateRectRgn", "l l l l", "l")
  return api.call(left, top, right, bottom)
end

def combineRgn(dest, src1, src2, mode)
  api = Win32API.new("gdi32.dll", "CombineRgn", "l l l l", "l")
  return api.call(dest, src1, src2, mode)
end

def deleteObject(obj)
  api = Win32API.new("gdi32.dll", "DeleteObject", "l", "l")
  return api.call(obj)
end


私も時々掲示板に出没する、マルペケつくろーどっとコムさん「ビットマップでリージョンを作成する」の記事を参考にしています。
ほとんどそのままですが、画像の一部分のみからリージョンを作成するようにしたり、1ドットずつを処理していたところを、1行分でまとめられるだけ処理するようにしたりしています。
一部分からリージョンを作れるようにしたのは、ランタイムの画像からそのままリージョンを作りたかったら。一々細切れにしてもいいんだけどね。
1行分まとめては、多分、その方が効率がいい気がしたから。まぁ、誤差の範囲な気がしますし、大差はないでしょうけど。そのまま、っていうのが気に入らないので、少しだけど改良したのです。


次回は、このリージョンを使ってあれこれして終わり、の予定です。