ExtractIcon?
Blitz3D Forums/Blitz3D Programming/ExtractIcon?
| ||
Does anyone have a Blitz equivalent of this old C function? hIcon = ExtractIcon(hInst, szExeName, nIconNum) I'd like to identify an exe, extract the icon, and use it to produce an image for a toolbar. |
| ||
This thread here has the BlitzMax equivalent: http://blitzbasic.com/Community/posts.php?topic=72899 You'll need to make DECLS for "ExtractIconA" from Shell32, and "SendMessageA" from User32 (User32 can be found wrapped here). Remember also there's SystemProperty() to get the HWND of the window of your application. |
| ||
I've never gone back and refined it so no idea if this is a good or bad way to do it (kind of forgotten about the function) but this is what I've setup as part of the blank framework I use to start any B3D project:Function icon() Local bank Local cut Local test$ Local c Local temp Local hWnd Local modname$ hWnd = SystemProperty("AppHWND") bank = CreateBank(512) ; should be sizeof the returned data block temp = GetModuleFileName(0,bank,512) cut = 0 For c = 0 To temp-1 test$ = test$ + Chr$(PeekByte(bank,c)) If (PeekByte(bank,c) = 92) Then cut = c EndIf Next FreeBank bank modname$ = Mid$(test$,cut+2) icon16 = ExtractIcon(hWnd,modname$,0) icon32 = icon16 temp = SendMessage(hWnd,128,0,icon16) temp = SendMessage(hWnd,128,1,icon32) setCvar("sys_proc",modname$,CVAR_ARCH Or CVAR_PERMA Or CVAR_READONLY) End Function It could probably be re-written more optimally but it seems to do the job so I've never revisisted it. |
| ||
Thanks, but it should be normal Blitz, not BlitzPlus or Max. I understand ExtractIcon() and User32, but how can the resulting icon handle be used to create a bitmap? |
| ||
Oh, I see. That's not easy, especially if you want to support XP-style icons with alpha channels. You can write a DLL with the GDI commands to do it, but it would require C++ experience. Alternatively you can do it with Blitz3D by directly peeking into memory and wrapping some of the Windows API, but you need to learn how the structures are formatted in memory and that takes time. The easiest "blitz" way to do what you want is for you to use ResourceHacker's command-line options to extract the EXE's resources (it extracts all icon groups into .ICO files that you can load). There comes a help file with ResourceHacker: Command Line Scripting: All the functionality of the Resource Hacker GUI (apart from viewing resources) can be accessed from the command line without having to open Resource Hacker. [...] Single Commands: [...] -extract ExeFileName, ResourceAddress, ResourceType, ResourceName, Each command parameter must be separated by a comma, but no comma is expected before the first parameter. To extract all icons from MyProg.exe to MyProgIcons.rc (creating MyProgIcons.rc, Icon_1.ico, Icon_2.ico , Icon_3.ico etc...) ResHacker.exe -extract MyProg.exe, MyProgIcons.rc, icongroup,, *Note the blank commas in the end to extract everything instead of just one. Use ExecFile with quote chars to extract. |
| ||
I'd have thought there is an easier way to do it using GDI API functions with just a userlib but its ages since I touched that stuff so I'd need to get my head around it again. EDIT: Looks like you'd have to rewrite a whole load of C code to blitz for outputting the buffer from memory to do it :| and even then still requires a minimal amount of memory peeking. |
| ||
The original C code was: hIcon = ExtractIcon(hInst, szExeName, nIconNum-1); hdc = GetDC(hWnd); if (hIcon != NULL) { DrawIcon(hdc,x,y,hIcon); } ReleaseDC(hWnd,hdc); What I need is a Blitz equivalent of DrawIcon() |
| ||
I don't understand what's the problem John, you just have to userlib DrawIcon..lib "shell32.dll" api_ExtractIcon% ( hWnd%, File$, Index% ) : "ExtractIconA" .lib "user32.dll" api_GetDC% ( hwnd% ) : "GetDC" api_DrawIcon% ( hdc%, x%, y%, hIcon% ) : "DrawIcon" api_ReleaseDC% ( hwnd%, hdc% ) : "ReleaseDC" api_GetSystemMetrics% ( nIndex% ) : "GetSystemMetrics" .lib "gdi32.dll" api_CreateCompatibleDC% ( hdc% ) : "CreateCompatibleDC" api_DeleteDC% ( hdc% ) : "DeleteDC" api_CreateCompatibleBitmap% ( hdc%, nWidth%, nHeight% ) : "CreateCompatibleBitmap" api_GetPixel% ( hdc%, x%, y% ) : "GetPixel" api_SelectObject% ( hdc%, hObject% ) : "SelectObject" api_DeleteObject% ( hObject% ) : "DeleteObject"-> ;Extract the icon. hIcon = api_ExtractIcon( hInst, szExeName, nIconNum-1 ) ;Create a GDI bitmap. Const SM_CXICON = 11 Const SM_CYICON = 12 iconWidth = api_GetSystemMetrics( SM_CXICON ) iconHeight = api_GetSystemMetrics( SM_CYICON ) hDC = api_GetDC( 0 ) hMemDC= api_CreateCompatibleDC( hDC ) hMemBmp= api_CreateCompatibleBitmap( hDC, iconWidth, iconHeight ) ;Draw the icon on the bitmap. api_SelectObject( hMemDC, hMemBmp ) api_DrawIcon( hMemDC, 0, 0, hIcon ) ;Read the bitmap's pixel data into a Blitz image. Local blitzImage = CreateImage( iconWidth, iconHeight ) SetBuffer ImageBuffer( blitzImage ) For x = 0 To iconWidth-1 For y = 0 To iconHeight-1 WritePixel( x, y, api_GetPixel( hMemDC, x, y ) ) Next Next SetBuffer BackBuffer() ;Clean all memory objects. api_ReleaseDC( 0, hDC ) api_DeleteDC( hMemDC ) api_DeleteObject( hMemBMP ) Reference: http://www.blitzbasic.com/Community/posts.php?topic=30480#1025547 |
| ||
Woah - very comprehensive. Thanks Kryzon. I'll try it in the next few days when I'm not on shift. |
| ||
Thanks - I've managed to simplify it even more.....Graphics 320,160 ;Extract the icon. szExeName$ = "E:\Blitz3D\Blitz3D.exe"+Chr$(0) hIcon = api_ExtractIcon( hInst, szExeName$, 0) : Print hIcon ;Create a GDI bitmap. - don't need it, just the icon straight to a surface Const SM_CXICON = 11 Const SM_CYICON = 12 iconWidth = api_GetSystemMetrics( SM_CXICON ) iconHeight = api_GetSystemMetrics( SM_CYICON ) Print iconWidth+" "+iconHeight hWnd = SystemProperty("AppHWND") : Print hWnd hDC = api_GetDC(hWnd) : Print hDC While Not KeyDown(1) Flip api_DrawIcon( hDC, 75, 75, hIcon ) Wend api_ReleaseDC( 0, hDC ) End Thanks for all your help. |
| ||
Good going, glad it worked. |