AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

per-pixel alpha blended GUI demo
Goto page 1, 2, 3 ... 11, 12, 13  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
Lexikos



Joined: 17 Oct 2006
Posts: 2605
Location: Australia, Qld

PostPosted: Tue Oct 16, 2007 12:42 pm    Post subject: per-pixel alpha blended GUI demo Reply with quote

tic wrote:
Should really start a new topic, but do you have any idea of how to have an image with transparencies put onto an invisible gui? So the png for example would appear to be its own gui.
So I'm starting a new topic. Razz

For anyone with programming experience, this demonstration is based on one of these articles/demos:
Per Pixel Alpha Blend (C++)
Per Pixel Alpha Blend in C#
(I forget which one.)


A while ago I wrote a test script to demonstrate how to do this from AutoHotkey. It got rather messy, as I tried various things with it. (Various text effects with GDI; messy because GDI doesn't really support alpha-blending.) Here's a cleaned up version - a magnifying glass (just an icon, lol) that can be dragged around the screen:
Quote:

[Edit: see Sean's post with added PNG support via GDI+]
Code:
; REQUIRES WINDOWS 2000 OR LATER

#NoEnv


Gui, -Caption +E0x80000 ; WS_EX_LAYERED

; Prevents later Gui,Show calls from auto-sizing the GUI.
; Center/default positioning doesn't work unless we explicitly
; size the GUI.  :-/  (It will be resized to the size of the icon later.)
Gui, Show, W1 H1 Hide

Gui, +LastFound


if !(h_icon := ExtractIcon("shell32.dll", 23, 48))
    ExitApp

GetIconSize(h_icon, width, height)


; Create a device context compatible with the screen.
if (hdcDest := DllCall("CreateCompatibleDC", "UInt", 0))
{
    ; Create a 32-bit bitmap to draw the icon onto.
    if (h_bm := CreateDIBSection(width, height, 32, hdcDest, pBits))
    {
        ; Select the new bitmap into the device context.
        if (bmOld := GDI_SelectObject(hdcDest, h_bm))
        {
            ; Draw the icon onto the window.
            DllCall("DrawIconEx"
                , "UInt", hdcDest ; hdc (destination device context)
                , "Int" , x+1       ; xLeft
                , "Int" , 0         ; yTop
                , "UInt", h_icon
                , "UInt", width
                , "UInt", height
                , "UInt", 0         ; istepIfAniCur
                , "UInt", 0         ; hbrFlickerFreeDraw = NULL (draw directly into buffer)
                , "UInt", 3)        ; diFlags = DI_NORMAL
           
           
            ; BLENDFUNCTION bf
            VarSetCapacity(bf, 4, 0)
            ;NumPut(0, bf, 0, "UChar") ; BlendOp := AC_SRC_OVER
            ;NumPut(0, bf, 1, "UChar") ; BlendFlags - must be zero
            NumPut(255, bf, 2, "UChar") ; SourceConstantAlpha := 255
            NumPut(1, bf, 3, "UChar") ; AlphaFormat := AC_SRC_ALHPA

           
            VarSetCapacity(size, 8, 0)
            NumPut(width, size, 0)
            NumPut(height, size, 4)
           
            hwnd := WinExist()
           
            DllCall("UpdateLayeredWindow"
                , "uint", hwnd
                , "uint", 0 ; hdcDst
                , "uint", 0 ; pptDst (pointer to new position, or NULL if not changing)
                , "uint", &size ; psize (pointer to new size, or NULL if not changing)
                , "uint", hdcDest ; hdcSrc (defines the layered window)
                , "uint", &ptSrc  ; pptSrc (pointer to location of the layer in the DC)
                , "uint", 0 ; crKey (not used if !(dwFlags&ULW_COLROKEY))
                , "uint", &bf ; pblend
                , "uint", 2) ; dwFlags := ULW_ALPHA (use pblend, not crKey)

            ; Reselect previous object (as per MSDN recommendation.)
            GDI_SelectObject(hdcDest, bmOld)
        }
        ; we no longer need the bitmap! (Windows has created a copy for the layered window)
        DllCall("DeleteObject", "uint", h_bm)
    }
    ; Done using the device context.
    DllCall("DeleteDC", "UInt", hdcDest)
}

OnMessage(0x201, "WM_LBUTTONDOWN")

Gui, Show
return

GuiClose:
GuiEscape:
ExitApp

; Allow click-drag to move the window.
WM_LBUTTONDOWN() {
    if (A_Gui) {
        Gui, +LastFound
        PostMessage, 0xA1, 2 ; WM_NCLBUTTONDOWN
    }
}


GDI_SelectObject(hdc, hgdiobj) {
    return DllCall("SelectObject", "uint", hdc, "uint", hgdiobj)
}

GDI_DeleteObject(hObject) {
    return DllCall("DeleteObject", "uint", hObject)
}

GetIconSize(h_icon, ByRef width, ByRef height)
{
    VarSetCapacity(ii, 20, 0)
   
    if (DllCall("GetIconInfo", "UInt", h_icon, "UInt", &ii))
    {
        hbmColor := NumGet(ii, 16)
        hbmMask  := NumGet(ii, 12)
       
        ret := GetBitmapSize(hbmColor, width, height)
       
        DllCall("DeleteObject", "UInt", hbmColor)
        DllCall("DeleteObject", "UInt", hbmMask)
       
        return ret
    }
    return false
}

GetBitmapSize(h_bitmap, ByRef width, ByRef height, ByRef bpp="")
{
    VarSetCapacity(bm, 24, 0) ; BITMAP
    if (!DllCall("GetObject", "UInt", h_bitmap, "Int", 24, "UInt", &bm))
        return false
    width  := NumGet(bm, 4, "int")
    height := NumGet(bm, 8, "int")
    bpp    := NumGet(bm,18, "ushort")
    return true
}

CreateDIBSection(w, h, bpp, hDC=0, ByRef ppvBits=0)
{
    hdcUsed := hDC ? hDC : DllCall("GetDC", "UInt", 0)
    if (hdcUsed)
    {
        VarSetCapacity(bi, 40, 0) ; BITMAPINFO(HEADER)
        NumPut(40, bi,  0)              ; biSize
        NumPut(1,  bi, 12, "UShort")    ; biPlanes
        NumPut(0,  bi, 16)              ; biCompression = BI_RGB (none)
        NumPut(w,  bi,  4)              ; biWidth
        NumPut(h,  bi,  8)              ; biHeight
        NumPut(bpp,bi, 14, "UShort")    ; biBitCount
       
        hbmp := DllCall("CreateDIBSection"
            , "UInt" , hDC
            , "UInt" , &bi   ; defines format, attributes, etc.
            , "UInt" , 0     ; iUsage = DIB_RGB_COLORS
            , "UInt*", ppvBits ; gets a pointer to the bitmap data
            , "UInt" , 0
            , "UInt" , 0)

        if (hdcUsed != hDC)
            DllCall("ReleaseDC", "UInt", 0, "UInt", hdcUsed)

        return hbmp
    }
    return 0
}


ExtractIcon(Filename, IconNumber, IconSize=0)
{
    return DllCall("LoadImage"
        ,"uint",DllCall("GetModuleHandle","str","shell32.dll")
        ,"uint",IconNumber,"uint",1,"int",IconSize,"int",IconSize,"uint",0)
}
It should work on Vista and XP; I'm not sure if the icon exists on earlier versions of Windows. The icon can easily be changed, anyway, by changing this line:
Code:
if !(h_icon := ExtractIcon("shell32.dll", 23, 48))
Icon 23 on Vista and XP is a magnifying glass. The "48" on the end is to specify the 48x48 icon.


The process is "basically":
  1. Create the GUI/window with the WS_EX_LAYERED extended style (+E0x80000).
  2. Create a GDI device context. (Knowing how to use this is more important than knowing what it is.)
  3. Create a 32-bit device independent bitmap.
  4. Select the bitmap into the device context.
  5. Using the device context, draw the icon onto the bitmap.
  6. Call UpdateLayeredWindow() to update the size and content of the window, using the device context.

If you already have a bitmap (i.e. loaded from a PNG file), you can skip steps 3 and 5. To load PNG files, see Image conversions and capturing with GDI+.


It is important to note that layered windows cannot have controls. At least, they won't be visible. To have similar functionality, you'd either have to use two windows/GUIs (one layered + one with controls) or draw your own "controls."

Edit: Updated ExtractIcon() to use LoadImage (thanks to Sean.)
Edit: Fixed WM_LBUTTONDOWN() to use Gui,+LastFound instead of Gui,Default (oops.)
Edit: Fixed handle leak in CreateDIBSection (minor since it didn't apply to the example.)


Last edited by Lexikos on Thu Feb 28, 2008 7:42 am; edited 4 times in total
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1365

PostPosted: Tue Oct 16, 2007 1:28 pm    Post subject: Reply with quote

This is very cool Lexikos. A probelm that I couldnt possibly understand yet until I delve further into your code is that on win2000, it shows the image, but it can only be moved around the area it was originally created (so is bounded by itself when it was 1st created). Hopefully you understand that, but its a little hard to describe.....

So I run the ahk, and the icon appears. I hover over it and it starts moving, but the edges of it are cut off outside where it was 1st drawn.

My plan is to make an objectdock clone, and then improve upon it. (may take a while Wink )
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2605
Location: Australia, Qld

PostPosted: Tue Oct 16, 2007 2:28 pm    Post subject: Reply with quote

I think I understand what you mean. Perhaps the window's position needs to be updated using UpdateLayeredWindow. Try adding this to the auto-execute section of the script:
Code:
OnMessage(0x3, "WM_MOVE")
and this elsewhere:
Code:
WM_MOVE(wParam, lParam, msg, hwnd) {
    if (A_Gui) {
        VarSetCapacity(p,8), NumPut(lParam,p)
        NumPut(NumGet(p,2,"short"),p,4,"int") ; Y
        NumPut(NumGet(p,0,"short"),p,0,"int") ; X
        DllCall("UpdateLayeredWindow","uint",hwnd,"uint",0,"uint",&p
            ,"uint",0,"uint",0,"uint",0,"uint",0,"uint",0,"uint",0)
    }
}
The third parameter of UpdateLayeredWindow is pptDst:
Quote:
Pointer to a POINT structure that specifies the new screen position of the layered window. If the current position is not changing, pptDst can be NULL.

Moving the window with UpdateLayeredWindow doesn't seem to trigger WM_MOVE. Even if it did,
Quote:
If a message arrives while its function is still running due to a previous arrival of the same message, the function will not be called again
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1359

PostPosted: Wed Oct 17, 2007 4:51 am    Post subject: Reply with quote

I was wondering why no one was interested in it...
Here is the code for PNG files.

Code:
sFile   := "C:\test.png"   ; Specify a real PNG file.

Gui, +LastFound -Caption +E0x80000
hGui := WinExist()

pToken   := Gdip_Startup()
pImage   := Gdip_LoadImageFromFile(sFile)
nW   := Gdip_GetImageWidth(pImage)
nH   := Gdip_GetImageHeight(pImage)

mDC   := Gdi_CreateCompatibleDC(0)
mBM   := Gdi_CreateDIBSection(mDC, nW, nH, 32)
oBM   := Gdi_SelectObject(mDC, mBM)

Gdip_DrawImageRectI(pGraphics:=Gdip_CreateFromHDC(mDC), pImage, 0, 0, nW, nH)
DllCall("UpdateLayeredWindow", "Uint", hGui, "Uint", 0, "Uint", 0, "int64P", nW|nH<<32, "Uint", mDC, "int64P", 0, "Uint", 0, "intP", 0xFF<<16|1<<24, "Uint", 2)

GDI_SelectObject(mDC, oBM)
Gdi_DeleteObject(mBM)
Gdi_DeleteDC(mDC)

Gdip_DeleteGraphics(pGraphics)
Gdip_DisposeImage(pImage)
Gdip_Shutdown(pToken)

Gui, Show, Center W%nW% H%nH%
Return

GuiClose:
GuiEscape:
ExitApp


Gdi_CreateCompatibleDC(hDC = 0)
{
   Return   DllCall("gdi32\CreateCompatibleDC", "Uint", hDC)
}

Gdi_CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
{
   NumPut(VarSetCapacity(bi, 40, 0), bi)
   NumPut(nW, bi, 4)
   NumPut(nH, bi, 8)
   NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
 
   Return   DllCall("gdi32\CreateDIBSection", "Uint", hDC, "Uint", &bi, "Uint", DIB_RGB_COLORS:=0, "UintP", pBits, "Uint", 0, "Uint", 0)
}

Gdi_SelectObject(hDC, hGdiObj)
{
   Return   DllCall("gdi32\SelectObject", "Uint", hDC, "Uint", hGdiObj)
}

Gdi_DeleteObject(hGdiObj)
{
   Return   DllCall("gdi32\DeleteObject", "Uint", hGdiObj)
}

Gdi_DeleteDC(hDC)
{
   Return   DllCall("gdi32\DeleteDC", "Uint", hDC)
}

Gdip_Startup()
{
   If Not   DllCall("GetModuleHandle", "str", "gdiplus")
      DllCall("LoadLibrary"    , "str", "gdiplus")
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)
   Return   pToken
}

Gdip_Shutdown(pToken)
{
   DllCall("gdiplus\GdiplusShutdown", "Uint", pToken)
   If   hModule :=   DllCall("GetModuleHandle", "str", "gdiplus")
         DllCall("FreeLibrary"    , "Uint", hModule)
   Return   0
}

Gdip_CreateFromHDC(hDC)
{
   DllCall("gdiplus\GdipCreateFromHDC", "Uint", hDC, "UintP", pGraphics)
   Return   pGraphics
}

Gdip_DeleteGraphics(pGraphics)
{
   Return   DllCall("gdiplus\GdipDeleteGraphics", "Uint", pGraphics)
}

Gdip_LoadImageFromFile(sFile)
{
   VarSetCapacity(wFile, 1023)
   DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sFile, "int", -1, "Uint", &wFile, "int", 512)
   DllCall("gdiplus\GdipLoadImageFromFile", "Uint", &wFile, "UintP", pImage)
   Return   pImage
}

Gdip_DisposeImage(pImage)
{
   Return   DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)
}

Gdip_GetImageWidth(pImage)
{
   DllCall("gdiplus\GdipGetImageWidth", "Uint", pImage, "UintP", nW)
   Return   nW
}

Gdip_GetImageHeight(pImage)
{
   DllCall("gdiplus\GdipGetImageHeight", "Uint", pImage, "UintP", nH)
   Return   nH
}

Gdip_DrawImageRectI(pGraphics, pImage, nL, nT, nW, nH)
{
   Return   DllCall("gdiplus\GdipDrawImageRectI", "Uint", pGraphics, "Uint", pImage, "int", nL, "int", nT, "int", nW, "int", nH)
}
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1359

PostPosted: Wed Oct 17, 2007 6:16 am    Post subject: Re: per-pixel alpha blended GUI demo Reply with quote

lexikos wrote:
Code:
h_icon := ExtractIcon("shell32.dll", 23, 48)

Do you have any particular reason using PrivateExtractIcons which seems to be abandoned by MS? Have you tried LoadImage instead?

Code:
h_icon := DllCall("LoadImage", "Uint", DllCall("GetModuleHandle", "str", "shell32.dll"), "Uint", 23, "Uint", 1, "int", 48, "int", 48, "Uint", 0)
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2605
Location: Australia, Qld

PostPosted: Wed Oct 17, 2007 7:12 am    Post subject: Reply with quote

AutoHotkey uses LoadImage for icon files and ExtractIcon for executables. Since ExtractIcon is limited to 16x16 or 32x32, I had assumed that LoadImage did not support loading icons from executables...

Thanks for the tip.

Now I wonder why Chris used ExtractIcon() at all...
Back to top
View user's profile Send private message
ManaUser



Joined: 24 May 2007
Posts: 904

PostPosted: Wed Oct 17, 2007 8:10 am    Post subject: Reply with quote

Hmm, it didn't work for me. I'm running XP, and I got a draggable magnifying glass, but it wasn't transparent at all.
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2605
Location: Australia, Qld

PostPosted: Wed Oct 17, 2007 10:03 am    Post subject: Reply with quote

Hmm. Works fine for me on two different XP machines.

It doesn't work (on any version of Windows, afaik) if the display depth is set to anything other than 32-bit. I think this is because the icon has no alpha channel. The solution is to manually calculate the alpha data for the bitmap (after drawing the icon onto it) or (I think) use GDI+ (which properly supports alpha blending) to draw the icon.

Since you said the icon was draggable, I assume you are already running at 32-bit. The icon is not drag-able at 16-bit (because pixels with alpha=0 are transparent to the mouse.) I think the magnifying glass is still visible because GDI uses pre-multiplied alpha.
Back to top
View user's profile Send private message
SoggyDog



Joined: 02 May 2006
Posts: 225
Location: Greeley, CO

PostPosted: Thu Oct 18, 2007 2:50 pm    Post subject: Reply with quote

ManaUser wrote:
Hmm, it didn't work for me. I'm running XP, and I got a draggable magnifying glass, but it wasn't transparent at all.

Same here; Draggable, but not transparant.
This is my computer at work; Haven't tried at home.

1024x768 32-bit 60 Hertz

MOBILITY RADEON AGP (0x4C59)
Internal DAC(350MHz)
16 MB

Microsoft Windows XP
Professional
Version 2002
Service Pack 2

Intel(R) Pentium(R) III
Mobile CPU 866MHz
863 MHz, 1.00 GB of RAM
_________________

SoggyDog
Download AutoHotKey Wallpaper
Does 'Fuzzy Logic' tickle?
Back to top
View user's profile Send private message Send e-mail Visit poster's website MSN Messenger
Sean



Joined: 12 Feb 2007
Posts: 1359

PostPosted: Thu Oct 18, 2007 4:44 pm    Post subject: Reply with quote

I think the transparent magnifying glass icon is Vista only. The one in XP isn't transparent. You may test the per-pixel alpha-blending with the PNG file here:
http://en.wikipedia.org/wiki/Portable_Network_Graphics

You may convert this .png to .ico, then could test also transparent icon for per-pixel alpha blending.
Back to top
View user's profile Send private message
ManaUser



Joined: 24 May 2007
Posts: 904

PostPosted: Thu Oct 18, 2007 9:59 pm    Post subject: Reply with quote

Ah, yes. The PNG one is works.
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2605
Location: Australia, Qld

PostPosted: Thu Oct 18, 2007 11:23 pm    Post subject: Reply with quote

Actually, it has slight transparency around the edges to make it look smooth. I can see how one might think it has no transparency. When you said "wasn't transparent at all", I imagined a completely opaque box. Rolling Eyes

Btw, you can also adjust the overall transparency level by changing this line:
Code:
NumPut(255, bf, 2, "UChar") ; SourceConstantAlpha := 255
Back to top
View user's profile Send private message
ManaUser



Joined: 24 May 2007
Posts: 904

PostPosted: Fri Oct 19, 2007 12:27 am    Post subject: Reply with quote

lexikos wrote:
Actually, it has slight transparency around the edges to make it look smooth. I can see how one might think it has no transparency.

Right again. Sorry. I was expecting the lens to be transparent like in your example.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1359

PostPosted: Fri Oct 19, 2007 1:25 am    Post subject: Reply with quote

lexikos wrote:
Actually, it has slight transparency around the edges to make it look smooth.

As a matter of fact, it doesn't work with GdiPlus in XP while it does work with DrawIconEx. I suppose it's because GdiPlus in XP doesn't fully support Icon yet. I'm wondering if the GdiPlus in Vista improves the support for Icon.

Code:
;sFile   := "C:\mag.ico"   ; Specify the real path of the Icon.
;hIcon   := DllCall("LoadImage", "Uint", 0, "Uint", &sFile, "Uint", 1, "int", 48, "int", 48, "Uint", 0x10)
hIcon   := DllCall("LoadImage", "Uint", DllCall("GetModuleHandle", "str", "shell32.dll"), "Uint", 23, "Uint", 1, "int", 48, "int", 48, "Uint", 0)

pToken   := Gdip_Startup()
pBitmap   := hIcon ? Gdip_CreateBitmapFromHICON(hIcon) : Gdip_CreateBitmapFromFile(sFile)
hBitmap   := Gdip_CreateHBITMAPFromBitmap(pBitmap)
nW   := Gdip_GetImageWidth( pBitmap)
nH   := Gdip_GetImageHeight(pBitmap)
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)

DllCall("DestroyIcon", "Uint", hIcon)

mDC   := Gdi_CreateCompatibleDC(0)
oBitmap   := Gdi_SelectObject(mDC, hBitmap)

Gui, +LastFound -Caption +E0x80000
DllCall("UpdateLayeredWindow", "Uint", WinExist(), "Uint", 0, "Uint", 0, "int64P", nW|nH<<32, "Uint", mDC, "int64P", 0, "Uint", 0, "UintP", 255<<16|1<<24, "Uint", 2)
Gui, Show, Center W%nW% H%nH%

Gdi_SelectObject(mDC, oBitmap)
Gdi_DeleteObject(hBitmap)
Gdi_DeleteDC(mDC)
Return

GuiClose:
GuiEscape:
ExitApp


Gdi_CreateCompatibleDC(hDC = 0)
{
   Return   DllCall("gdi32\CreateCompatibleDC", "Uint", hDC)
}

Gdi_SelectObject(hDC, hGdiObj)
{
   Return   DllCall("gdi32\SelectObject", "Uint", hDC, "Uint", hGdiObj)
}

Gdi_DeleteObject(hGdiObj)
{
   Return   DllCall("gdi32\DeleteObject", "Uint", hGdiObj)
}

Gdi_DeleteDC(hDC)
{
   Return   DllCall("gdi32\DeleteDC", "Uint", hDC)
}

Gdip_Startup()
{
   If Not   DllCall("GetModuleHandle", "str", "gdiplus")
   DllCall("LoadLibrary"    , "str", "gdiplus")
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)
   Return   pToken
}

Gdip_Shutdown(pToken)
{
   DllCall("gdiplus\GdiplusShutdown", "Uint", pToken)
   If   hModule :=   DllCall("GetModuleHandle", "str", "gdiplus")
         DllCall("FreeLibrary"    , "Uint", hModule)
   Return   0
}

Gdip_CreateBitmapFromFile(sFile)
{
   VarSetCapacity(wFile, 1023)
   DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sFile, "int", -1, "Uint", &wFile, "int", 512)
   DllCall("gdiplus\GdipCreateBitmapFromFile", "Uint", &wFile, "UintP", pBitmap)
   Return   pBitmap
}

Gdip_CreateBitmapFromHICON(hIcon)
{
   DllCall("gdiplus\GdipCreateBitmapFromHICON", "Uint", hIcon, "UintP", pBitmap)
   Return   pBitmap
}

Gdip_CreateHBITMAPFromBitmap(pBitmap, ARGB = 0)
{
   DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pBitmap, "UintP", hBitmap, "Uint", ARGB)
   Return   hBitmap
}

Gdip_DisposeImage(pImage)
{
   Return   DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)
}

Gdip_GetImageWidth(pImage)
{
   DllCall("gdiplus\GdipGetImageWidth", "Uint", pImage, "UintP", nW)
   Return   nW
}

Gdip_GetImageHeight(pImage)
{
   DllCall("gdiplus\GdipGetImageHeight", "Uint", pImage, "UintP", nH)
   Return   nH
}


Last edited by Sean on Fri Oct 19, 2007 5:58 am; edited 1 time in total
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2605
Location: Australia, Qld

PostPosted: Fri Oct 19, 2007 2:55 am    Post subject: Reply with quote

Sean wrote:
I'm wondering if the GdiPlus in Vista improves the support for Icon.
It's the same on Vista. Bitmap.FromHicon() / CreateBitmapFromHICON() loses the alpha channel. Icon.FromHandle() + Graphics.DrawIcon() should work, but they don't have unmanaged GDI+ equivalents.

Here's what I've discovered via .NET Reflector:

Icon.FromHandle()
The Icon class seems to be a wrapper around a GDI icon. FromHandle() simply copies the handle to the Icon's private handle variable.

Graphics.DrawIcon()
If the Graphics object was created from an Image object, it does this:
Code:
this.DrawImage(icon.ToBitmap(), targetRect);
If the icon is 32-bit, Icon.ToBitmap() creates a 32-bit bitmap and copies the icon data to it. This seems similar to what this guy does to work around the FromHicon issue.
Quote:
There appears to be a bug in GDI+ with regard to getting the bitmap
image of any icon which results in an image being use that is not the
correct pixel format. This seems to occur with any GDI+ function that
internally has to a convert an image to a bitmap. The solution below
addresses the issue by using GetIconInfo, creating a bitmap which will
contain the correct bits but wrong format, then copy the bitmap bits
to a new bitmap with the correctly format.

If the Graphics object was not created from an Image object, it (indirectly) calls (the native Win32 function) DrawIconEx(). Confused
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Goto page 1, 2, 3 ... 11, 12, 13  Next
Page 1 of 13

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group