VB6で作成したOCXをVS2005で使用したいのですが、
VS2005上でアイコンイメージを読み込むと
透過色が紺色になって透過しません。
どうすれば透過色を使用したアイコンを描画できる
OCXを作成できるのでしょうか。
OCXのUserControl上にImageコントロールがあり、
Pictureプロパティを外だしにしてイメージを読み込んでいます。
よろしくお願いします。
> どうすれば透過色を使用したアイコンを描画できる
> OCXを作成できるのでしょうか。
VB6 ヘルプでいうところの「ShapeLabel コントロール」サンプルは、
VB2005 上でも、背景が透過しますよね?
VB6 ヘルプの下記の項を参照してみてください。
[Visual Basic ドキュメント]
└[Visual Basic の使用方法]
└[コンポーネント ツール ガイド]
└[ActiveX コンポーネントの作成方法]
└[ActiveX コントロールの作成技術]
└[Visual Basic ActiveX コントロールの機能]
└[コントロールの透明な背景の設定]
回答ありがとうございます。
> VB2005 上でも、背景が透過しますよね?
これは、コントロール自体のリージョンのようなものでしょうか。
コントロール自体の透過ではなく、Imageコントロールが読み込んだ
アイコンファイルの透過色の透過です。
問題を具体的な例で挙げますと…
1.VB6でActiveXコントロールのプロジェクトを作成する。
2.UserControlの背景色を(透過したかわかるように)赤にする。
3.ImageコントロールをUserControlにのせる
4.ImageコントロールのPictureプロパティを
作成したActiveXコントロールのプロパティとして外にだす。
このようにして作成したActiveXコントロールをフォームに貼り付け
Pictureプロパティにアイコンファイルを指定します。
VB6では読み込んだアイコンファイルの透過色は透過して
Imageコントロールの下のUserControlの背景色が見えます。
VS2005では透過色が透過しません。紺色になってしまいます。
あぁ、そういう事ですか。
.NET から COM へのやりとりの際に、どうやらアイコンが
ビットマップに変換されてしまっているようですね。
img = Image.FromFile(strFilePath)
If img.RawFormat.Guid = Imaging.ImageFormat.Icon.Guid Then
MsgBox("これはアイコンです")
End If
AxSampleControl1.Picture = img
img = AxSampleControl1.Picture
If img.RawFormat.Guid = Imaging.ImageFormat.MemoryBmp.Guid Then
MsgBox("これはメモリビットマップです")
End If
VB6 の場合、 Form.Icon も Form.Picture も「Picture型」ですが、
.NET では、Form.Icon は「Icon 型」、Form.BackgroundImage は「Image 型」ですね。
しかも .NET の Icon クラスは、Image クラスを継承していません。
ところが、Picture 型をそのまま公開した場合、Image 型にマッピングされます。
理由はよくわかりませんが、このあたりの事情が絡んでいるのでしょう。
===================
で。対応策としては、VB6 側で「System.Drawing.Icon 型を渡すためのメンバ」を、
別途用意することなのでしょうけれども……それは難しそうなので、
(案1) アンマネージの Picture オブジェクトのままでやりとりする。
(案2) ファイル名またはバイナリを渡すようにして、VB6 側で Picture を生成する。
といったところで如何でしょう。これなら、Icon の背景もきちんと透過するかと。
とりあえず、案1 の実装例を。
------《VB6》-------
Option Explicit
Public Property Get Picture() As Picture
Set Picture = UserControl.Picture
End Property
Public Property Set Picture(ByVal New_Picture As Picture)
Set UserControl.Picture = New_Picture
PropertyChanged "Picture"
End Property
Public Property Get AxPicture() As Object
Set AxPicture = Me.Picture
End Property
Public Property Set AxPicture(ByVal New_AxPicture As Object)
Set Me.Picture = New_AxPicture
End Property
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
Set Picture = PropBag.ReadProperty("Picture", Nothing)
End Sub
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
Call PropBag.WriteProperty("Picture", Picture, Nothing)
End Sub
------ 《VB2005》 -------
Const vbPicTypeBitmap As Integer = 1
Const vbPicTypeIcon As Integer = 3
Dim oIcon As New Icon(strFilePath)
Dim inPic As Object, outPic As Object
inPic = Microsoft.VisualBasic.Compatibility.VB6.Support.IconToIPicture(oIcon)
If inPic.Type = vbPicTypeIcon Then
MsgBox("これはアイコン")
End If
AxSampleControl1.AxPicture = inPic
' Icon のまま保持されているか確認
outPic = AxSampleControl1.AxPicture
If outPic.Type = vbPicTypeBitmap Then
MsgBox("これはビットマップ")
ElseIf outPic.Type = vbPicTypeIcon Then
MsgBox("これはアイコン")
End If
おっとっと、VB6 側の変更は一切不要でした。
.NET 側の処理を変更してやるだけで対応できそうです。
《修正前》
AxSampleControl1.Picture = Image.FromFile(strFilePath)
《修正後》
AxSampleControl1.GetOcx().Picture = Microsoft.VisualBasic.Compatibility.VB6.Support.IconToIPicture(New System.Drawing.Icon(strFilePath))
# 問題があるのは、VS が自動生成する「AxInterop.SampleProject.dll」の
# 相互運用アセンブリなので、この DLL を手直しするのも手かも。
ありがとうございました。
VB2005では確認できました。
プロパティウィンドウからでは難しそうですね。
この場での質問でないかもしれませんが、すみません。
C#2005の場合、ビルドでエラーになります。
(object型にPictureプロパティが無いため)
どのようにキャストしたらよいのでしょうか。
> プロパティウィンドウからでは難しそうですね。
AxInterop.SampleProject.dll を修正するか、または、
SampleControl を継承して、Icon プロパティを追加すれば OKOK。
IPicture を公開するレガシーコントロールが他にもあるのなら、
いっそのこと、プロパティ設定用の拡張プロバイダを作ると便利かも。
http://msdn2.microsoft.com/ja-jp/library/d6c1xa43%28VS.80%29.aspx
> C#2005の場合、ビルドでエラーになります。
C# ではレイトバインドをサポートしていないので、System.Reflection で
対応するか……あるいは、適切な型へのキャストが必要でしょうね。
> どのようにキャストしたらよいのでしょうか。
板違いにならないように、VBのコードで説明。
Option Strict On
Imports AxSampleProject, SampleProject, stdole
Imports Microsoft.VisualBasic.Compatibility.VB6
Public Class Form1
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
DirectCast(AxSampleControl1.GetOcx(), _SampleControl).Picture = _
DirectCast(IconToIPicture(Me.Icon), StdPicture)
End Sub
End Class
まずはImageListからアイコンを取り出して
ロード時に設定するようにしました。
とても助かりました。
ありがとうございました。
ツイート | ![]() |