Jump to content

GaryC

Members
  • Posts

    17
  • Joined

  • Last visited

GaryC's Achievements

Seeker

Seeker (1/7)

0

Reputation

  1. I see an incompatibility between this version of _ArrayBinarySearch and the standard one. The parameter order of the standard version is Func _ArrayBinarySearch(Const ByRef $avArray, $vValue, $iStart = 0, $iEnd = 0)Yours is Func _ArrayBinarySearch(Const ByRef $avArray, $vValue, $iSubItem = 0, $iStart = 0, $iEnd = 0)If you moved the $iSubItem parameter to the end like this Func _ArrayBinarySearch(Const ByRef $avArray, $vValue= 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)it would be more of a "drop-in replacement" for the standard UDF. I also posted modifications to some of the _array_* functions to add enhancements () which you might want to incorporate.
  2. This UDF contains modifications of functions in Array.au3 as well as a couple of other functions that ended up in the file I use in a couple of my projects. I replaced the "_" prefix with "my" to avoid name collisions. There is also commented-out test code for two of the functions. I hope the tests can serve as examples. MyArrayInsert - _ArrayInsert modified to allow insertion of an array into another array, also appending to an array. MyArrayBinarySearch - _ArrayBinarySearch modified to return the index at which to insert a not-found item, also to search 2d arrays. MyArrayAdd - wrapper for _ArrayAdd that creates the array if the specified variable isn't an array. This could be added to _ArrayAdd but the wrapper was a quick way to implement it before I pulled it out into a library. MyArrayPop - _ArrayPop modified to pop multiple items. This might not be useful very often. MyArrayBinarySearch and MyArrayInsert should be backward compatible with the functions they replace. I kept and modified the header blocks (I hope) appropriately. MyArrayAdd, MyArrayPop, Display2d, and the test functions don't have standard header comment blocks. Display2d returns a string containing a display of a 2d array. I use it for debugging in some of my code, but it may not be of much interest to anyone else. It certainly needs to be renamed, which I haven't done so I don't have to change my code base :-). The functions are in attached file myarray_d.au3. Attached file _ArrayBinarySearch.au3 is a modified example file for MyArrayBinarySearch. Enjoy! GaryC myarray_d.au3 _ArrayBinarySearch.au3
  3. Can I make a safe structure to return? I've tried copying it to another structure($tRet = $tPropId), copying to a structure which the caller creates that is passed by reference, and making a _AutoItObject_DllStructCreate($tag, $tGUID), which should copy the struct. I thought AutoIt handled the memory allocation when returning structs. Thanks. ; Attempt to generate a GUID in a form that can be passed as 4 dwords. #include "AutoItObject.au3" _AutoItObject_StartUp() Main() Func Main() Local $sPropId2 = "{01020304-0506-0708-0910-111213141516}" Local $tGUID = _AutoItObject_CLSIdFromString($sPropId2) Dbg("$tGUID = " & DbgShowPropIdAsBytes($tGUID)) Dbg("Calling GetPropId($sPropId2)") Local $tPropId2 If @OSArch = "X64" Then $tPropId2 = DllStructCreate("uint64;uint64") Dbg("X64") Else $tPropId2 = DllStructCreate("dword;dword;dword;dword") Dbg("X86") EndIf GetPropId($sPropId2, $tPropId2) Dbg("Main: Size of $tGUID = " & DllStructGetSize($tGUID) & " of $tPropId2 is " & DllStructGetSize($tPropId2)) Dbg("Main: $tPropId2 returned from GetPropId = " & DbgShowPropIdAsBytes($tPropId2)) $aPropId4 = ary_GetPropId($sPropId2) Dbg("$aPropId4 = " & DbgShowPropIdAsBytes($aPropId4)) EndFunc ;Convert a MSAAPROPID used in IAccPropServices methods (a GUID) to a struct of DWORDs appropriate for the current architecture. ; On X86 returns struct with 4 DWORDs, on X64 returns struct with 2 UINT64s. Func GetPropId($sPropId, ByRef $tRet) Local $tGUID = _AutoItObject_ClsIdFromString($sPropId) Dbg("GetPropId: showing $tGUID for " & $sPropId & ": " & DbgShowPropIdAsBytes($tGUID)) Local $tPropId, $sPropIdTag If @OSArch = "X64" Then $sPropIdTag = "uint64 data1;uint64 data2" Dbg("X64").__ptr__ Else $sPropIdTag = "dword data1;dword data2;dword data3;dword data4" Dbg("X86") EndIf $oPropId = _AutoItObject_DllStructCreate($sPropIdTag, $tGUID) ; this should make a copy of $tGUID If Not IsObj($oPropId) Then Dbg("GetPropId: $oPropId is not an object") Return EndIf Dbg("$oPropId.__elements__ = " & $oPropId.__elements__ & ",data1 = " & Hex($oPropId.data1)) $tPropId = DllStructCreate($sPropIdTag, $oPropId()) ; $tPropId points to struct in $oPropId. Dbg("GetPropId: Returning $tPropId: " & DbgShowPropIdAsBytes($tPropId)) $tRet = $tPropId Return $tRet EndFunc ;==>GetPropId Func DbgShowPropIdAsBytes($aPropId) Local $tagAsBytes = "byte[4];byte[4];byte[4];byte[4]" If IsArray($aPropId) Then Local $s = "" Local $tBytes = DllStructCreate($tagAsBytes) For $i = 0 to Ubound($aPropId) - 1 DllStructSetData($tBytes, $i + 1, Binary($aPropId[$i])) Next ; $i Local $s = "" for $i = 1 to 4 $s &= String(DllStructGetData($tBytes, $i)) & " " next ; $i Return "(from array) " & $s Else ; $aPropId is a struct. ;Local $tBytes = DllStructCreate($tagAsBytes, DllStructGetPtr($aPropId)) Local $tBytes = DllStructCreate("byte[16]", DllStructGetPtr($aPropId)) Return "(From struct) " & String(DllStructGetData($tBytes, 1)) ;Return "(from struct " & DllStructGetSize($tBytes) & ") " & String(DllStructGetData($tBytes, 1)) & " " & String(DllStructGetData($tBytes, 2)) & " " & String(DllStructGetData($tBytes, 3)) & " " & String(DllStructGetData($tBytes, 4)) ;Return "(from struct) " & Hex(DllStructGetData($tBytes, 1)) & " " & Hex(DllStructGetData($tBytes, 2)) & " " & Hex(DllStructGetData($tBytes, 3)) & " " & Hex(DllStructGetData($tBytes, 4)) EndIf EndFunc ;Convert a MSAAPROPID used in IAccPropServices methods (a GUID) to a struct of DWORDs appropriate for the current architecture. ; On X86 returns struct with 4 DWORDs, on X64 returns struct with 2 DWORDS. Returns an array. Func ary_GetPropId($sPropId) Local $tGUID = _AutoItObject_ClsIdFromString($sPropId) Dbg("GetPropId: showing $tGUID for " & $sPropId & ": " & DbgShowPropIdAsBytes($tGUID)) Local $tPropId If @OSArch = "X64" Then $tPropId = DllStructCreate("dword;dword", DllStructGetPtr($tGUID)) Dbg("X64") Else $tPropId = DllStructCreate("dword;dword;dword;dword", DLLStructGetPtr($tGUID)) Dbg("X86") EndIf Dbg("GetPropId: Returning $tPropId: " & DbgShowPropIdAsBytes($tPropId)) Local $aPropId[4] for $i = 0 to 3 $aPropId[$i] = DllStructGetData($tPropId, $i + 1) next ; $i Return $aPropId EndFunc ;==>GetPropId Func Dbg($sMsg) ConsoleWrite($sMsg & @CRLF) EndFunc
  4. Thanks trancexx. I'm trying to convert a GUID to 4 DWORDs and I'm getting strange results returning a struct from a function. Note the value in the line "Main: $tPropId2 returned from GetPropId " is different from the value in the previous line "GetPropId: Returning $tPropId" generated before GetPropId returns. If I put the values in an array and return them it works. What's going on? Output: $tGUID = (From struct) 0x04030201060508070910111213141516 Calling GetPropId($sPropId2) GetPropId: showing $tGUID for {01020304-0506-0708-0910-111213141516}: (From struct) 0x04030201060508070910111213141516 X86 GetPropId: Returning $tPropId: (From struct) 0x04030201060508070910111213141516 Main: Size of $tGUID = 16 of $tPropId2 is 16 ***Main: $tPropId2 returned from GetPropId = (From struct) 0x00005E01060508070910111213141516 GetPropId: showing $tGUID for {01020304-0506-0708-0910-111213141516}: (From struct) 0x04030201060508070910111213141516 X86 GetPropId: Returning $tPropId: (From struct) 0x04030201060508070910111213141516 $aPropId4 = (from array) 0x04030201 0x06050807 0x09101112 0x13141516 ; Attempt to generate a GUID in a form that can be passed as 4 dwords. #include "AutoItObject.au3" _AutoItObject_StartUp() Main() Func Main() Local $sPropId2 = "{01020304-0506-0708-0910-111213141516}" Local $tGUID = _AutoItObject_CLSIdFromString($sPropId2) Dbg("$tGUID = " & DbgShowPropIdAsBytes($tGUID)) Dbg("Calling GetPropId($sPropId2)") Local $tPropId2 = GetPropId($sPropId2) Dbg("Main: Size of $tGUID = " & DllStructGetSize($tGUID) & " of $tPropId2 is " & DllStructGetSize($tPropId2)) Dbg("Main: $tPropId2 returned from GetPropId = " & DbgShowPropIdAsBytes($tPropId2)) $aPropId4 = ary_GetPropId($sPropId2) Dbg("$aPropId4 = " & DbgShowPropIdAsBytes($aPropId4)) EndFunc ;Convert a MSAAPROPID used in IAccPropServices methods (a GUID) to a struct of DWORDs appropriate for the current architecture. ; On X86 returns struct with 4 DWORDs, on X64 returns struct with 2 DWORDS. Func GetPropId($sPropId) Local $tGUID = _AutoItObject_ClsIdFromString($sPropId) Dbg("GetPropId: showing $tGUID for " & $sPropId & ": " & DbgShowPropIdAsBytes($tGUID)) Local $tPropId If @OSArch = "X64" Then $tPropId = DllStructCreate("dword;dword", DllStructGetPtr($tGUID)) Dbg("X64") Else $tPropId = DllStructCreate("dword;dword;dword;dword", DLLStructGetPtr($tGUID)) Dbg("X86") EndIf Dbg("GetPropId: Returning $tPropId: " & DbgShowPropIdAsBytes($tPropId)) Return $tPropId EndFunc ;==>GetPropId Func DbgShowPropIdAsBytes($aPropId) Local $tagAsBytes = "byte[4];byte[4];byte[4];byte[4]" If IsArray($aPropId) Then Local $s = "" Local $tBytes = DllStructCreate($tagAsBytes) For $i = 0 to Ubound($aPropId) - 1 DllStructSetData($tBytes, $i + 1, Binary($aPropId[$i])) Next ; $i Local $s = "" for $i = 1 to 4 $s &= String(DllStructGetData($tBytes, $i)) & " " next ; $i Return "(from array) " & $s Else ; $aPropId is a struct. ;Local $tBytes = DllStructCreate($tagAsBytes, DllStructGetPtr($aPropId)) Local $tBytes = DllStructCreate("byte[16]", DllStructGetPtr($aPropId)) Return "(From struct) " & String(DllStructGetData($tBytes, 1)) ;Return "(from struct " & DllStructGetSize($tBytes) & ") " & String(DllStructGetData($tBytes, 1)) & " " & String(DllStructGetData($tBytes, 2)) & " " & String(DllStructGetData($tBytes, 3)) & " " & String(DllStructGetData($tBytes, 4)) ;Return "(from struct) " & Hex(DllStructGetData($tBytes, 1)) & " " & Hex(DllStructGetData($tBytes, 2)) & " " & Hex(DllStructGetData($tBytes, 3)) & " " & Hex(DllStructGetData($tBytes, 4)) EndIf EndFunc ;Convert a MSAAPROPID used in IAccPropServices methods (a GUID) to a struct of DWORDs appropriate for the current architecture. ; On X86 returns struct with 4 DWORDs, on X64 returns struct with 2 DWORDS. Returns an array. Func ary_GetPropId($sPropId) Local $tGUID = _AutoItObject_ClsIdFromString($sPropId) Dbg("GetPropId: showing $tGUID for " & $sPropId & ": " & DbgShowPropIdAsBytes($tGUID)) Local $tPropId If @OSArch = "X64" Then $tPropId = DllStructCreate("dword;dword", DllStructGetPtr($tGUID)) Dbg("X64") Else $tPropId = DllStructCreate("dword;dword;dword;dword", DLLStructGetPtr($tGUID)) Dbg("X86") EndIf Dbg("GetPropId: Returning $tPropId: " & DbgShowPropIdAsBytes($tPropId)) Local $aPropId[4] for $i = 0 to 3 $aPropId[$i] = DllStructGetData($tPropId, $i + 1) next ; $i Return $aPropId EndFunc ;==>GetPropId Func Dbg($sMsg) ConsoleWrite($sMsg & @CRLF) EndFunc
  5. I was trying to use AutoItObject with the IAccPropServices::SetHwndPropStr method. Its signature is: HRESULT SetHwndPropStr( [in] HWND hwnd, [in] DWORD idObject, [in] DWORD idChild, [in] MSAAPROPID idProp, [in] LPCWSTR str ); These methods use a type MSAAPROPID. I wrote a dtag for this method that looks like "SetHwndPropStr hresult(hWnd;dword;dword;MSAAPROPID;wstr)". I googled for a copy of oleacc.h and found that it is defined as "typedef GUID MSAAPROPID". As I understand it, this means you are passing a struct as a parameter, not a pointer to a struct. I didn't see a type that would pass a struct or a 4-DWORD value for TAG values. Can I do this with AutoItObject? Thanks.
  6. Hi all, I have a list view in which I delete items and move items to the end. When items are moved or deleted I want the focused item to be the one following the moved or deleted item. So I delete the item, create one at the end, and use _GUICtrlListView_SetItemState to set selected and focused state on the item following the one that was moved. When I move using the button, it works as desired. However, when I use the CTRL+End key, when I read back the status after setting it it is set, and the state on the last item is clear, but the last item is still highlighted. What do I need to do so that I don't lose my place in the list view when I use the CTRL+END key? Below is a test script that I hope illustrates what I mean. The script initially sets the focus on the second item. Then push the move button. The second item moves to the end and what was the 3rd item is selected as desired. Then restart the script but use the CTRL+END key while focused on the list view. The second item moves to the end of the list and what was the 3rd item should be selected (and focused), but instead the last item is selected. I'm using WINXP SP3. [update: I added code (updated below) to allow underline to also move to the end. It does not have the same problem as CTRL+END. It does emit a ding, which CTRL+END does not. Any idea why the ding? I assume CTRL+END is behaving the way it is because the list view processes arrow keys even though I'm catching LVN_KEYDOWN. Is there any way to get it to not do that processing when I catch the key?] [Okay, I got rid of the references to LbC.au3. (Layout by Code is a library designed to assist blind programmers with GUI layout. It can generate code to make the UI so that it doesn't have to be included.)] Thanks. GaryC ; 6/5/11 Test changing selection in a list view. #include <GUIConstantsEx.au3> #include <ListviewConstants.au3> #include <GuiListview.au3> #include <WindowsConstants.au3> Global Const $VK_SHIFT = 16 Global Const $VK_CONTROL = 17 Global Const $VK_MENU = 18 Global Const $VK_SPACE = 0x20 Global Const $VK_PRIOR = 33 Global Const $VK_NEXT = 34 Global Const $VK_END = 35 Global Const $VK_HOME = 36 Global Const $VK_LEFT = 37 Global Const $VK_UP = 38 Global Const $VK_RIGHT = 39 Global Const $VK_DOWN = 40 Global Const $VK_DELETE = 46 Global $ghForm, $gIdLV, $ghLV, $gIdMsg Global $giMask = BitOR($LVIS_FOCUSED, $LVIS_SELECTED) Main() Func Main() $ghForm = GUICreate("Test list view focus and selection change", 531, 372, 246, 181) $gIdLV = GUICtrlCreateListView("Item text", 14, 14, 300, 120) $ghLV = GUICtrlGetHandle($gIdLV) For $i = 0 To 4 GUICtrlCreateListViewItem("Item " & $i, $gIdLV) Next ; $i GUICtrlCreateLabel("This tests whether the display changes as a result of programatically setting focus and selected item state.", 14, 148, 497, 16, 0x50020100, 0x00000000) GUICtrlCreateLabel("When I delete or move an item to the end I want the focus and selection to be on the item following it.", 14, 172, 478, 16, 0x50000100, 0x00000000) Local $IdMoveBtn = GUICtrlCreateButton("Move to end", 14, 196, 100, 16, 0x50010F00, 0x00000000) Local $IdDeleteBtn = GUICtrlCreateButton("Delete", 122, 196, 100, 16, 0x50010F00, 0x00000000) GUICtrlCreateLabel("Msg", 14, 226, 20, 16, 0x50020100, 0x00000000) $gIdMsg = GUICtrlCreateEdit("", 40, 226, 300, 100, 0x503110C4, 0x00000000) GUISetState(@SW_SHOW) GUIRegisterMsg($WM_NOTIFY, "WMNotify") SelItem(1) Msg("Item 1 should have focus and be selected") While 1 Local $iMsg = GUIGetMsg() Switch $iMsg Case 0 ContinueLoop Case $GUI_EVENT_CLOSE ExitLoop Case $IdMoveBtn Msg("Move button pressed.") Move() Case $IdDeleteBtn Msg("Delete button pressed.") Delete() EndSwitch WEnd GUIDelete() EndFunc ;==>Main Func Msg($s) GUICtrlSetData($gIdMsg, $s & @CRLF, 1) EndFunc ;==>Msg Func SelItem($iItem, $fFlag = True) Local $iState If $fFlag Then $iState = $giMask Else $iState = 0 EndIf Msg("Setting state of item " & $iItem & " to " & $iState) _GUICtrlListView_SetItemState($ghLV, $iItem, $iState, $giMask) EndFunc ;==>SelItem Func Move() Local $iFirst = _GUICtrlListView_GetNextItem($ghLV) Local $sItm = _GUICtrlListView_GetItemTextString($ghLV, $iFirst) _GUICtrlListView_DeleteItemsSelected($ghLV) Local $iLast = _GUICtrlListView_GetItemCount($ghLV) ; get index of next added item. GUICtrlCreateListViewItem($sItm, $gIdLV) SelItem($iFirst) Msg("After selecting item " & $iFirst & ", its state is " & _GUICtrlListView_GetItemState($ghLV, $iFirst, $giMask)) Msg(" State of item " & $iLast & ", is " & _GUICtrlListView_GetItemState($ghLV, $iLast, $giMask)) EndFunc ;==>Move Func Delete() Local $iFirst = _GUICtrlListView_GetNextItem($ghLV) _GUICtrlListView_DeleteItemsSelected($ghLV) SelItem($iFirst) Msg("After selecting item " & $iFirst & ", its state is " & _GUICtrlListView_GetItemState($ghLV, $iFirst, $giMask)) EndFunc ;==>Delete Func WmNotify($hWnd, $iMsg, $iWParam, $iLParam) Local $tagNM = DllStructCreate($tagNMHDR, $iLParam) If DllStructGetData($tagNM, "IdFrom") = $gIdLV Then Switch DllStructGetData($tagNM, "Code") Case $LVN_KEYDOWN ;Dbg("LVN_KEYDOWN") ; debug $tagNM = DllStructCreate($tagNMLVKEYDOWN, $iLParam) Local $iKey = DllStructGetData($tagNM, "VKey") Local $fControl = BitAND(GetKeyState($VK_CONTROL), 0x8000) Local $fShift = BitAND(GetKeyState($VK_SHIFT), 0x8000) Local $fAlt = BitAND(GetKeyState($VK_MENU), 0x8000) If Not $fControl And Not $fAlt And Not $fShift Then Msg($iKey) Switch $iKey Case $VK_DELETE Msg("Delete key") Delete() Return 0 Case Else Return $GUI_RUNDEFMSG EndSwitch EndIf ; no modifiers If Not $fControl And Not $fAlt And $fShift Then Msg("Shift+" & $iKey) Switch $iKey Case 189 Msg("_ key") Move() Return 0 Case Else Return $GUI_RUNDEFMSG EndSwitch EndIf ; Shift If $fControl And Not $fShift And Not $fAlt Then Msg("CTRL+" & $iKey) Switch $iKey Case $VK_END ; CTRL+END Msg("CTRL+END") Move() Return 0 #cs Case $VK_UP ; CTRL+UP Return 0 Case $VK_DOWN ; CTRL+DOWN Return 0 #ce Case Else Return $GUI_RUNDEFMSG EndSwitch ; $iKey EndIf ; $fControl EndSwitch ; code EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WmNotify ; Adapted from WINApi.au3 function _WinAPI_GetAsyncKeyState. ; Return is a short; if MSB (bit 15, 0x8000) is set the key is down, if bit 0 is 1 a toggle key (like caps lock) is toggled (on). Func GetKeyState($iKey) Local $aResult = DllCall("user32.dll", "short", "GetKeyState", "int", $iKey) If @error Then Return SetError(@error, @extended, 0) Return $aResult[0] EndFunc ;==>GetKeyState
  7. Thanks, Zedna. I ended up using something like you suggested. I use LVN_ITEMCHANGED. The trick is that checked and unchecked appear as state images in this notification. (This is extracted from working code but this sample doesn't stand alone.) #include <GUIConstantsEx.au3> #include <ListviewConstants.au3> #include <structureConstants.au3> Global Const $LVIS_CHECKED = 0x2000 ; list view item checked Global Const $LVIS_UNCHECKED = 0x1000 ; .... Func WmNotify($hWnd, $iMsg, $iWParam, $iLParam) Local $tagNM = DllStructCreate($tagNMHDR, $iLParam) Switch DllStructGetData($tagNM, "Code") Case $LVN_ITEMCHANGED If DllStructGetData($tagNM, "IdFrom") = $gIdlRoster Then $tagNM = DllStructCreate($tagNMLISTVIEW, $iLParam) Local $iCheckedState = BitAND(DllStructGetData($tagNM, "NewState"), $LVIS_STATEIMAGEMASK) ; state image index * 0x1000 If $iCheckedState Then $giCurItem = DllStructGetData($tagNM, "Item") Local $fChecked = ($iCheckedState = $LVIS_CHECKED) Local $fUnChecked = ($iCheckedState = $LVIS_UNCHECKED) EndIf ; $iCheckedState EndIf ; IDFrom EndSwitch EndFunc ;==>WmNotify I'm not testing that newstate is different from oldstate, or testing the member indicating what has changed, but it seems to work for my application. Gary
  8. I did some more experimenting and was successful. First, the IP address I used, which I got from the IE8 properties, was wrong. I thought that nc wouldn't do a host look-up, but it does. I also changed to a http1.1 request and I got a Last-Modified header. I used nc (netcat) to do a quick test because I had it laying around: nc -v -v www.nwcousins.net 80 <head1.1.txt [head1.1.txt contains: HEAD /NWCC_Roster.csv HTTP/1.1 Host: www.nwcousins.net Connection: close ] Response: DNS fwd/rev mismatch: www.nwcousins.net != choklat.getnetserver.com www.nwcousins.net [64.22.106.177] 80 (http) open HTTP/1.1 200 OK Date: Fri, 21 Jan 2011 00:45:49 GMT Server: Apache Last-Modified: Mon, 03 Jan 2011 19:36:26 GMT ETag: "42b0033-d1fe-498f644884280" Accept-Ranges: bytes Content-Length: 53758 Connection: close Content-Type: text/plain; charset=UTF-8 sent 78, rcvd 259: NOTSOCK Sending with a HTTP1.0 request got an error, which I don't understand since servers that accept 1.1 requests are also supposed to accept 1.0 requests. I found this page helpful: HTTP Made Really Easy. My next step will be to modify the code in to do what I need. Hope someone finds this useful. Gary
  9. My program uses a .CSV file that is downloaded from a web page. I would like to determine when the file is updated. I know that when I load a HTML page there is a last modified attribute in the document object. When I do a HEAD request for the file via NC I don't get the modification date: nc -v -v 92.242.144.2 80 <head.txt [head.txt contains: HEAD /NWCC_Roster.csv HTTP/1.0 ] 92.242.144.2: inverse host lookup failed: h_errno 11004: NO_DATA (UNKNOWN) [92.242.144.2] 80 (http) open HTTP/1.1 200 OK Date: Wed, 19 Jan 2011 17:28:04 GMT Server: Apache Connection: close Content-Type: text/html; charset=UTF-8 sent 34, rcvd 131: NOTSOCK Is there a way to get the last modification date of the file? Thanks. Gary
  10. It gets an error because $s1_var is not set. You would need either $s1_var = "s1_var" dllstructsetdata($struct,$s1_var,$a10) or dllstructsetdata($struct,"s1_var",$a10) What I am trying to do is save some data to implement a recovery file. I want to save it as fast as possible so as to be as transparent as possible. If I need to recover I basically want to restore the array as it was before the crash, so I don't want to have to convert to binary or hex. I am using ushort because I know my numbers will fit in two bytes and don't want to waste disk space if I don't have to. That's why I am using the WinAPI functions. The documentation says if you set a struct element[...] to an array it takes as much of the array as there is room for, but it also talks about only being able to store strings or binary types, otherwise it has to be numbers. I guess what it means is that you can set any kind of array you want as long as it's a string or binary type. I have it working using the for loop to load the struct and I guess that's what I'll have to use. I was just hoping not to have to copy the data in a loop. Oh well, I guess most of the time there won't be much data. About hijacking the thread: that was exactly what I wanted to know, so it's fine with me :-). Thanks. Gary
  11. Thanks for your prompt response. In some places the docs seem to indicate that you can assign a whole array at a time, in others they seem to say you can assign only a number or a string (or maybe a binary type). Can I assign a whole array at once, or do I have to set each element of the struct? This program tries to assign an array to a struct array of ushorts and then read it back. The data returned by DllStructGetData is a number rather than an array, and the contents of the struct is all 0. #include <array.au3> Const $gciCheckinsSize = 3000 Const $gcsLogFile = @ScriptDir & "\tststruct.log" Global $gaCheckins[$gciCheckinsSize] Global $gsLog = "" ; holds output messages. Main() Func Main() MakeData() ;_ArrayDisplay($gaCheckins, "test data") Local $tagBuf = "USHORT[" & UBound($gaCheckins) & "]" MsgOut(0, "Info", "Creating struct " & $tagBuf) Local $stBuf = DllStructCreate($tagBuf) If @error Then MsgOut(0, "Info", "After DllCreateStruct($tagBuf) @error was " & @error) EndIf DllStructSetData($stBuf, 1, $gaCheckins) If @error Then MsgOut(0, "Info", "After DllStructSetData($stBuf) @error was " & @error) EndIf Local $sMsg = "First elements of $stBuf: " For $i = 1 To 5 $sMsg &= DllStructGetData($stBuf, 1, $i) & " " If @error Then $sMsg &= @CRLF & "After GetData for element " & $i & " @error = " & @error & @CRLF EndIf Next ; $i $sMsg &= @CRLF MsgOut(0, "Info", $sMsg) Local $gaCheckins2 = DllStructGetData($stBuf, 1) If @error Then MsgOut(0, "Info", "After DllStructGetData($stBuf) @error was " & @error) EndIf If Not IsArray($gaCheckins2) Then MsgOut(0, "Error", "DllStructGetData for $gaCheckins2 did not return array, type is " & VarGetType($gaCheckins2) & ", value = " & $gaCheckins2) EndIf ;_ArrayDisplay($gaCheckins2, "$gaCheckins2") CheckArrays($gaCheckins, $gaCheckins2) If @error Then MsgOut(0, "Error", "CheckArrays returned @error = " & @error) EndIf ; Write log. FileDelete($gcsLogFile) FileWrite($gcsLogFile, $gsLog) MsgBox(0, "Done", "Log written to " & $gcsLogFile) EndFunc ;==>Main Func MakeData() Local $iIdx = 1 For $i = 0 To UBound($gaCheckins) - 1 $gaCheckins[$i] = ($iIdx + 1) * 256 + $iIdx If $iIdx >= 253 Then $iIdx = 1 Else $iIdx += 2 EndIf Next ; $i EndFunc ;==>MakeData ; Compares 2 arrays. If they match returns 0, if different sizes sets @error=2, if contents differ sets @error=1 and @extended=first differing element. ; If either is not an array sets @error = 3. Func CheckArrays(Const ByRef $a1, Const ByRef $a2) If Not IsArray($a1) Or Not IsArray($a2) Then Return SetError(3, 0, 0) If UBound($a1) <> UBound($a2) Then Return SetError(2, 0, 0) Local $fDiff = False For $i = 0 To UBound($a1) - 1 If $a1[$i] <> $a2[$i] Then $fDiff = True ExitLoop EndIf Next ; $i If $fDiff Then Return SetError(1, $i) EndIf Return 0 EndFunc ;==>CheckArrays Func MsgOut($iFlag, $sTitle, $sMsg) $gsLog &= $sMsg & @CRLF EndFunc ;==>MsgOut tststruct.log contents: Creating struct USHORT[3000] First elements of $stBuf: 0 0 0 0 0 DllStructGetData for $gaCheckins2 did not return array, type is Int32, value = 0 CheckArrays returned @error = 3 Thanks. Gary
  12. I want to store data in a file to allow the program to recover if it crashes. I want this to happen fast so that it doesn't interrupt the user. I have been able to write integers to a binary file one at a time but haven't found a way to write an array at one time-- actually I think I read that you can't. I looked at the binary type but can't see a way to concatenate data to it to hold more than one number. I tried a DllStruct but it wouldn't write. The only other way I can think of is to "manyually" convert the bytes to a string. Otherwise I'll have to write the stuff in ASCII numbers as in a print-out, which seems like a lot of wasted conversion just so that it can read it back in and convert it back to binary. My data is primarily a list of up to about 3000 2-byte integers indicating selected items. Any ideas? Thanks. Gary
  13. I am trying to catch when the user checks an item in a list view so that it can be saved in a recovery info file. I found no way to find the focused item without iterating through the list view items, so I save the current item index when I receive LVN_ITEMCHANGED with focused state. Then when LVN_KEYDOWN for SPACE occurs I change the checked state and record the state with the param of the current item. I suppress default handling. I might have been able to allow default processing and record the opposite of the checked state (NOT _GUICtrlListView_GetItemChecked()) but I thought doing it myself was safer. The problem is that most of the time the checked state doesn't change, at least not long enough to show on the screen. The exception is if I press SPACE immediately after the program starts. The following is the debug output resulting from loading the program, and pressing DownArrow twice followed by SPACE. (Why does the first DownArrow do nothing?) The SPACE should cause the current item to be checked, and according to the debug output it does, but after the following LVN_ITEMCHANGED the debug output shows it is unchecked. Can anyone tell me why that's happening? WMNotify Roster keydown key = 40 LVN_ITEMCHANGED: item 0 changed, not focus, NewState = 0x00000000, Changed = 00000008 Checked = False LVN_ITEMCHANGED: item 0 changed, new state 00000003, Changed = 00000008 Checked = False WMNotify Roster keydown key = 40 LVN_ITEMCHANGED: item 0 changed, not focus, NewState = 0x00000000, Changed = 00000008 Checked = False LVN_ITEMCHANGED: item 0 changed, not focus, NewState = 0x00000000, Changed = 00000008 Checked = False LVN_ITEMCHANGED: item 1 changed, new state 00000003, Changed = 00000008 Checked = False WMNotify Roster keydown key = 32 $giCurItem = 1 Checking LVN_KEYDOWN after checking/unchecking Item check state is True LVN_ITEMCHANGED: item 1 changed, not focus, NewState = 0x00001000, Changed = 00000008 Checked = False (Note: I am blind. I used a modified version of the LbC.au3 (Layout by Code) library by Jamal Mazrui to do the rough layout and then tweaked it based on coordinate information provided by my JAWS screen reader. My understanding of the checked/unchecked state of list view items is that reported by JAWS. If the layout is strange, or if there is something happening on the screen I'm not seeing, that's probably why.) #include <array.au3> #Include <GUIConstantsEx.au3> #Include <WindowsConstants.au3> #include <ListviewConstants.au3> #include <GuiListview.au3> Global Const $VK_SPACE = 0x20 Global $gIdlRoster, $gIdeMemo Global $ghForm Global $giCurItem = 0 ; index in $gIdlRoster of current item, set in WMNotify Main() Func Main() FormCreate() ; Try to make the first press of DownArrow move to the second item, but it doesn't change this, even with focused set to true. _GUICtrlListView_SetItemSelected($gIdlRoster, 0) ;Local $sDbg = LbcDbgCtrlCoords() ;ConsoleWrite($sDbg) FormExec() GUIDelete() EndFunc ;==>Main Func Dbg($sMsg) Local $iRtn = GUICtrlSetData($gIdeMemo, $sMsg & @CRLF, 1) If $iRtn <> 1 Then MsgBox(0, "Dbg", "GUICtrlSetData returned " & $iRtn & "@LFmsg = " & $sMsg) ;_lbcSay($sMsg) EndFunc ;==>Dbg ; Create the GUI. Func FormCreate() $ghForm = GUICreate("Test logging of LV check/uncheck", 600, 500) $gIdlRoster = GUICtrlCreateListView("Item ", 14, 14, 400, 300, 0x5003000D, 0x00000004) For $i = 1 To 5 Local $sItem = "Item " & $i GUICtrlCreateListViewItem($sItem, $gIdlRoster) _GUICtrlListView_SetItemParam($gIdlRoster, $i - 1, $i) ; store index Next ; $i GUICtrlCreateLabel("Memo", 14, 328, 29, 16, 0x50020100, 0x00000000) $gIdeMemo = GUICtrlCreateEdit("", 49, 328, 500, 100, 0x503110C4, 0x00000000) WinSetState($ghForm, "", @SW_MAXIMIZE) GUISetState() EndFunc ;==>FormCreate Func FormExec() GUIRegisterMsg($WM_NOTIFY, "WmNotify") While 1 Local $iMsg = GUIGetMsg() Switch $iMsg Case 0 ContinueLoop Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; main loop EndFunc ;==>FormExec Func ErrorMsg($sMsg) MsgBox(0, "Error", $sMsg) EndFunc ;==>ErrorMsg ; GUIRegisterMsg function to handle the WM_NOTIFY message. ; We want to change the checked state of the item when SPACE is pressed as the default action, ; but we want to record that the item is checked. We do it by recording the 0-based ; index of the focused item in LVN_ITEMCHANGED, then we record it and set the state ; in LVN_KEYDOWN. We also set the checked/unchecked state and avoid default ; processing, although we could reverse the test and then let the default processing change the state. Func WmNotify($hWnd, $iMsg, $iWParam, $iLParam) Local $tagNM = DllStructCreate($tagNMHdr, $iLParam) Switch DllStructGetData($tagNM, "Code") Case $LVN_KEYDOWN If DllStructGetData($tagNM, "IdFrom") = $gIdlRoster Then $tagNM = DllStructCreate($tagNMLVKEYDOWN, $iLParam) Local $iKey = DllStructGetData($tagNM, "VKEY") Dbg("WMNotify Roster keydown key = " & $iKey) ; debug If $iKey = $VK_SPACE Then Local $iCheckin = _GUICtrlListView_GetItemParam($gIdlRoster, $giCurItem) Dbg(" $giCurItem = " & $giCurItem) ; debug ; $giCurItem was set in previous LVN_ITEMCHANGED. If _GUICtrlListView_GetItemChecked($gIdlRoster, $giCurItem) Then Dbg(" unchecking") ; debug _GUICtrlListView_SetItemChecked($gIdlRoster, $giCurItem, False) CheckinRemove($iCheckin) Else Dbg(" Checking") ; debug _GUICtrlListView_SetItemChecked($gIdlRoster, $giCurItem, True) CheckinAdd($iCheckin) EndIf ; checked ; Checked state is shown to be changed here. Dbg(" LVN_KEYDOWN after checking/unchecking Item check state is " & _GUICtrlListView_GetItemChecked($gIdlRoster, $giCurItem)) ; debug Return 0 ; suppress normal message handling ;Return $GUI_RUNDEFMSG ; debug EndIf ; if $VK_SPACE EndIf ; if lRoster Case $LVN_ITEMCHANGED If DllStructGetData($tagNM, "IdFrom") = $gIdlRoster Then $tagNM = DllStructCreate($tagNMLISTVIEW, $iLParam) If BitAND(DllStructGetData($tagNM, "NewState"), $LVIS_FOCUSED) Then ; We get here when we arrow up/down to the item. ; remember the item in this event. $giCurItem = DllStructGetData($tagNM, "Item") Dbg("LVN_ITEMCHANGED: item " & $giCurItem & " changed, new state " & Hex(DllStructGetData($tagNM, "NewState")) & ", Changed = " & Hex(DllStructGetData($tagNM, "Changed"))) ; debug Dbg(" Checked = " & _GUICtrlListView_GetItemChecked($gIdlRoster, $giCurItem)) ; debug Else ; debug Dbg("LVN_ITEMCHANGED: item " & $giCurItem & " changed, not focus, NewState = 0x" & Hex(DllStructGetData($tagNM, "NewState")) & ", Changed = " & Hex(DllStructGetData($tagNM, "Changed"))) ; debug Dbg(" Checked = " & _GUICtrlListView_GetItemChecked($gIdlRoster, $giCurItem)) ; debug EndIf ; else not focused Return $GUI_RUNDEFMSG ; do normal message handling EndIf ; if lRoster EndSwitch ; code EndFunc ;==>WmNotify ; Add a checkin to the list of checkins. ; $iCheckin - Identifier of checkin record (Index in $gaRoster of checkin or $gciNewCheckinFirst + index in $gaNewCheckins). ; Updates globals $gaCheckins, $gaNewCheckins. Func CheckinAdd($iCheckin) EndFunc ;==>CheckinAdd ; Updates globals $gaCheckins, $gaNewCheckins. Func CheckinRemove($iCheckin) EndFunc ;==>CheckinRemove Thanks. GaryC
  14. Hi, When I run xcopy with runwait() its output doesn't appear. When I added the option that causes handles to be inherited (not documented in the RunWait page) it would then show xcopy output when I ran the script from cmd prompt after compiling as a console program. However, when I redirected output with > or ran it from TextPad, my AutoIt script output appeared but the xcopy output did not. I think output from other commands, like dir, does appear. What's going on with xcopy? Gary
  15. Thanks for your responses. I used something like eltorro's solution. I was not able to retrieve a number for the currently-focused item matching the number stored by _GUICtrlTreeViewInsertItem2 (should be the same as GUICtrlTreeViewInsertItem in the GUITreeView.au3 library), either by GUICtrlRead or by GUICtrlGetHandle(GUICtrlRead()). I replaced my _GUICtrlTreeViewInsertItem2 with GUICtrlCreateTreeViewItem and it worked. Because I forgot to disable my debug call to my _GUICtrlTreeViewGetParam function I found out that GUICtrlCreateTreeViewItem does store the item ID in the LPARAM value of the item structure. I also found out that the problem with my code for that is in the storing function (_GUICtrlTreeViewInsertItem2) since _GUICtrlTreeViewGetParam seems to work. Thanks again. GaryC
×
×
  • Create New...