DigDeep Posted March 27, 2017 Share Posted March 27, 2017 I am doing 2 things here. 1. If VLC found on the machine then the Text will appear in the Form. 2. If VLC text shows up, and if I click on the text, it should give a message. If VLC text is hidden, the msgbox should not auto pop-up. Can someone please help in getting this fixed? #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> Global $VLC, $filepath Func VLC() $filepath = 'C:\Program Files (x86)\VideoLAN\VLC\vlc.exe' If FileExists($filepath) Then $VLC = GUICtrlCreateLabel("VLC", 176, 48, 41, 25) GUICtrlSetFont(-1, 14, 400, 0, "Times New Roman") GUICtrlSetState($VLC, $GUI_SHOW) Else GUICtrlSetState($VLC, $GUI_HIDE) EndIf EndFunc #Region ### START Koda GUI section ### Form= $Form2 = GUICreate("Form1", 388, 142, 750, 373) VLC() GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $VLC MsgBox(0, '', $filepath) EndSwitch WEnd Link to comment Share on other sites More sharing options...
taylansan Posted March 27, 2017 Share Posted March 27, 2017 How about you move that create label before the if check? Func VLC() $filepath = 'C:\Program Files (x86)\VideoLAN\VLC\vlc.exe' $VLC = GUICtrlCreateLabel("VLC", 176, 48, 41, 25) ;create the label before if If FileExists($filepath) Then GUICtrlSetFont(-1, 14, 400, 0, "Times New Roman") GUICtrlSetState($VLC, $GUI_SHOW) Else GUICtrlSetState($VLC, $GUI_HIDE) EndIf EndFunc DigDeep 1 TY. Link to comment Share on other sites More sharing options...
DigDeep Posted March 27, 2017 Author Share Posted March 27, 2017 (edited) thanks @taylansan Edited March 27, 2017 by DigDeep Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 27, 2017 Share Posted March 27, 2017 (edited) I know your question has been solved but here's another one for you. It's a lot more complex and you may not understand it but you may find it useful in the future. (to create hyperlink looking labels) expandcollapse popup#include <GUIConstants.au3> #include <WinAPIShellEx.au3> Global Const $sStructFormat = "struct;int iCtrlId;char path[256];endstruct" Enum $idProcLabel = 9999 Global $hMain = GUICreate("Example") Global $lblVlc = GUICtrlCreateLabel("VLC", 10, 10, 50, 25) GUICtrlSetFont(-1, 12, 400, "", "Segoe UI") Global $lblIE = GUICtrlCreateLabel("Internet Explorer", 10, 45, 150, 25) GUICtrlSetFont(-1, 12, 400, "", "Segoe UI") Global $lblGoogle = GUICtrlCreateLabel("https://www.google.com", 10, 80, 175, 25) GUICtrlSetFont(-1, 12, 400, 4, "Segoe UI") GUICtrlSetColor(-1, 0x0066CC) Global $hLblVlc = GUICtrlGetHandle($lblVlc) Global $hLblIE = GUICtrlGetHandle($lblIE) Global $hLblGoogle = GUICtrlGetHandle($lblGoogle) Global $hNewWindowProc = DllCallbackRegister("NewWindowProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") Global $pNewWindowProc = DllCallbackGetPtr($hNewWindowProc) ; How the DLLStructGetPtr thing works: ; First call the CreateLabelStruct to create a struct with the ID of the label and the corresponding path to execute ; Then get a pointer to it and use that in the $dwRefData of the NewWindowProc function ; Subclass the VLC label _WinAPI_SetWindowSubclass($hLblVlc, $pNewWindowProc, $idProcLabel, DllStructGetPtr(CreateLabelStruct($lblVlc, "C:\Program Files (x86)\VideoLAN\VLC\vlc.exe"))) ; Subclass the IE label _WinAPI_SetWindowSubclass($hLblIE, $pNewWindowProc, $idProcLabel, DllStructGetPtr(CreateLabelStruct($lblIE, @ProgramFilesDir & "\Internet Explorer\iexplore.exe"))) ; Subclass the google label _WinAPI_SetWindowSubclass($hLblGoogle, $pNewWindowProc, $idProcLabel, DllStructGetPtr(CreateLabelStruct($lblGoogle, "https://www.google.com"))) GUISetState(@SW_SHOW, $hMain) While (True) Switch (GUIGetMsg()) Case $GUI_EVENT_CLOSE _WinAPI_RemoveWindowSubclass($hLblVlc, $pNewWindowProc, $idProcLabel) _WinAPI_RemoveWindowSubclass($hLblIE, $pNewWindowProc, $idProcLabel) _WinAPI_RemoveWindowSubclass($hLblGoogle, $pNewWindowProc, $idProcLabel) Exit 0 EndSwitch WEnd ; Create and return a struct with the Control ID and the path for this control Func CreateLabelStruct(Const $iCtrlId, Const $sPath) Local $tReturn = DllStructCreate($sStructFormat) DllStructSetData($tReturn, 1, $iCtrlId) DllStructSetData($tReturn, 2, $sPath) Return $tReturn EndFunc ; Window Procedure Func NewWindowProc($hWnd, $iMsg, $wParam, $lParam, $uIdSubclass, $dwRefData) #forceref $hWnd, $iMsg, $wParam, $lParam, $uIdSubclass, $dwRefData Local $tData = DllStructCreate($sStructFormat, $dwRefData) ; If the subclass ID is the label Switch ($uIdSubclass) Case $idProcLabel ; Switch on the window message Switch ($iMsg) ; User left clicked Case $WM_LBUTTONUP ; If the file exists or it's a valid URL If (FileExists(DllStructGetData($tData, 2)) or _WinAPI_UrlIs(DllStructGetData($tData, 2))) Then ShellExecute(DllStructGetData($tData, 2)) ; User right clicked Case $WM_RBUTTONUP ; If the file exists or it's a valid URL If (FileExists(DllStructGetData($tData, 2)) or _WinAPI_UrlIs(DllStructGetData($tData, 2))) Then ClipPut(DllStructGetData($tData, 2)) ; User hovered over the label Case $WM_SETCURSOR ; If the file exists or it's a valid URL If (FileExists(DllStructGetData($tData, 2)) or _WinAPI_UrlIs(DllStructGetData($tData, 2))) Then GUICtrlSetCursor(DllStructGetData($tData, 1), 0) EndSwitch EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>NewWindowProc A lot more complex but essentially I created a struct using the control id and a path for that control (first two used local files, third uses google.com) and then use a pointer to that struct for the subclass. (This is retrieved in the $dwRefData in the NewWindowProc function. I use this to re-create the same struct to get the data for that label, without having to create a case for each label in the NewWindowProc function) A simpler method would be to have a switch based on the $hWnd (This will correspond to the $hLbl* values where I got the GUICtrlGetHandle). But storing everything I need in a struct that will never be used outside of the NewWindowProc function looks cleaner and requires less lines of code! Edited March 28, 2017 by InunoTaishou Forgot to call _WinApi_RemoveWindowSubclass for each label Skysnake 1 Link to comment Share on other sites More sharing options...
Subz Posted March 27, 2017 Share Posted March 27, 2017 @InunoTaishou thanks for sharing, should the Internet Explorer label open Internet Explorer or have I read it wrong, I thought this could be useful in a project I'm working on for opening third-party apps but it didn't appear to do anything? For Internet labels I've always used the following: #include <GUIConstants.au3> $hMain = GUICreate("Example") $lblGoogle = GUICtrlCreateLabel("https://www.google.com", 10, 80, 175, 25) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1, 12, 400, 4, "Segoe UI") GUICtrlSetColor(-1, 0x0066CC) GUICtrlSetCursor(-1, 0) GUISetState() While 1 Switch (GUIGetMsg()) Case $GUI_EVENT_CLOSE Exit 0 Case $lblGoogle ShellExecute(GUICtrlRead($lblGoogle)) EndSwitch WEnd Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 28, 2017 Share Posted March 28, 2017 (edited) The Internet Explorer just opens internet explorer (at least it should, unless your iexplorer.exe is in a different path). It will only execute the ShellExecute if the file exists or it's a valid URL. I set the path to iexplorer.exe when I did the second second call to _WinApi_SetWindowSubclass. With my subclassing example you can set the label text to be whatever you want, you set the path to execute in the struct. It's exactly like creating a hyperlink (which is the whole reason why I created that in the first place, I wanted a hyperlink looking label and didn't want to create a richedit label). A quick look at the 4th parameter for _WinApi_SetWindowSubclass is Quote $pData [optional] The reference data. This value is passed to the subclass procedure. The meaning of this value is determined by the calling application. It will take a pointer (or int value, I mention this because in the past I've done the same thing except used the control id returned from GUICtrlCreate*). What this means is you can create a struct and set the data in the struct, get a pointer to that struct and then use that for you $pData, and you won't have to keep a global variable of that data. You could get pretty crazy with something like this. Even storing some kind of function call in the struct or even execute a whole script when you click a label, or hover over a picture. (Although you'll be limited to the size of one char array in the struct, anything over [266] and I get errors. But this could be overcome by having multiple char arrays in the struct and combining them all) This is what I mean expandcollapse popup#include <GUIConstants.au3> #include <WinAPIShellEx.au3> Global Const $sStructFormat = "struct;int iCtrlId;char data[256];endstruct" Enum $idProcLabel = 9999 Global $hMain = GUICreate("Example") Global $lblMsgBox = GUICtrlCreateLabel("MsgBox Example", 10, 10, 150, 25) GUICtrlSetFont(-1, 12, 400, "", "Segoe UI") Global $lblPingExample = GUICtrlCreateLabel("Ping Example", 10, 45, 150, 25) GUICtrlSetFont(-1, 12, 400, "", "Segoe UI") Global $hLblMsgBox = GUICtrlGetHandle($lblMsgBox) Global $hLblPing = GUICtrlGetHandle($lblPingExample) Global $hNewWindowProc = DllCallbackRegister("NewWindowProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") Global $pNewWindowProc = DllCallbackGetPtr($hNewWindowProc) _WinAPI_SetWindowSubclass($hLblMsgBox, $pNewWindowProc, $idProcLabel, DllStructGetPtr(CreateLabelStruct($lblMsgBox, "MsgBox::64||Example||This is an example call to a function inside my subclass"))) _WinAPI_SetWindowSubclass($hLblPing, $pNewWindowProc, $idProcLabel, DllStructGetPtr(CreateLabelStruct($lblPingExample, "Run::" & @ComSpec & " /c ping -t www.google.com"))) GUISetState(@SW_SHOW, $hMain) While (True) Switch (GUIGetMsg()) Case $GUI_EVENT_CLOSE _WinAPI_RemoveWindowSubclass($hLblMsgBox, $pNewWindowProc, $idProcLabel) _WinAPI_RemoveWindowSubclass($hLblPing, $pNewWindowProc, $idProcLabel) Exit 0 EndSwitch WEnd ; Create and return a struct with the Control ID and the path for this control Func CreateLabelStruct(Const $iCtrlId, Const $sPath) Local $tReturn = DllStructCreate($sStructFormat) DllStructSetData($tReturn, 1, $iCtrlId) DllStructSetData($tReturn, 2, $sPath) Return $tReturn EndFunc ;==>CreateLabelStruct ; Window Procedure Func NewWindowProc($hWnd, $iMsg, $wParam, $lParam, $uIdSubclass, $dwRefData) #forceref $hWnd, $iMsg, $wParam, $lParam, $uIdSubclass, $dwRefData Local $tData = DllStructCreate($sStructFormat, $dwRefData) ; If the subclass ID is the label Switch ($uIdSubclass) Case $idProcLabel ; Switch on the window message Switch ($iMsg) ; User left clicked Case $WM_LBUTTONUP ConsoleWrite(DllStructGetData($tData, 2) & @LF) Local $aSplit = StringSplit(DllStructGetData($tData, 2), "::", $STR_NOCOUNT + $STR_ENTIRESPLIT) If (Not @error) Then Local $sFunction = $aSplit[0] Local $aParams = StringSplit("CallArgArray||" & $aSplit[1], "||", $STR_NOCOUNT + $STR_ENTIRESPLIT) Call($sFunction, $aParams) EndIf ; User right clicked Case $WM_RBUTTONUP ; If the file exists or it's a valid URL ;If (FileExists(DllStructGetData($tData, 2)) or _WinAPI_UrlIs(DllStructGetData($tData, 2))) Then ClipPut(DllStructGetData($tData, 2)) ; User hovered over the label Case $WM_SETCURSOR ; If the file exists or it's a valid URL ;If (FileExists(DllStructGetData($tData, 2)) or _WinAPI_UrlIs(DllStructGetData($tData, 2))) Then GUICtrlSetCursor(DllStructGetData($tData, 1), 0) EndSwitch EndSwitch Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>NewWindowProc Since AutoIt doesn't have pointers to functions I have to use Call. I chose to have the parameters follow the double semicolon (double to allow my arguments to have a semicolon), then when I do the call to StringSplit on the parameters, I put the special string at the beginning to let the Call function know I'm gonna pass an array for parameters (since I don't know how many there might be) and split using double pipe (||, to allow my arguments to have a single pipe without interfering with the call) Edited March 28, 2017 by InunoTaishou Link to comment Share on other sites More sharing options...
Subz Posted March 28, 2017 Share Posted March 28, 2017 Thanks for the explanation, I just get STX in console when I run the code above, was expecting msgbox, with your first code the issue with IE was the code behaviour if I opened Google (Chrome) it wouldn't open IE, if I opened IE it wouldn't open Google (Chrome). However this only happens every three or four attempts. Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 28, 2017 Share Posted March 28, 2017 (I copied and pasted the wrong code, just updated it) Could be the OS? I've got Windows 10 x64 and [256] for my char array hasn't failed. Strange though, it's just a string to the path to IE. Try doing a ConsoleWrite of the DLLStructGetData($tData, 2) in the example where I have IE and see what path it gives. Link to comment Share on other sites More sharing options...
Subz Posted March 28, 2017 Share Posted March 28, 2017 Thanks Msgbox code is now working and cmd. It seems that the IE code is losing it's data, for example: Case $WM_RBUTTONUP ConsoleWrite(DLLStructGetData($tData, 2) & @CRLF) Results - Alternate Right Clicking on IE and Google labels returns any of the following, usually first time is always correct although I sometimes receive eot in which case nothing works. C:\Program Files (x86)\Internet Explorer\iexplore.exe https://www.google.com s://www.google.com www.google.com google.com le.com eot e Windows 10 Enterprise x64 32GB Ram Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 28, 2017 Share Posted March 28, 2017 (edited) Ah i had that same issue when i went over 256 in the array. Try reducing the array until it works properly. Lmk what number you get to where it works. Would be useful info to have for anyone using struct on Windows 10 x64 and x86 It's strange that it happens in the first place though. Makes me wonder if there's some limitation of DLLStructCreate or if it's a memory issue when using the Subclass. If I remember correctly the maximum size an array should be somewhere around 2^16 bytes, which should be a pretty large number, and since I used char (not wchar) that's a 65k byte array. I wouldn't think it'd be the $dwRefData since it's just a pointer to the internal memory address of the application that holds the struct with the data. I'm wondering where the data is getting jumbled/lost/corrupt. Maybe one of the more experienced AutoIt VIPs could chime in a bit more about char[] structs. Side note: Went around to find the snippit. I said it doesn't have to be a pointer to a struct, you can use an int or a handle too. Here's the snippit where I subclass labels and make them send their messages to the corresponding checkbox instead. I pass the handle to the checkbox as the $dwRefData because I used _SendMessage but you can pass the control id as the $dwRefData and interact with the control using GUICtrl* functions Edited March 28, 2017 by InunoTaishou Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now