Window2.SetTabPicture and transparency once again
-
Tuesday, February 12, 2008 4:52 PM
Hello everybody,
I am just writing an addin and I wanted to set custom tab picture for the addin window. But it seems, that something has been changed (again) in RTM version comparing to Beta2. I cannot get the transparency for my picture. I tried different colors: pure green, almost green, pure magenta, almost magenta, white, black... I tried to load both 16 colors and 24bit bitmaps. The result is everytime the same - no transparency. I tried the addin under VS 2005 and had no problem - pure magenta worked perfectly, so the problm is not with the addin but with the color self.
Any ideas?
All Replies
-
Tuesday, February 12, 2008 5:23 PMModerator
See:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1871235&SiteID=1
Let us know if that does not help.
-
Tuesday, February 12, 2008 9:02 PM
Hi Carlos,
sorry, but your solution with a TrueColor 24-bits Color bitmap, with a background color 0,254,0 (green) will not work in Visual Studio 2008.
OK, here is my working way:
I have created a bitmap in TrueColor 24-bits (16x16 / 0,254,0 background color) with paint.net.
Then I have added my custom bitmap to my add-in resource file, with the resource editor in Visual Studio 2008. The name of the bitmap in the resource editor is MyToolWindowTabPicture.
Next, I added a reference to the official microsoft dll "Microsoft.VisualBasic.Compatibillity. From this dll, I use the class Support and the static method ImageToIPicture. This method needs an image as method argument. OK, here is a sample code snipped:
Code SnippetWindows2 vsWindows = applicationObject.Windows as Windows2;
Window2 myToolWindow = vsWindows.CreateToolWindow2(...) as Window2;
Image tabPicture = Properties.Resources.MyToolWindowTabPicture;
myToolWindow.AddTabPicture(Support.ImageTiIPicture(tabPicture));
OK, for Visual Studio 2005 (with 254,0,254) this works fine. In Visual Studio 2008, the background from tool window tab picture is always green end never transparent.
I think this is a bug of the release version from visual studio 2008. In the RC of Visual Studio 2008 has my solution has worked.
I would be glad to know, if you have found out a different solution that works.
Greetings from Germany
TOM (Thomas Mueller)
-
Tuesday, February 12, 2008 9:59 PMTom has already answered for me and I can only confirm - I tried different colors and configurations, but none seems to be the right one. I know the thread you linked me to - it was one of my first attempts
.
-
Wednesday, February 13, 2008 12:26 PMModerator
Well, it works with 16x16 24-bit bitmaps and RGB=0,254,0 as background in VS 2008 RTM because I have tested it with my own MZ-Tools add-in (you can download a demo version if you want). So, you must be doing something differently:
- First, ensure that the bitmap is TrueColor 24-bit and not TrueColor 32-bit because both are TrueColor but different formats.
- Second, I am using the builtin image editor of VS, with the menu Image, Adjust Colors... to define the RGB=0,254,0 almost green color.
- Finally, I use a C++ resource DLL and the the code (VB.NET) that I use is the following (notice that I use RGB=0,254,0 in all cases because my resource dll is the same for all IDEs and I remap at runtime to magenta RGB=255,0,255 only in VS 2005):
iSatelliteDLLHandle = LoadLibrary(sSatelliteDLLPath)
#If VS_7_0 Or VS_7_1 Then
objPicture = GetTransparentIPictureDispFromDLLResource(iSatelliteDLLHandle, iImageIndex)
objWindow.SetTabPicture(objPicture)
#ElseIf VS_8_0 Then
objBitmap = GetTransparentBitmapUsingMagentaFromDLLResource(iSatelliteDLLHandle, iImageIndex)
objWindow.SetTabPicture(objBitmap.GetHbitmap)
#Else
' Using the technique of VS 2005 causes an exception (argument outside of expected range) so we use the VS.NET 2002/2003 approach again
objPicture = GetTransparentIPictureDispFromDLLResource(iSatelliteDLLHandle, iImageIndex)
objWindow.SetTabPicture(objPicture)#End If
objWindow.Visible = True
...
FreeLibrary(iSatelliteDLLHandle)
...
Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" (ByVal lpFileName As String) As IntPtr
Private Declare Function FreeLibrary Lib "kernel32.dll" (ByVal iHandle As IntPtr) As Integer<DllImport("user32.dll", EntryPoint:="LoadBitmapA")> _
Private Shared Function LoadBitmap(ByVal hInstance As IntPtr, ByVal iBitmapIndex As Integer) As Integer
End Function<DllImport("oleaut32.dll", CharSet:=CharSet.Unicode, PreserveSig:=True, EntryPoint:="OleLoadPictureFile")> _
Private Shared Sub OleLoadPictureFile(ByVal varFileName As Object, <MarshalAs(UnmanagedType.IDispatch)> ByRef lpIPictureDisp As Object)
End Sub<DllImport("olepro32.dll", EntryPoint:="OleCreatePictureIndirect")> _
Private Shared Function OleCreatePictureIndirect(ByRef pPictDesc As PICTDESC, ByRef riid As Guid, ByVal fOwn As Integer, <MarshalAs(UnmanagedType.IDispatch)> ByRef ppvObj As Object) As Integer
End FunctionPrivate Structure PICTDESC
Friend SizeOfStruct As Integer
Friend PicType As Integer
Friend Hbitmap As IntPtr
Friend Hpal As IntPtr
Friend Padding As IntegerFriend Sub New(ByVal hBmp As IntPtr)
Me.SizeOfStruct = Marshal.SizeOf(Me.GetType)
Me.PicType = 1
Me.Hbitmap = hBmp
Me.Hpal = IntPtr.Zero
Me.Padding = 0
End SubEnd Structure
Friend Shared Function GetTransparentIPictureDispFromDLLResource(ByVal iDLLHandle As IntPtr, ByVal iResourceIndex As Integer) As stdole.IPictureDisp
Dim iBitmapHandle As Integer
Dim objPicture As stdole.IPictureDispIf Not iDLLHandle.Equals(IntPtr.Zero) Then
iBitmapHandle = LoadBitmap(iDLLHandle, iResourceIndex)
If iBitmapHandle <> 0 Then
objPicture = GetTransparentIPictureDispFromBitmapHandle(New IntPtr(iBitmapHandle))
End IfEnd If
Return objPicture
End Function
Friend Shared Function GetTransparentIPictureDispFromBitmapHandle(ByVal hIntPtr As IntPtr) As stdole.IPictureDisp
Dim objPicture As Object
Dim objGuid As New Guid("00020400-0000-0000-C000-000000000046")
Dim iResult As Integer
Dim tPICTDESC As New PICTDESC(hIntPtr)iResult = OleCreatePictureIndirect(tPICTDESC, objGuid, 1, objPicture)
Return CType(objPicture, stdole.IPictureDisp)
End Function
Friend Shared Function GetTransparentBitmapUsingMagentaFromDLLResource(ByVal iDLLHandle As IntPtr, ByVal iResourceIndex As Integer) As Bitmap
Dim iBitmapHandle As Integer
Dim objInputBitmap As Bitmap
Dim objOutputBitmap As Bitmap
Dim objGreenColor As Color = Color.FromArgb(0, 254, 0)
Dim objMagentaColor As Color = Color.FromArgb(255, 0, 255)If Not iDLLHandle.Equals(IntPtr.Zero) Then
iBitmapHandle = LoadBitmap(iDLLHandle, iResourceIndex)
If iBitmapHandle <> 0 Then
objInputBitmap = Bitmap.FromHbitmap(New IntPtr(iBitmapHandle))
objOutputBitmap = RemapBitmapColor(objInputBitmap, objGreenColor, objMagentaColor)
objInputBitmap.Dispose()
End If
End If
Return objOutputBitmap
End Function
Friend Shared Function RemapBitmapColor(ByVal objInputBitmap As Bitmap, ByVal objOldColor As Color, ByVal objNewColor As Color) As Bitmap
Dim objGraphics As Graphics
Dim objColorMap As Imaging.ColorMap
Dim objColorMapTable(0) As Imaging.ColorMap
Dim objImageAttributes As Imaging.ImageAttributes
Dim objRectangle As Rectangle
Dim objOutputBitmap As Bitmap
Dim iWidth As Integer
Dim iHeight As Integer
' Get dimensions
iWidth = objInputBitmap.Width
iHeight = objInputBitmap.Height' Create a the new bitmap
' Important: we must use 24bpp pixel format.
' If we use 32bpp pixel format, it does not work on graphic cards drivers
' set to 32 bpp (curiously it would work with 16 bpp, for example)
objOutputBitmap = New Bitmap(iWidth, iHeight, Drawing.Imaging.PixelFormat.Format24bppRgb)' Get the graphics object
objGraphics = Graphics.FromImage(objOutputBitmap)' Create the table to remap the color
objColorMap = New Imaging.ColorMap()
objColorMap.OldColor = objOldColor
objColorMap.NewColor = objNewColor
objColorMapTable(0) = objColorMap' Create the image attributes and set the table to remap the color
objImageAttributes = New Imaging.ImageAttributes()
objImageAttributes.SetRemapTable(objColorMapTable, Drawing.Imaging.ColorAdjustType.Bitmap)' Draw the image in the output with the new attributes (remaped color)
objRectangle = New Rectangle(0, 0, iWidth, iHeight)
objGraphics.DrawImage(objInputBitmap, objRectangle, 0, 0, iWidth, iHeight, GraphicsUnit.Pixel, objImageAttributes)
objGraphics.Dispose()objInputBitmap.Dispose()
Return objOutputBitmap
End Function
HTH,
-
Wednesday, February 13, 2008 2:55 PM
I haven't tried to use satelite assembly technique yet.
I have tested following code under VS 2005 and it worked:
Code Snippetwnd = windows.CreateToolWindow2(...);
...
Bitmap img = Properties.Resources.MyTabPic;
stdole.IPicture tabPic = Support.ImageToIPicture(img) as stdole.IPicture;
wnd.SetTabPicture(tabPic);
wnd.Visible = true;
To be honest I didn't expect a step back - that I will have to use the satellite assemblies to show custom pictures in my addin.
Besides, look what Tom has written: it has functioned up to RC version. So I find it as a bug. Is there really no other way?
-
Tuesday, April 15, 2008 9:31 AM
I am reanimating this thread to announce that I have finally found a solution of this problem. And it seems to be a step forward instead of a step back.
The simplest solutions are the least obvious ones, but the simplest possible solution works:
Code Snippetwnd = windows.CreateToolWindow2(...);
...
Bitmap img = Properties.Resources.MyTabPic;
img.MakeTransparent(imageTransparencyColor);
stdole.IPicture tabPic = Support.ImageToIPicture(img) as stdole.IPicture;
wnd.SetTabPicture(tabPic);
wnd.Visible = true;
I didn't expect it to be so simple...

