I am trying to save the icons used by the system to icon files. I have
some code that works only partially. I am able to get the filename
passed to the ShGetFileInfo api. I am able to get an image list handle
back too. There would be no error either. I check the icon size based
on the image list handle. It reports it properly based on if I was
pulling the large or the small icons and again posts no errors. Then I
try the ImageList_GetIcon api. Now there is a problem. It returns both
an icon handle and an error. The icon handle seems to be invalid and
the error is Not enough storage is available to process this command. I
get the invalid handle on the other api calls that use the Icon handle
created by ImageList_GetIcon. So, my question is: What is also needed
to allow ImageList_GetIcon to have the memory it needs to perform it's
task or what have I possibly mis-entered to cause it to fail?
PResult = Clip(Left(PDirectory)) & Clip(Left(PFile))
hImageList = ShGetFileInfo(PResult, 0, Address(ShFileIn), Size
(ShFileIn), 4000h)
Message('errora: ' & GetLastError())
message('himagelist: ' & himagelist & '<13>handle: ' &
ShFileIn.hIcon & '<13>index: ' & ShFileIn.iIcon)
Ret# = ImageList_GetIconSize(hImageList, xx#, yy#)
Message('ret: ' & ret# & '<13>xx: ' & xx# & '<13>yy: ' & yy# & '<13>
errorc: ' & GetLastError())
hIcon = ImageList_GetIcon(hImageList, ShFileIn.iIcon, 0)
Message('errorb: ' & GetLastError() & <13>hicon: ' & hicon)
FileSize = GlobalSize(hIcon)
Message('filesize: ' & filesize)
lpIcon = GlobalLock(hIcon)
message('address of: ' & lpicon)
Thank you for your help.
Terry Steadman
"Terry Steadman" <t.ste...@cumberlandtech.com> wrote in message
news:Xns93BA9CB46B083ts...@209.16.210.54...
> I have not done what you are trying to do but used the same api's in
> other ways. Some things that may help:
> before calling shgetfileinfo you need to initialize com. Typically
> this requires calling coinitialize() and reverse at the end with
> couninitialize(). The clarion rtl may be doing this for you but you
> never know so I do it expclicitly. Secondly before you can use the
> image list api you need to call InitCommonControls() so I would call
> that after initializing com before doing anything else. That may help
> you get the hicon. Good luck.
> Jim Kane
>
Jim,
I have added the code as you have suggested. The results were not so
good though. With the CoInitialize and CoUninitialize, when the program
hit the CoUninitialize, it would end suddenly. I had added the
InitCommonControls right after the CoInitialize. Then when I ran the
program, the ShGetFileInfo returned an error code 6 - The handle is
invalid. The rest of the api's followed suit with the same errors as
before. Any other suggestions?
"Terry Steadman" wrote:
| Jim,
|
| I have added the code as you have suggested. The results were not so
| good though. With the CoInitialize and CoUninitialize, when the program
| hit the CoUninitialize, it would end suddenly. I had added the
| InitCommonControls right after the CoInitialize. Then when I ran the
| program, the ShGetFileInfo returned an error code 6 - The handle is
| invalid. The rest of the api's followed suit with the same errors as
| before. Any other suggestions?
If you post a complete example that includes all of your code, someone will most likely be
able to help. Just create a handcoded project that illustrates the problem you're
encountering.
Cheers,
Larry Sand
"Terry Steadman" wrote:
|
| Ok. I will include the .app and .dct files. There are no templates
| used so that should not be a problem. The program is messy because I
| have tried so many different ways of pulling the icons. Most of the
| code is in the windows.init embed point.
|
| Terry.
|
|
I really didn't want the whole program. I was trying to get you to narrow the problem
down so it was more managable. In your code, you're dealing with the result of the
ShGetFileInfo call as a handle to an image list. But since you've used SHGFI_ICON as the
only flag the function returns non-zero for success and the hIcon in the SHFILEINFO
structure.
Below is a simple example of using ShGetFileInfo to get the hIcon.
Does that help?
PROGRAM
SHGFI_ICON EQUATE(000000100h) ! get icon
SHGFI_DISPLAYNAME EQUATE(000000200h) ! get display name
SHGFI_TYPENAME EQUATE(000000400h) ! get type name
SHGFI_ATTRIBUTES EQUATE(000000800h) ! get attributes
SHGFI_ICONLOCATION EQUATE(000001000h) ! get icon location
SHGFI_EXETYPE EQUATE(000002000h) ! return exe type
SHGFI_SYSICONINDEX EQUATE(000004000h) ! get system icon index
SHGFI_LINKOVERLAY EQUATE(000008000h) ! put a link overlay on icon
SHGFI_SELECTED EQUATE(000010000h) ! show icon in selected state
SHGFI_ATTR_SPECIFIED EQUATE(000020000h) ! get only specified attributes
SHGFI_LARGEICON EQUATE(000000000h) ! get large icon
SHGFI_SMALLICON EQUATE(000000001h) ! get small icon
SHGFI_OPENICON EQUATE(000000002h) ! get open icon
SHGFI_SHELLICONSIZE EQUATE(000000004h) ! get shell size icon
SHGFI_PIDL EQUATE(000000008h) ! pszPath is a pidl
SHGFI_USEFILEATTRIBUTES EQUATE(000000010h) ! use passed dwFileAttribute
SHGFI_ADDOVERLAYS EQUATE(000000020h) ! apply the appropriate overlays
SHGFI_OVERLAYINDEX EQUATE(000000040h) ! Get the index of the overlay
! in the upper 8 bits of the iIcon
S_OK EQUATE(0)
S_FALSE EQUATE(1)
SHFILEINFO Group, Type
hIcon UNSIGNED
iIcon Long
dwAttributes UNSIGNED
DisplayName CString(260)
TypeName CString(80)
End
MAP
MODULE('win32api')
shGetFileInfo(*CSTRING pszPath, |
UNSIGNED dwFileAttributes, |
*SHFILEINFO psfi, |
UNSIGNED cbFileInfo, |
ULONG uFlags |
),LONG, PASCAL, RAW, NAME('shGetFileInfoA')
DestroyIcon(UNSIGNED hIcon),BOOL,PASCAL,PROC
CoInitialize(LONG pvReserved=0 | Reserved; must be NULL
),LONG, PASCAL
CoUninitialize(),PASCAL
END
END
IconFileInfo LIKE(SHFILEINFO),AUTO
szFilePath CSTRING(260),AUTO
hIcon UNSIGNED
retcde UNSIGNED
CoInitResult LONG(-1)
CODE
CoInitResult = CoInitialize()
szFilePath = 'libmaker.exe'
retcde = ShGetFileInfo(szFilePath,|
0,|
IconFileInfo, |
SIZE(IconFileInfo), |
SHGFI_ICON)
IF retcde <> 0
MESSAGE('This is the icon handle ' &IconFileInfo.hIcon)
DestroyIcon(IconFileInfo.hIcon)
END
IF CoInitResult = S_OK OR CoInitResult = S_FALSE
CoUninitialize()
END
--
Ben E. Brady
http://www.clariondeveloper.com/diabetes/
Read the article... don't wait for the movie...
"Terry Steadman" <t.ste...@cumberlandtech.com> wrote in message
news:Xns93BB7B8788F5Dts...@209.16.210.54...
> "Larry Sand" <La...@sand-associates.com> wrote in
> news:3f16b94d$1...@news.softvelocity.com:
>
> >
> > If you post a complete example that includes all of your code, someone
> > will most likely be able to help. Just create a handcoded project
> > that illustrates the problem you're encountering.
> >
> > Cheers,
> > Larry Sand
> >
> >
>
> Ok. I will include the .app and .dct files. There are no templates
> used so that should not be a problem. The program is messy because I
> have tried so many different ways of pulling the icons. Most of the
> code is in the windows.init embed point.
>
> Terry.
>
>
>
----------------------------------------------------------------------------
----
>
>
>
> Hi Terry,
>
> "Terry Steadman" wrote:
>|
>| Ok. I will include the .app and .dct files. There are no templates
>| used so that should not be a problem. The program is messy because I
>| have tried so many different ways of pulling the icons. Most of the
>| code is in the windows.init embed point.
>|
>| Terry.
>|
>|
>
> I really didn't want the whole program. I was trying to get you to
> narrow the problem down so it was more managable. In your code,
> you're dealing with the result of the ShGetFileInfo call as a handle
> to an image list. But since you've used SHGFI_ICON as the only flag
> the function returns non-zero for success and the hIcon in the
> SHFILEINFO structure.
>
> Below is a simple example of using ShGetFileInfo to get the hIcon.
>
> Does that help?
>
Hello Larry,
I had actually also tried to use the shgfi_iconlocation and the
shgfi_sysiconindex. Generally, it made no difference. But I will take
a look at the provided code and see if I can find the difference to why
it does not work. Thank you for your help.
Terry.
> PROGRAM
>
> SHGFI_ICON EQUATE(000000100h) ! get icon
> SHGFI_DISPLAYNAME EQUATE(000000200h) ! get display name
> SHGFI_TYPENAME EQUATE(000000400h) ! get type name
> SHGFI_ATTRIBUTES EQUATE(000000800h) ! get attributes
> SHGFI_ICONLOCATION EQUATE(000001000h) ! get icon location
> SHGFI_EXETYPE EQUATE(000002000h) ! return exe type
> SHGFI_SYSICONINDEX EQUATE(000004000h) ! get system icon index
> SHGFI_LINKOVERLAY EQUATE(000008000h) ! put a link overlay on
> icon SHGFI_SELECTED EQUATE(000010000h) ! show icon in
<snip>
I had made the changes to my program that were differences in the code or
values. I have re-run it as well. It seems to work until it gets to the
point of doing the create icon. Then it gives an errorcode of 8 - not
enough memory or not enough storage. Any ideas why that would come up?
***
WndSavedProc = Window{Prop:WndProc}
Window{Prop:WndProc} = Address(WndSubClass)
CoInitResult = CoInitialize()
NullVar = 0
Buttonx = 16
Buttony = 16
ButtonSpace = 2
LoginName = ''
LoginLength = 20
J = GetUserNameA(LoginName,LoginLength)
Clear(Users)
Usr:LogonId = Clip(LoginName)
Startx = 2
Starty = 10
TotalButtons = 0
Set(Usr:ByLogon, Usr:ByLogon)
Next(Users)
Loop While Not ErrorCode() And Usr:LogonId = Clip(LoginName)
Clear(Programs)
Pro:ProgramId = Usr:ProgramId
Set(Pro:ByProgramId, Pro:ByProgramId)
Next(Programs)
If ErrorCode() Or Pro:ProgramId <> Usr:ProgramId then
Clear(Programs)
Pro:ProgramName = 'Program: ' & Usr:ProgramId & ' Not Found'
End
TotalButtons += 1
I = TotalButtons
Btns[I].Use = 0
Btns[I].Use = Create(Btns[I].Use, Create:Button)
If I > 1 Then
If (Window{Prop:Width} - (Btns[I - 1].X + Btns[I - 1].W +
ButtonSpace)) < Buttonx + (ButtonSpace / 2) Then
Btns[I].X = Startx
Btns[I].Y = Btns[I - 1].Y + Buttony + ButtonSpace
Else
Btns[I].X = Btns[I - 1].X + Buttonx + ButtonSpace
Btns[I].Y = Btns[I - 1].Y
End
Else
Btns[I].X = Startx
Btns[I].Y = Starty
End
Btns[I].W = Buttonx
Btns[I].H = Buttony
If Clip(Left(Usr:OtherIcon)) > '' Then
Btns[I].Icon = Clip(Left(Usr:OtherIcon))
Else
PFile = Clip(Left(Pro:ProgramExec))
PDirectory = Clip(Left(Pro:ProgramPath))
PResult = ''
PResult = Clip(Left(PDirectory)) & Clip(Left(PFile))
szFilePath = Clip(Left(PDirectory)) & Clip(Left(PFile))
Message('presult prior: ' & szFilePath)
retcde = ShGetFileInfo(szFilePath, 0, IconFileInfo, Size
(IconFileInfo), SHGFI_SYSICONINDEX + SHGFI_SMALLICON)
Message('errora: ' & GetLastError())
message('himagelist: ' & retcde & '<13>handle: ' & IconFileInfo.hIcon
& '<13>index: ' & IconFileInfo.iIcon)
Ret# = ImageList_GetIconSize(retcde, xx#, yy#)
Message('ret: ' & ret# & '<13>xx: ' & xx# & '<13>yy: ' & yy# & '<13>
errorc: ' & GetLastError())
hIcon = 0
hIcon = ImageList_GetIcon(retcde, ShFileIn.iIcon, 0)
Message('errorb: ' & GetLastError() & '<13>hicon: ' & hicon)
*** Here is where the error occurs. errorb: 8, which is not enough
memory, not enough storage to process this command. How do I give this
api the storage it seems to want? ***
FileSize = GlobalSize(hIcon)
Message('filesize: ' & filesize)
lpIcon = GlobalLock(hIcon)
message('address of: ' & lpicon)
If FileSize > 0 Then
IconFile = Clip(Left(Path()))
If Right(Clip(IconFile), 1) <> '\' Then
IconFile = Clip(IconFile) & '\Icons\File' & Pro:ProgramId &
'.ico'
Else
IconFile = Clip(IconFile) & 'Icons\File' & Pro:ProgramId & '.ico'
End
Clear(SA)
Clear(OL)
!*
dwDesiredAccess = BOR(GENERIC_WRITE,GENERIC_READ)
dwShareMode = FILE_SHARE_READ
lpSecurityAttributes = 0
dwCreationDisposition = 4 !OPEN_ALWAYS
dwFlagsAndAttributes = 080h !FILE_ATTRIBUTE_NORMAL
hTemplateFile = 0
message('iconfile: ' & iconfile)
hFile = CreateFile
(IconFile,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisp
osition,dwFlagsAndAttributes,hTemplateFile)
message('createfile: ' & hFile & '<13>to write: ' & filesize)
ret# = WriteFile(hFile, lpIcon, FileSize, writ#,
lpSecurityAttributes)
message('writefile: ' & ret# & '<13>writ: ' & writ#)
ret# = CloseHandle(hFile)
Message('closehandle: ' & ret#)
End
ret# = DestroyIcon(hIcon)
PResult = Clip(Left(ShFileIn.DisplayName))
!If ret# > 32 Then
If ret# > 0 Then
!Message('exe: ' & LongPath(PResult))
FoundExeFlag = True
!Btns[I].Icon = Clip(Left(LongPath(PResult)))
Btns[I].Icon = IconFile
Else
Btns[I].Icon = IconFile
FoundExeFlag = False
End
!Btns[I].Icon = Clip(Left(Pro:ProgramPath)) & Clip(Left
(Pro:ProgramExec))
End
Btns[I].Text = Clip(Left(Pro:ProgramName))
Btns[I].ProgramId = Pro:ProgramId
Btns[I].Use{Prop:Alrt} = MouseRight
Btns[I].Use{Prop:Tip} = Btns[I].Text
Btns[I].Use{Prop:Icon} = Btns[I].Icon
SetPosition(Btns[I].Use, Btns[I].X, Btns[I].Y, Btns[I].W, Btns[I].H)
UnHide(Btns[I].Use)
Ret# = ImageList_Draw(hImageList, ShFileIn.iIcon, Window{Prop:Handle},
Btns[I].X, Btns[I].Y, 0)
Message('draw: ' & Ret# & '<13>errord: ' & GetLastError())
Next(Users)
End
Window{Prop:Height} = Btns[TotalButtons].Y + Buttony + (ButtonSpace / 2)
Window{Prop:Text} = 'Menu Box For: ' & Clip(LoginName)
If CoInitResult = S_OK Or CoInitResult = S_FALSE Then
CoUninitialize()
End
***
> Hello Larry and Others.
>
> I had made the changes to my program that were differences in the code
> or values. I have re-run it as well. It seems to work until it gets
> to the point of doing the create icon. Then it gives an errorcode of
> 8 - not enough memory or not enough storage. Any ideas why that would
> come up?
>
> szFilePath = Clip(Left(PDirectory)) & Clip(Left(PFile))
> Message('presult prior: ' & szFilePath)
> retcde = ShGetFileInfo(szFilePath, 0, IconFileInfo, Size
> (IconFileInfo), SHGFI_SYSICONINDEX + SHGFI_SMALLICON)
> Message('errora: ' & GetLastError())
> message('himagelist: ' & retcde & '<13>handle: ' &
> IconFileInfo.hIcon
> & '<13>index: ' & IconFileInfo.iIcon)
> Ret# = ImageList_GetIconSize(retcde, xx#, yy#)
> Message('ret: ' & ret# & '<13>xx: ' & xx# & '<13>yy: ' & yy# &
> '<13>
> errorc: ' & GetLastError())
> hIcon = 0
> hIcon = ImageList_GetIcon(retcde, ShFileIn.iIcon, 0)
> Message('errorb: ' & GetLastError() & '<13>hicon: ' & hicon)
>
> *** Here is where the error occurs. errorb: 8, which is not enough
> memory, not enough storage to process this command. How do I give
> this api the storage it seems to want? ***
>
I did find and correct this mistake in the imagelist_geticon. I changed
the shfilein.iicon to be iconfileinfo.iicon. It still gave the same
error.
Terry.
First as Jim Kane noted before, if you use a common control like the ImageList, you must
call InitCommonControls or InitCommonControlsEx to ensure their windows classes are
registered and the control is initialized. I suspect that's why you're receiving the
error message.
Next carefully verify each parameter that you're passing. I recommend that you don't use
any implicit variables. They'll cause you nothing but trouble.
Also later in your code you're using ImageList_Draw() with the handle to the window. This
is incorrect, it requires a handle to a device context. They aren't the same thing.
Next, ask yourself what happens when Windows needs to redraw the icon, say for instance
when another window opens over your icon and it's erased. Typically you need to subclass
the control you're drawing on and respond to WM_PAINT for the invalidated region. I don't
think the _Draw() method handles that for you.
Do you need to use ImageList to accomplish what you want?
HTH,
Larry Sand
Jim kane
!in thiswindow.init after the window is open
shellcl.init() !init common controls
If ShellCl.GetSmallIcon(FileName,himglist,idx) then
message('Unable to draw this screen - aborting.')
return(level:fatal) !abort window on error
end
!code to sublass image control goes here
glo:imagelist=himglist !visible in the subclass
glo:imagelistidx=idx !visible in subclass
display() !Show the window
!or for testing and 1x draw use this
shellcl.draw(?Image1{prop:handle}, himglist,idx)
!from shellclass inc file
ShFileInfoType Group,Type
hIcon Unsigned
iIcon signed
dwAttributes Ulong
szDisplayName cstring(260)
szTypeName cstring(80)
end
!member variable
shfileinfo like(shfileinfotype)
ShellClassType.GetSmallIcon Procedure(*Cstring pPathFile, *unsigned
himagelist, *signed idx)
ulFlags ulong
code
clear(hImageList)
clear(idx)
Clear(SELF.ShFileInfo)
ulFlags =1+ 4000H !Shgfi_SmallICON+ShGfi_SysIconIndex
hImageList=ShGetFileInfo(pPathFile, 0, address(SELF.ShFileInfo),
Size(SELF.ShFileInfo), ulflags)
idx = SELF.ShFileInfo.iIcon
Return(Choose(himagelist<>0,0,1))
shellclasstype.draw(long hwnd, long himglist,long idx)
res long
hdc long
code
hdc=getdc(hwnd) !hdc for where to show
Omit('***')
#define ILD_NORMAL 0x0000
#define ILD_TRANSPARENT 0x0001
#define ILD_MASK 0x0010
#define ILD_IMAGE 0x0020
#define ILD_ROP 0x0040
#define ILD_BLEND25 0x0002
#define ILD_BLEND50 0x0004
#define ILD_OVERLAYMASK 0x0F00
***
res=ImageList_Draw(himglist,idx,hdc,0,0,1) !Transparent at 0,0 coord in
hdc#
if ~res and SELF.Debugmode=true then Message('draw failed').
ReleaseDc(Hwnd, hdc) !release the dc
return