Associated icon

Chris Herring submitted the following code to draw the associated icon for any document on a button. For example: you created a button to open a file like "c:\invoices\abc001.doc", the file extension "doc" is associated with MS-Word so you want the icon for Word-documents displayed on the Progress button.
The remainder of the text is from Chris. As you see, he has some issues left. If you know the solution, please click the "Edit"-link near the bottom of this page to help out.
There were two ways I found to add the icon, using SendMessageA and ImageList_Draw. SendMessageA works ok except it suffers from the same limitations and the toggle button - can't remove focus. ImageList_Draw seems to be able to draw the icon on progress widgets that have the HWND attribute( at least the button and frame anyway ) but the image is release whenever the display for the image is refreshed. On the plus side it would work with flat buttons if you could get the image to stay. Anyway I've put some of my code below. Only thing that I'm aware of that is not entirely correct is the size of the fileinfo memptr regarding the last two string parameters. I wasn't sure of the size so I set them to 1 which only returns the first char of the string if the display name and type tags are added to the flag.

&GLOBAL-DEFINE GWL_STYLE -16 
&GLOBAL-DEFINE BM_SETIMAGE 247 
&GLOBAL-DEFINE IMAGE_ICON 1 
&GLOBAL-DEFINE SHGFI_ICON 256 
&GLOBAL-DEFINE SHGFI_SYSICONINDEX 16384 
&GLOBAL-DEFINE SHGFI_USEFILEATTRIBUTES 16 
&GLOBAL-DEFINE FILE_ATTRIBUTE_NORMAL 128 
&GLOBAL-DEFINE BS_ICON 64 
PROCEDURE SHGetFileInfo EXTERNAL 'shell32': 
    DEFINE INPUT  PARAMETER pszPath AS CHARACTER. 
    DEFINE INPUT  PARAMETER dwFileAttributes AS LONG. 
    DEFINE OUTPUT PARAMETER SBFileInfo AS MEMPTR. 
    DEFINE INPUT  PARAMETER cbSizeFileInfo AS LONG. 
    DEFINE INPUT  PARAMETER uFlags AS LONG. 
    DEFINE RETURN PARAMETER ReturnValue AS LONG. 
END PROCEDURE. 
PROCEDURE ImageList_Draw EXTERNAL "comctl32": 
    DEFINE INPUT  PARAMETER himl AS LONG. 
    DEFINE INPUT  PARAMETER iIndex AS LONG. 
    DEFINE INPUT  PARAMETER hdc AS LONG. 
    DEFINE INPUT  PARAMETER X AS LONG. 
    DEFINE INPUT  PARAMETER Y AS LONG. 
    DEFINE INPUT  PARAMETER iStyle AS LONG. 
    DEFINE RETURN PARAMETER lBool AS LONG. 
END PROCEDURE. 
PROCEDURE setButton :
/*-- Purpose: gets the icon from a program, file, or extension and draws the icon 
                on the specified button 
      Notes:  the button must not be flat or no-focus     
    ------------------------------------------------------------------------------*/ 
    DEFINE INPUT  PARAMETER iHwnd            AS INTEGER    NO-UNDO. 
    DEFINE INPUT  PARAMETER iphButton        AS HANDLE     NO-UNDO.
    DEFINE INPUT  PARAMETER pcProgram        AS CHARACTER  NO-UNDO. 
    DEFINE INPUT  PARAMETER plExtension      AS LOGICAL    NO-UNDO. 
    DEFINE VARIABLE iSize AS INTEGER NO-UNDO. 
    DEFINE VARIABLE fileinfo AS MEMPTR NO-UNDO. 
    DEFINE VARIABLE iFlags AS INTEGER NO-UNDO. 
    DEFINE VARIABLE iReturn AS INTEGER NO-UNDO. 
    DEFINE VARIABLE hIcon AS INTEGER NO-UNDO. 
    DEFINE VARIABLE iIcon AS INTEGER NO-UNDO. 
    DEFINE VARIABLE iAttr AS INTEGER NO-UNDO. 
    DEFINE VARIABLE cDName AS CHARACTER NO-UNDO. 
    DEFINE VARIABLE cType AS CHARACTER NO-UNDO. 
    DEFINE VARIABLE iStyles AS INTEGER NO-UNDO. 
    DEFINE VARIABLE iOldIcon AS INTEGER NO-UNDO. 
    SET-SIZE(fileinfo) = 4 + 4 + 4 + 1 + 1. 
    iSize = GET-SIZE(fileinfo). 
    IF iSize NE 0 THEN DO: 
        /*RUN SHGetFileInfo( "C:\Program Files\Internet Explorer\IEXPLORE.EXE", 0, OUTPUT fileinfo, iSize, iFlags, OUTPUT lReturn ).*/
        /*RUN SHGetFileInfo( ".html", 128, OUTPUT fileinfo, iSize, iFlags, OUTPUT lReturn ).*/ 
        IF plExtension THEN DO: 
            iFlags = {&SHGFI_ICON} + {&SHGFI_USEFILEATTRIBUTES}. 
            RUN SHGetFileInfo( pcProgram, {&FILE_ATTRIBUTE_NORMAL}, OUTPUT fileinfo, iSize, iFlags, OUTPUT iReturn ). 
        END. 
        ELSE DO: 
            iFlags = {&SHGFI_ICON}. 
            RUN SHGetFileInfo( pcProgram, 0, OUTPUT fileinfo, iSize, iFlags, OUTPUT iReturn ). 
        END. 
        hIcon = GET-LONG(fileinfo, 1). 
        iIcon = GET-LONG(fileinfo, 5). 
        iAttr = GET-LONG(fileinfo, 9). 
        cDName = GET-STRING(fileinfo, 13). 
        cType = GET-STRING(fileinfo, 14). 
        SET-SIZE(fileinfo) = 0. 
    END.
    RUN GetWindowLongA(iHwnd, {&GWL_STYLE}, OUTPUT iStyles). 
    IF iphButton:PRIVATE-DATA EQ ? 
        THEN ASSIGN iStyles = iStyles + {&BS_ICON}
                    iphButton:PRIVATE-DATA = "loaded". 
        ELSE ASSIGN iStyles = iStyles. 
    RUN SetWindowLongA(iHwnd, {&GWL_STYLE}, iStyles, OUTPUT iStyles). 
    RUN SendMessageA( iHwnd, {&BM_SETIMAGE}, {&IMAGE_ICON}, hIcon, OUTPUT iOldIcon). 
END PROCEDURE.