Windows Change Icon Dialog
Author |
Message |
Joe Earnes #1 / 10
|
 Windows Change Icon Dialog
I need to publicly distribute a script only on Windows XP. The script needs to allow users to select icons of their choice from any files. With AutoItX, I've been able to come up with a routine that uses the Windows built-in "Change Icon" dialog, by creating a LNK in the temporary folder with a default icon, using ShellExecute "properties" to open the LNK properties, and running the "Change Icon" dialog by Send. After the user closes the "Change Icon" dialog, the routine applies the change through Send, closes the properties dialog, and polls the LNK any icon change, so that any icon selected can be used. A workable extract is at the bottom. Although I think AutoItX is great, I would strongly prefer to distribute a self-contained script without requiring a third-party add-in. I can effect a workable version of the routine (not as smooth, but quite acceptable) with VBS-only commands, with one major exception -- I cannot figure out how to know when the "Choose Icon" dialog is closed by the user, so that I can reactivate the script to apply and close the properties dialog and poll the LNK file. If I use the IE6 file dialog (which I learned from this newsgroup), the user will have to blindly input the numeric icon index for multiple-icon files, without being able to view or select the icon, which is much less desirable. 1) Does anyone know how to directly access the Windows "Change Icon" routine (wherever it is) and get a return value without jumping through these hoops? 2) Any ideas on how to make the routine below work without AutoItX (i.e., how do I know when the user closes the "Change Icon" box)? 3) To test for Windows XP, I'm testing the HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ "CurrentBuildNumber" value for leftmost two characters "26". This works as expected on all the WinXP, Win2k and Win98 machines that I have tried it on, but is there a more "official" way to check for WinXP? Thanks in advance. I scan this newsgroup semi-regularly, search it through Google groups and vist the MVP websites, so you've answered most of my questions in the past without my even needing to ask them. But this one has me stumped. Regards, Joe Earnest ====================== lines may wrap ====================== Option Explicit Dim Default, FSO, Shell Set FSO= WScript.CreateObject("Scripting.FileSystemObject") Set Shell= WScript.CreateObject("WScript.Shell") Default= FSO.BuildPath(FSO.GetSpecialFolder(1), "Shell32.dll,0") WScript.echo IconDialog(Default, "Get Icon", "Select Icon") WScript.Quit Function IconDialog (DefaultIcon, PropTitle, ChangeTitle) Dim AIX, App, File, Icon, IniTitle, LNK, TXT Set App= WScript.CreateObject("Shell.Application") Set AIX= WScript.CreateObject("AutoItX.Control") AIX.SetWinDelay 100 ChangeTitle= Trim(ChangeTitle) PropTitle= Trim(PropTitle) IniTitle= PropTitle & " Properties" LNK= FSO.BuildPath(FSO.GetSpecialFolder(2), PropTitle) & ".lnk" TXT= FSO.BuildPath(FSO.GetSpecialFolder(2), FSO.GetBaseName(FSO.GetTempName)) & ".txt" Icon= "ERROR" Do ' faux error exit loop ' create null temp-txt, create temp-lnk to txt with default icon and user title On Error Resume Next If FSO.FileExists(TXT) Then FSO.DeleteFile TXT, True: If Err Then Exit Do Set File= FSO.CreateTextFile(TXT, True): If Err Then Exit Do File.Close Set File= Nothing If FSO.FileExists(LNK) Then FSO.DeleteFile LNK, True: If Err Then Exit Do Set File= Shell.CreateShortcut(LNK): If Err Then Exit Do File.TargetPath= TXT: If Err Then Exit Do File.IconLocation= DefaultIcon: If Err Then Exit Do File.Save: If Err Then Exit Do Set File= Nothing On Error GoTo 0 ' open temp-lnk properties box, error ext after 3 sec, rename, activate App.ShellExecute """" & LNK & """",,,"properties" If AIX.WinWait(IniTitle, "", 3) Then Exit Do AIX.WinSetTitle IniTitle, "", PropTitle AIX.WinActivate PropTitle, "" ' send change icon key, error exit after 3 sec, rename, wait indefinitely to close AIX.Send "!c" If AIX.WinWait("Change Icon", "", 4) Then AIX.WinClose Title, "": Exit Do AIX.WinSetTitle "Change Icon", "", ChangeTitle AIX.WinWaitClose ChangeTitle, "", 0 ' activate temp-lnk properties box, send apply key, close AIX.WinActivate PropTitle, "" AIX.Send "!a" AIX.WinClose PropTitle, "" ' get icon, cancel if default icon, expand, delete temp-lnk & temp-txt On Error Resume Next Set File= Shell.CreateShortcut(LNK): If Err Then Exit Do Icon= File.IconLocation: If Err Then Exit Do Set File= Nothing If FSO.FileExists(LNK) Then FSO.DeleteFile LNK, True: If Err Then Exit Do If FSO.FileExists(TXT) Then FSO.DeleteFile TXT, True: If Err Then Exit Do Loop Until True Err.Clear On Error GoTo 0 Select Case Icon Case "ERROR" Case DefaultIcon: Icon= "CANCEL" Case Else: If Instr(Icon, "%") Then Icon= Shell.ExpandEnvironmentStrings(Icon) End Select IconDialog= Icon End Function ====================
|
Wed, 22 Dec 2004 00:34:45 GMT |
|
 |
Joe Earnes #2 / 10
|
 Windows Change Icon Dialog
Sorry to repost, but the sample script wrapped far worse than I expected in the original post. This should be better. I need to publicly distribute a script only on Windows XP. The script needs to allow users to select icons of their choice from any files. With AutoItX, I've been able to come up with a routine that uses the Windows built-in "Change Icon" dialog, by creating a LNK in the temporary folder with a default icon, using ShellExecute "properties" to open the LNK properties, and running the "Change Icon" dialog by Send. After the user closes the "Change Icon" dialog, the routine applies the change through Send, closes the properties dialog, and polls the LNK for any icon change, so that any icon selected can be used. A workable extract is at the bottom. Although I think AutoItX is great, I would strongly prefer to distribute a self-contained script without requiring a third-party add-in. I can effect a workable version of the routine (not as smooth, but quite acceptable) with VBS-only commands, with one major exception -- I cannot figure out how to know when the "Choose Icon" dialog is closed by the user, so that I can reactivate the script to apply and close the properties dialog and poll the LNK file. If I use the IE6 file dialog (which I learned from this newsgroup), the user will have to blindly input the numeric icon index for multiple-icon files, without being able to view or select the icon, which is much less desirable. 1) Does anyone know how to directly access the Windows "Change Icon" routine (wherever it is) and get a return value without jumping through these hoops? 2) Any ideas on how to make the routine below work without AutoItX (i.e., how do I know when the user closes the "Change Icon" box)? 3) To test for Windows XP, I'm testing the HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ "CurrentBuildNumber" value for leftmost two characters "26". This works as expected on all the WinXP, Win2k and Win98 machines that I have tried it on, but is there a more "official" way to check for WinXP? Thanks in advance. I scan this newsgroup semi-regularly, search it through Google groups and vist the MVP websites, so you've answered most of my questions in the past without my even needing to ask them. But this one has me stumped. Regards, Joe Earnest ====================== lines may wrap ====================== Option Explicit Dim Default, FSO, Shell Set FSO= WScript.CreateObject("Scripting.FileSystemObject") Set Shell= WScript.CreateObject("WScript.Shell") Default= FSO.BuildPath(FSO.GetSpecialFolder(1), "Shell32.dll,0") WScript.echo IconDialog(Default, "Get Icon", "Select Icon") WScript.Quit Function IconDialog (DefaultIcon, PropTitle, ChangeTitle) Dim AIX, App, File, Icon, IniTitle, LNK, TXT Set App= WScript.CreateObject("Shell.Application") Set AIX= WScript.CreateObject("AutoItX.Control") AIX.SetWinDelay 100 ChangeTitle= Trim(ChangeTitle) PropTitle= Trim(PropTitle) IniTitle= PropTitle & " Properties" LNK= FSO.BuildPath(FSO.GetSpecialFolder(2), PropTitle) & ".lnk" TXT= FSO.BuildPath(FSO.GetSpecialFolder(2), FSO.GetBaseName(FSO.GetTempName)) & ".txt" Icon= "ERROR" Do ' faux error exit loop ' create null temp-txt ' create temp-lnk to txt with default icon and user title On Error Resume Next If FSO.FileExists(TXT) Then FSO.DeleteFile TXT, True If Err Then Exit Do Set File= FSO.CreateTextFile(TXT, True): If Err Then Exit Do File.Close Set File= Nothing If FSO.FileExists(LNK) Then FSO.DeleteFile LNK, True If Err Then Exit Do Set File= Shell.CreateShortcut(LNK): If Err Then Exit Do File.TargetPath= TXT: If Err Then Exit Do File.IconLocation= DefaultIcon: If Err Then Exit Do File.Save: If Err Then Exit Do Set File= Nothing On Error GoTo 0 ' open temp-lnk properties box, error exit after 3 sec ' rename, activate App.ShellExecute """" & LNK & """",,,"properties" If AIX.WinWait(IniTitle, "", 3) Then Exit Do AIX.WinSetTitle IniTitle, "", PropTitle AIX.WinActivate PropTitle, "" ' send change icon key, error exit after 3 sec ' rename, wait indefinitely to close AIX.Send "!c" If AIX.WinWait("Change Icon", "", 4) Then AIX.WinClose Title, "": Exit Do End If AIX.WinSetTitle "Change Icon", "", ChangeTitle AIX.WinWaitClose ChangeTitle, "", 0 ' activate temp-lnk properties box, send apply key, close AIX.WinActivate PropTitle, "" AIX.Send "!a" AIX.WinClose PropTitle, "" ' get icon, cancel if default icon, expand, delete temp-lnk & temp-txt On Error Resume Next Set File= Shell.CreateShortcut(LNK): If Err Then Exit Do Icon= File.IconLocation: If Err Then Exit Do Set File= Nothing If FSO.FileExists(LNK) Then FSO.DeleteFile LNK, True: If Err Then Exit Do End If If FSO.FileExists(TXT) Then FSO.DeleteFile TXT, True: If Err Then Exit Do End If Loop Until True Err.Clear On Error GoTo 0 Select Case Icon Case "ERROR" Case DefaultIcon: Icon= "CANCEL" Case Else If Instr(Icon, "%") Then Icon=Shell.ExpandEnvironmentStrings(Icon) End If End Select IconDialog= Icon End Function ====================
|
Wed, 22 Dec 2004 00:53:57 GMT |
|
 |
Gurge #3 / 10
|
 Windows Change Icon Dialog
There is an undocumented SHChangeIconDialog function from shell32.dll (No support at MS). Unfortunately there is no verb for this function. If you know VB take a look at this link: http://www.mvps.org/vbnet/index.html?code/shell/undocchangeicondlg.htm You might want to write your own activex or even application based on the sample. Regards, -- Gurgen Alaverdian http://www.gurgensvbstuff.com
Quote: > I need to publicly distribute a script only on Windows XP. > The script needs to allow users to select icons of their > choice from any files. With AutoItX, I've been able to > come up with a routine that uses the Windows built-in > "Change Icon" dialog, by creating a LNK in the temporary > folder with a default icon, using ShellExecute "properties" > to open the LNK properties, and running the "Change Icon" > dialog by Send. After the user closes the "Change Icon" > dialog, the routine applies the change through Send,
|
Wed, 22 Dec 2004 06:04:47 GMT |
|
 |
Joe Earnes #4 / 10
|
 Windows Change Icon Dialog
Gurgen, Thanks much for the info. At least now I know where the routine is and a little about it. Unfortunately, I'm purely a scripter, not a VB programmer, and I can't translate all the impressive code at the referenced site into something useful for me. If I could get it to run with rundll32, I could play with it more, but I keep getting a missing entry error message. Anyway, thanks again for the response. Regards, Joe Earnest
Quote: > There is an undocumented SHChangeIconDialog function from shell32.dll (No > support at MS). Unfortunately there is no verb for this function. If you > know VB take a look at this link: > http://www.mvps.org/vbnet/index.html?code/shell/undocchangeicondlg.htm > You might want to write your own activex or even application based on the > sample. > Regards, > -- > Gurgen Alaverdian
|
Wed, 22 Dec 2004 07:42:25 GMT |
|
 |
Gurge #5 / 10
|
 Windows Change Icon Dialog
Joe, The problem is that the function name is not defined in shell32.dll and referenced by an alias as ordinal 62. I do not think it's possible to run this function by ordinal as an entry point with rundll32. You are out of luck If I come up with the activex I'll post it, Regards, -- Gurgen Alaverdian http://www.gurgensvbstuff.com
Quote: > Gurgen, > Thanks much for the info. At least now I know where the routine is and a > little about it. Unfortunately, I'm purely a scripter, not a VB programmer, > and I can't translate all the impressive code at the referenced site into > something useful for me. If I could get it to run with rundll32, I could > play with it more, but I keep getting a missing entry error message. > Anyway, thanks again for the response. > Regards, > Joe Earnest
> > There is an undocumented SHChangeIconDialog function from shell32.dll (No > > support at MS). Unfortunately there is no verb for this function. If you > > know VB take a look at this link: > > http://www.mvps.org/vbnet/index.html?code/shell/undocchangeicondlg.htm > > You might want to write your own activex or even application based on the > > sample. > > Regards, > > -- > > Gurgen Alaverdian
|
Wed, 22 Dec 2004 07:50:19 GMT |
|
 |
Gurge #6 / 10
|
 Windows Change Icon Dialog
I think this executable can save the "SendKey" and "WinWait" mess (-: http://www.gurgensvbstuff.com/Zips/IconIndx.zip The code is included as well. Tested on NT\W2K\XP Regards, -- Gurgen Alaverdian http://www.gurgensvbstuff.com
Quote: > Gurgen, > Thanks much for the info. At least now I know where the routine is and a > little about it. Unfortunately, I'm purely a scripter, not a VB programmer, > and I can't translate all the impressive code at the referenced site into > something useful for me. If I could get it to run with rundll32, I could > play with it more, but I keep getting a missing entry error message. > Anyway, thanks again for the response. > Regards, > Joe Earnest
> > There is an undocumented SHChangeIconDialog function from shell32.dll (No > > support at MS). Unfortunately there is no verb for this function. If you > > know VB take a look at this link: > > http://www.mvps.org/vbnet/index.html?code/shell/undocchangeicondlg.htm > > You might want to write your own activex or even application based on the > > sample. > > Regards, > > -- > > Gurgen Alaverdian
|
Wed, 22 Dec 2004 12:43:39 GMT |
|
 |
Joe Earnes #7 / 10
|
 Windows Change Icon Dialog
Gurgen, Thanks again. Didn't mean to get someone to write code. But it's very interesting. I downloaded it yesterday and played with it a bit. It's much more concise than my version, and I really like the secondary confirmation box with the icon display. Since the rest of my script is in VBS, to use it and get a return, I'd either have to either rewrite the entire script in VB and compile it (which I don't have the basis or background to do), or convert it to an ActiveX (same problems). Compared to a compiled app, VBS is always a concoction held together by bailing wire and chewing gum. So my awkward routine fits the rest of the script. If I have to distribute an ActiveX with the script, I might as well distribute AutoItX's. I've found a way to work the routine with standard script methods, but it's even more awkward and uncertain than the AutoItX version. Thanks again for the help. Regards, Joe Earnest
Quote: > I think this executable can save the "SendKey" and "WinWait" mess (-: > http://www.gurgensvbstuff.com/Zips/IconIndx.zip > The code is included as well. Tested on NT\W2K\XP > Regards, > -- > Gurgen Alaverdian > http://www.gurgensvbstuff.com
|
Fri, 24 Dec 2004 23:40:20 GMT |
|
 |
Gurge #8 / 10
|
 Windows Change Icon Dialog
There is another awkward VBS routine to deal with "Wait for close". This loop should be executed after "change icon" window is started and will run until dialog box is closed. Some additional tweaking might require. Do ret = WshShell.AppActivate ("Select Icon") WScript.Sleep 1000 Loop until ret = 0 Regards, -- Gurgen Alaverdian http://www.gurgensvbstuff.com
Quote: > Gurgen, > Thanks again. Didn't mean to get someone to write code. But it's very > interesting. > I downloaded it yesterday and played with it a bit. It's much more concise > than my version, and I really like the secondary confirmation box with the > icon display. Since the rest of my script is in VBS, to use it and get a > return, I'd either have to either rewrite the entire script in VB and > compile it (which I don't have the basis or background to do), or convert it > to an ActiveX (same problems). Compared to a compiled app, VBS is always a > concoction held together by bailing wire and chewing gum. So my awkward > routine fits the rest of the script. If I have to distribute an ActiveX > with the script, I might as well distribute AutoItX's. I've found a way to > work the routine with standard script methods, but it's even more awkward > and uncertain than the AutoItX version. > Thanks again for the help. > Regards, > Joe Earnest
> > I think this executable can save the "SendKey" and "WinWait" mess (-: > > http://www.gurgensvbstuff.com/Zips/IconIndx.zip > > The code is included as well. Tested on NT\W2K\XP > > Regards, > > -- > > Gurgen Alaverdian > > http://www.gurgensvbstuff.com
|
Sat, 25 Dec 2004 05:40:17 GMT |
|
 |
Joe Earnes #9 / 10
|
 Windows Change Icon Dialog
Gurgen, Thanks for the suggestion. Unfortunately, this routine is a real pain, and it won't work here. I had already tried your suggestion in this form: Do While oShell.AppActivate("Change Icon") oShell.Sleep 250 Loop One problem is that the user might try to refer to another window and end up in a focus fight. More significantly, however, with the "Change Icon" dialog, when the user selects the Browse button to select another file or folder, the routine opens a second window also entitled "Change Icon" (quite clever those MS guys). When the second identically titled window is opened, AppActivate fails to activate either window and generates a vbFalse return (despite the v5.6 documentation that states that it should randomly activate one or the other window). I've tentatively decided, if AutoItX is not found installed, to warn the user of the awkward procedure at startup and suggest installing AIX by jumping the user to the AIX website if the user chooses, or running regsvr32 if the autoitx.dll is available. If AIX is not loaded, the user can proceed, and this works as an alternative, though it's not pretty. Essentially it runs a predefined OK-only message box from another sub, with an explanation to dismiss the message box only after selecting an icon or cancelling at the "Change Icon" dialog. The message box is regenerated if the user dismisses it prematurely. The routine will subsequently apply the selection and dismiss the properties window, and since the message box is script modal, it doesn't get into a focus fight with the user. Needless to say, it's open to user mistakes, but there are no grave consequences that I can think of (unless the user freaks). (partial code inside another Do-Loop for error handling - error exits omitted - object assignments obvious): ... oShellApp.ShellExecute """" & vLNKFile & """",,, "properties" WScript.Sleep 250 oShell.SendKeys "%c": WScript.Sleep 250 Do While oShell.AppActivate(vTitle(0, 2)) subMsgBox [parameters] Loop If oShell.AppActivate(vPropTitle) Then Shell.SendKeys "%a": WScript.Sleep 250 Shell.SendKeys "%{F4}" End If ... Thanks again for all the information. Regards, Joe Earnest
Quote: > There is another awkward VBS routine to deal with "Wait for close". > This loop should be executed after "change icon" window is started and will > run until dialog box is closed. > Some additional tweaking might require. > Do > ret = WshShell.AppActivate ("Select Icon") > WScript.Sleep 1000 > Loop until ret = 0 > Regards, > -- > Gurgen Alaverdian
|
Sat, 25 Dec 2004 07:52:18 GMT |
|
|
|