The information in this article applies to:
- Professional and Enterprise Editions of Microsoft Visual Basic,
16-bit only, for Windows, version 4.0
SUMMARY
The example program included below demonstrates how to extract an
icon from a Microsoft Windows program, whether it is currently running or
not. There are two different techniques depending on whether the program is
run in Microsoft Windows version 3.0 or 3.1. The ExtractIcon API function,
introduced in Windows version 3.1, simplifies the process of extracting
the icon. In Windows version 3.0, a different approach is required.
Both methods are illustrated below.
MORE INFORMATION
The example program shown below displays the icon of an application in a
picture box. The example demonstrates the handling of the hDC property of
the picture box control, specifically the relationship between the Refresh
method, the Image property, and the AutoRedraw property. The code in the
Command3_Click event demonstrates how to transfer the captured icon image
to the Picture property of a picture box (Picture2).
Step-by-Step Example
- Start Visual Basic, or on the File menu, click New Project
(ALT, F, N) if Visual Basic is already running. Form1 is created by
default.
- Create the following controls with the default property settings:
- Picture1
- Picture2
- Command1
- Command2
- Command3
- Add the code below to the general Declarations section of Form1
taking care to enter each Declare statement on one, single line:
' API declarations used in Windows version 3.0 method.
Private Declare Function GetActiveWindow Lib "User" () As Integer
Private Declare Function PostMessage Lib "User" _
(ByVal hWnd As Integer, ByVal wMsg As Integer, _
ByVal wParam As Integer, ByVal lParam As Any) As Integer
Private Declare Function FindWindow Lib "User" _
(ByVal lpClassName As Any, ByVal lpWindowName As Any) As Integer
Private Declare Function LoadLibrary Lib "Kernel" _
(ByVal lpLibFileName As String) As Integer
Private Declare Function GetWindowWord Lib "User" _
(ByVal hWnd As Integer, ByVal nIndex As Integer) As Integer
Private Declare Function LoadIcon Lib "User" _
(ByVal hInstance As Integer, ByVal lpIconName As Any) As Integer
' API declarations used in Windows version 3.1 method.
Private Declare Function GetModuleHandle Lib "Kernel" _
(ByVal lpModuleName As String) As Integer
Private Declare Function GetClassWord Lib "User" _
(ByVal hWnd As Integer, ByVal nIndex As Integer) As Integer
Private Declare Function ExtractIcon Lib "SHELL" _
(ByVal hInst As Integer, ByVal lpszexename As String, _
ByVal hIcon As Integer) As Integer
' API declaration used by both Windows version 3.0 and 3.1 methods.
Private Declare Function DrawIcon Lib "User" (ByVal hDC As Integer, _
ByVal x As Integer, ByVal Y As Integer, ByVal hIcon As Integer) _
As Integer
' Window field offsets for GetClassWord() and GetWindowWord().
Const GWW_HINSTANCE = (-6)
Const GCW_HMODULE = (-16)
' Constants for SendMessage and PostMessage.
Const WM_CLOSE = &H10
' If using Visual Basic version 1.0, remove the single quotation mark
' from the following line of code:
' Const NULL = 0&
- Place the following code in the Form_Load event of Form1:
Private Sub Form_Load ()
Command1.Caption = " 3.0 method "
Command2.Caption = " 3.1 method "
Command3.Caption = " Transfer "
Form1.Caption = " Example of Extracting an Icon"
Form1.Width = Screen.Width * 2 / 3
Form1.Height = Screen.Height / 2
' Center the form on the screen.
Form1.Move (Screen.Width - Form1.Width) / 2, _
(Screen.Height - Form1.Height) / 2
' Size and position the controls dynamically at run time.
Picture1.Move 0, 0, Form1.Width / 2, _
Form1.Height - Command1.Height * 4
Picture2.Move Form1.Width / 2, 0, Form1.Width, _
Form1.Height - Command2.Height * 4
Command1.Move (Form1.Width / 2 - Command1.Width) / 2, _
Form1.Height - Command1.Height * 4
Command2.Move (Form1.Width / 2 - Command1.Width) / 2, _
Form1.Height - Command1.Height * 3
Command3.Move (Form1.Width * 3 / 2 - Command2.Width) / 2, _
Form1.Height - Command2.Height * 4
End Sub
- Place the following code in the Command1_Click event. Configure the code
to match your situation by removing the comment apostrophe from one of
the three methods and adding comment apostrophes to the other two -- to
effectively enable one of the methods and disable the other two.
Private Sub Command1_Click ()
Dim hInstance As Integer, handle As Integer, hIcon As Integer
Picture1.Picture = LoadPicture("") ' clear any previous image.
' Three alternative ways to obtain the handle of the top-level window
' of the program whose icon you want to extract:
' Method 1: If the program is currently running and you do not know
' the class name.
' AppActivate ("Program Manager") ' Set focus to application.
' handle = GetActiveWindow() ' Get handle to window.
' Command1.SetFocus ' Return focus to button.
' Method 2: If program is running and you know the class name.
' Handle = FindWindow("Progman", "Program Manager")
' Method 3: If program is not running, use path and filename.
' Not_Running_Way "sysedit.exe" ' Call sub at general level.
' Exit Sub ' Bypass remaining code in this Sub.
' Now you have the handle -- use it to obtain the instance handle.
hInstance = GetWindowWord(handle, GWW_HINSTANCE)
Picture2.Print "3.O method "
Picture2.Print "handle="; Hex$(handle)
Picture2.Print "hInstance= "; Hex$(hInstance) ' Sanity check.
' Iterate through icon resource identifier values
' until you obtain a valid handle to an icon.
Do
hIcon = LoadIcon(hInstance, n&)
n& = n& + 1
Loop Until hIcon <> 0
Picture2.Print "hIcon= "; Hex$(hIcon)
Picture1.AutoRedraw = -1 ' Make hDC point to persistent bitmap.
r = DrawIcon(Picture1.hDC, 19, 19, hIcon) 'Draw the icon.
Picture1.Refresh ' Refresh from persistent bitmap to Picture.
End Sub
- Place the following code in the Command2_Click event. Note that the
first two methods commented out are provided for information and
contrast to the preferred method, method 3.
Private Sub Command2_Click ()
Dim myhInst As Integer, hIcon As Integer
Picture1.Picture = LoadPicture("") ' Clear the previous image.
' Listed below are three alternative methods that can be used to
' obtain the hInst of your program's module handle.
' Method 1: Use only with .EXE version of your program.
' myhInst = GetModuleHandle("Project1.exe")
' Method 2: Use only with your program running in the environment.
' myhInst = GetModuleHandle("VB.EXE")
' Method 3: The slick way that works in either case.
myhInst = GetClassWord(hWnd, GCW_HMODULE)
' The path and filename of program to extract icon from.
lpzxExeName$ = "moricons.dll" ' Can also use an .EXE file here.
' Get handle to icon.
hIcon = ExtractIcon(myhInst, lpzxExeName$, 0)
Picture2.Print "3.1 method "
Picture2.Print "myhInst= "; Hex$(myhInst) ' Sanity check.
Picture2.Print "hIcon= "; Hex$(hIcon) ' Sanity check.
Picture1.AutoRedraw = -1 ' Make the picture's hDC point to the
' persistent bitmap.
r% = DrawIcon(Picture1.hDC, 19, 19, hIcon)
Picture1.Refresh ' Cause Windows to paint from the persistent bitmap
' to show the icon.
End Sub
- Place the following code in the form's general Declarations section:
Private Sub Not_Running_Way (appname As String)
Dim hInstance As Integer, handle As Integer, hIcon As Integer
Dim hWndShelledWindow As Integer
Picture1.Picture = LoadPicture("") ' Clear any previous image.
hInstance = Shell(appname, 2)
Picture2.Print "3.0 method-application not running"
Picture2.Print "hInstance= "; Hex$(hInstance) ' Check return.
r = DoEvents() ' Allow time for shell to complete.
' The following technique is from another article that explains
' how to determine when a shelled process has terminated. It is
' used here to obtain the correct handle to the window of the
' application whose icon is being extracted. The handle is needed
' to close the application after the extraction is complete.
TimeOutPeriod = 5
fTimeOut = 0 ' Set to false.
s! = Timer
Do
r = DoEvents()
hWndShelledWindow = GetActiveWindow()
' Set timeout flag if time has expired.
If Timer - s! > TimeOutPeriod Then fTimeOut = True
Loop While hWndShelledWindow = Form1.hWnd And Not fTimeOut
' If a timeout occurred, display a timeout message and terminate.
If fTimeOut Then
MsgBox "Timeout waiting for shelled application", 16
Exit Sub
End If
' Iterate through icon resource identifier values
' until you obtain a valid handle to an icon.
Do
hIcon = LoadIcon(hInstance, n&)
n& = n& + 1
Loop Until hIcon <> 0
Picture2.Print "HICON= "; Hex$(hIcon)
Picture1.AutoRedraw = -1 ' Make hDC point to persistent bitmap.
r = DrawIcon(Picture1.hDC, 19, 19, hIcon)
Picture2.Print "return from DrawIcon="; r
Picture1.Refresh ' Refresh from persistent bitmap to picture.
' Now post a message to the window to close the application.
r = PostMessage(hWndShelledWindow, WM_CLOSE, NULL, NULL)
Picture2.Print "return from PostMessage="; r
End Sub
- Place the following code in the Command3_Click event:
Private Sub Command3_Click ()
' This code transfers the extracted icon's image to Picture2's
' Picture property and demonstrates that DrawIcon assigns the image
' to the hDC of Picture1, which points to the persistent bitmap
' (Image property), not to the Picture property.
Picture2.Picture = LoadPicture("") ' Clear old icon.
Picture2.currenty = 0 ' Reset coordinates for printing
' return values.
Picture2.currentx = 0
Picture2.Picture = Picture1.image ' Transfer persistent bitmap
' image to the Picture property.
End Sub
- Press ALT F, V to save the project. Then press F5 to run the program.
Click "3.0 method" to run the code that works in Windows version 3.0.
Click "3.1 method" to run the code that works in Windows version 3.1.
Click Command3 to copy the icon in Picture1 to Picture2 so that the
icon can be accessed as Picture2.Picture.
Both methods extract the first icon in the file. This can be
modified to find the second or succeeding icons by:
- Storing the value of n& in the Do Loop from the first extraction
and plugging that in as the starting point of the next search in
Windows version 3.0.
-or-
- Setting the third parameter of the ExtractIcon function to a
specific index number in Windows version 3.1.
You could perform this functionality in a loop to find and examine each
icon in the file.
The Windows version 3.0 method may take slightly longer to iterate and
find the icon resource ID number.
REFERENCES
"Microsoft Windows Software Development Kit Volume 2"
"Microsoft Press Programmer's Reference Library Volume 2"
|