none
Window2.SetTabPicture and transparency once again

    Question

  •  

    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?

    Tuesday, February 12, 2008 4:52 PM

Answers

  • 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 Snippet

    wnd = 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...

    Tuesday, April 15, 2008 9:31 AM
  • Tuesday, February 12, 2008 5:23 PM

All replies

  • Tuesday, February 12, 2008 5:23 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 Snippet

    Windows2 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)

    www.tom-mue.de

    Tuesday, February 12, 2008 9:02 PM
  • Tom 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 Sad.

     

    Tuesday, February 12, 2008 9:59 PM
  • 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 Function

     

       Private Structure PICTDESC
          Friend SizeOfStruct As Integer
          Friend PicType As Integer
          Friend Hbitmap As IntPtr
          Friend Hpal As IntPtr
          Friend Padding As Integer

          Friend 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 Sub

       End Structure

     

       Friend Shared Function GetTransparentIPictureDispFromDLLResource(ByVal iDLLHandle As IntPtr, ByVal iResourceIndex As Integer) As stdole.IPictureDisp

          Dim iBitmapHandle As Integer
          Dim objPicture As stdole.IPictureDisp

          If Not iDLLHandle.Equals(IntPtr.Zero) Then

             iBitmapHandle = LoadBitmap(iDLLHandle, iResourceIndex)
             If iBitmapHandle <> 0 Then
                objPicture = GetTransparentIPictureDispFromBitmapHandle(New IntPtr(iBitmapHandle))
             End If

          End 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 12:26 PM
  • I haven't tried to use satelite assembly technique yet.

    I have tested following code under VS 2005 and it worked:

     

    Code Snippet

    wnd = 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?

     

     

    Wednesday, February 13, 2008 2:55 PM
  • 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 Snippet

    wnd = 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...

    Tuesday, April 15, 2008 9:31 AM