Jump to content

kinch

Members
  • Posts

    8
  • Joined

  • Last visited

Everything posted by kinch

  1. Hi guys, Sorry for such a trivial post, but this is really doing my head in. I've spent all day trying to figure this out and the last 3 hours searching everything on this forum that mentions "treeview". I'm trying to build a Treeview based on variable input data. The problem is that some of the data is duplicated, and I can't figure out how to avoid creating duplicate children in the treeview. Code: #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <TreeViewConstants.au3> #include <GuiTreeView.au3> $a = GUICreate("My GUI with treeview", 700, 315) Global $treeview = GUICtrlCreateTreeView(6, 6, 338, 303, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE) Build("Apps|WordPerfect") Build("Apps|Word") Build("Apps|Outlook") Build("Apps|Outlook|Addins") Build("Training|Outlook") Func Build($input) Local $child Local $items = StringSplit($input, "|") For $i = 1 To $items[0] If ($i > 1) Then ; child item $child = _GUICtrlTreeView_AddChild($treeview, $child, $items[$i]) Else ; root item $child = _GUICtrlTreeView_Add($treeview, 1, $items[$i]) EndIf Next EndFunc ;==>Build ; Output that I want it to look like, based on the above "input". Global $treeview2 = GUICtrlCreateTreeView(350, 6, 338, 303, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE) $apps = _GUICtrlTreeView_Add($treeview2, "", "Apps") _GUICtrlTreeView_AddChild($treeview2, $apps, "WordPerfect") _GUICtrlTreeView_AddChild($treeview2, $apps, "Word") $outlook = _GUICtrlTreeView_AddChild($treeview2, $apps, "Outlook") _GUICtrlTreeView_AddChild($treeview2, $outlook, "Addins") $training = _GUICtrlTreeView_Add($treeview2, "", "Training") _GUICtrlTreeView_AddChild($treeview2, $training, "Outlook") GUISetState(@SW_SHOW) While (1) $nmsg = GUIGetMsg() Switch $nmsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd The Treeview on the left is what my "build" code creates. The Treeview on the right is what I want it to look like, based on the string input I provided to the Build function. In other words, the Treeview shouldn't just blindly create a new element, but should check for an existing one of the same name. If it exists, then it drills down into that sub-tree, and then repeats the same process. I've investigated the FindItem function, but that doesn't help since it searches the entire treeview, and it might find an item under the wrong heading (ie. Outlook might be found under Apps, when I'm trying to search under Training). I looked into FindItemEx, but that gets complicated with the 4th Input (ie. Apps/Outlook would exist, but the FindEx would fail on Apps/Outlook/Addins). Every solution I've tried of listing the children of a node to see if one already exists fails. I think a further complication that I'm struggling with is the difference between a ControlID and a Handle. The other thing I'll mention is that I can't use variables for each "group" like in the working example, as the input will eventually contain hundreds of lines with many duplicates. It's doing my head in, no matter what ideas I try, it doesn't produce the right output. I'm sure it can't be that complicated, but I'm just at the end of my patience with this. Please, if anyone can provide some guidance, it'll stop me from screaming in frustration.
  2. Hi all, While I know NOT to mention the words "multi-threading" here, because AutoIT is not multi-threaded nor will it be according to the developers, I'm still interested in multi-processing - running multiple processes to achieve a more efficient result. This is made very easy in AutoIT thanks to things like "Run" and "ShellExecute" which could allow you to spawn whatever applications or processes you want. Plus, the wonderful ease of GUI creation means it's easy to give a simple user interface for spawning, modifying, and monitoring results. I've tried to do my due diligence with the forum, but the best I found was '?do=embed' frameborder='0' data-embedContent>> which unfortunately doesn't seem to work anymore (I tried to fix up the UDF but I had no idea what I was doing or why). And to get the awkward part out of the way first - I know an interpreted language like AutoIT will be slow, so it's not ideal for intense calculations and loops. However, I believe using it as a wraparound for the "fast" functions could be of great benefit - heck, you could even dump numerical data into Excel, run the calculations and then grab the result. The best of both worlds! So anyway, I'd like to discuss multi-processing in a classic "master/slave" relationship, and get some ideas on possible implementation. Idea #1: Named Pipes So, you have a process running as the master which opens the pipe, and then have however many slave processes which connect to the master through the named pipe, to download "tasks" to execute. Whatever your particular application is. My understanding is that all PCs/processes will need to be able to connect to where the pipe is created though. I've never used pipes for this kind of thing, are they any good? Idea #2: Sockets Similar to the above, but the master process opens a socket and receives incoming connections from the slaves. Apart from that, it's similar to named pipes. I guess this method has the advantage of (theoretically) being used by any PC on the internet/network, instead of having to have access to the server the pipe is created on. Idea #3: SQLite While probably the weakest (and, I suspect, slowest), you could have an SQLite table stored on a network drive, which could have the jobs to be completed, and then each process could lock the DB, update the row for "being worked on by me" and then unlock the DB. It could also store it's results in the table, so that it's accessible from any process (including the master). This does limit it to applications that could connect to that network resource though. Idea #4: "Overseers" I couldn't think of what else to call this, but overseers seems semi-relevant. The idea being that on a PC you have a master, which accepts requests for work from another PC. The concept of overseers is that it's a "mini-master" running on a (non-master) PC. It connects to the master PC, downloads a bunch of jobs, and then creates sub-processes based on the number of processes/CPU cores. This would mean that a user of that PC has more control over how much work the application(s) are doing. Idea #5: Clipboard (Idea stolen from the link pasted above) This one is straightforward, you copy data to the clipboard, and the processes grab it and action it. It's presumably limited to one PC, although I suspect it'd be pretty easy to implement (especially if it was just a small number of processes). Discussion: So then we get to the discussion. I'm curious to know if you guys know of better ways (using AutoIT - I don't want to write a DLL in C++ and use DllCall+CreateThread() ) for multi-processing. Given the above, is one likely to be easier to implement than another? Are there any efficiency concerns to take note of? Can anyone tell me if I've made a glaring error or mistake in my reasoning? I've never written a program using pipes, but I have done sockets in Perl/C a long time ago. Or am I just wasting everyone's time including my own? I have an upcoming project where I'll have to crunch massive amounts of data - farming it out to multiple PCs/CPUs sounds like a fine idea to me... and even if it never is efficient enough for that, I would probably use it for calculating primes or something. It's just fun to multi process Has anyone written something similar and would like to share their thoughts on the topic? Cheers.
  3. Thanks jchd. I figured right on most of it, but it's good to have it confirmed by an expert. As for running SQLite over the network... I understand it's not the most desirable solution, but in a worst case scenario I'm envisaging 20 added rows per transaction, 20 times a work day (spread over the course of a few hours). I'm hoping that this isn't too much for the (network) SQLite DB to handle, because if it is, then my entire project goes down the drain. I'd have to switch over to using just a textfile as database storage with no easy way to check for data integrity or modifications. It'd be doable, but messy. Anyway, I'll see how it goes in the live environment first. Initial reports from my alpha testers are ok. It's partly why I'm even writing my admin application - to open the DB and compare the DB data with the logfiles to ensure the correct data has been written to the DB. If something goes wrong, I should be able to manually fix it with the admin tool. The user_version pragma is a nifty little feature, could be useful for all sorts of things. I'll have a think as to how best to incorporate it. I imagine the array<->DB functionality could be done with a messy bunch of functions, such as "SArrayInsert" and "SArrayGet" which would just be wrappers around the sql queries... and you'd have to make it robust enough to handle all the array queries that people would ordinarily throw at it... again, probably doable but very messy and not worth it. Oh well, as I said, I was just curious. Cheers.
  4. Hi, I suspect this is really more of an SQL question than an AutoIT question, but since I'm writing and using AutoIT, I wondered if someone might have come up with a neat little solution (as so often happens around here!) I have a basic DB admin program - it loads the data into a ListView for easy viewing and editing. This allows me to fix typos, make updates, add rows, delete erroneous rows, etc. The DB is stored on a network server and potentially could be opened (and updated) by another user while I'm working on it. Due to the nature of the program, I'm technically working on a copy in the listview, rather than on the DB itself (ie, I load the DB into the listview contents, and then have to save it back to the DB when I'm ready to commit my changes). So my question is, is there a way to detect if someone else has updated the DB while I'm working on it, so I don't commit changes that might overwrite or undo someone else's work? I suspect not based on what I've read in the SQLite AutoIT helpfiles, but hopefully someone with more knowledge than me can help. If not, is there any workaround? I'm looking into the "begin exclusive" SQL function to lock the DB while I'm working on it, so that other updates will have to wait until I've finished - this allows me to make my updates, reload the DB, and check that it's all good. Then I release the exclusive lock and the other updates can read the updated data and go about their business. Am I doing this wrong? Also, slightly off-topic but I'm curious... when I was using Perl, there was this really nifty trick (module) where they linked a perl array variable to a SQL database using some funky object code and a Database Abstraction Layer, so that queries to the "array" were channeled through to the DB itself. i.e., "$array[0]" would actually run a "select * from db where index=0" type of query and "$array[0] = 1" would run an "update table" query and effectively give you a live interface to the database. Probably quite problematic in a large environment with lots of updates, but none-the-less, a very cool functionality. Is such a thing possible in AutoIT? Cheers.
  5. Hey guys, Excellent UDF and very helpful to keep everything in one neat little .exe package. I thought I'd (try to) modify it to make the image resize to the control size, so that you wouldn't have to find the exact sized picture or manually convert each image to the control size. I thought it'd be easy but I spent a frustrating few hours trying to figure out what I was doing wrong. The original code near the end of "_SetBitmapToCtrl" (line 270-281): ; set SS_BITMAP/BS_BITMAP style to the control $Style = _WinAPI_GetWindowLong($hWnd, $GWL_STYLE) If @error Then Return SetError(4, 0, 0) _WinAPI_SetWindowLong($hWnd, $GWL_STYLE, BitOR($Style, $iCtrl_BITMAP)) If @error Then Return SetError(5, 0, 0) ; set image to the control $hPrev = _SendMessage($hWnd, $iCtrl_SETIMAGE, $IMAGE_BITMAP, $hBitmap) If @error Then Return SetError(6, 0, 0) If $hPrev Then _WinAPI_DeleteObject($hPrev) Return 1 I added some code to resize the image to match the control size just before the "_SendMessage" command: $Style = _WinAPI_GetWindowLong($hWnd, $GWL_STYLE) If @error Then Return SetError(4, 0, 0) _WinAPI_SetWindowLong($hWnd, $GWL_STYLE, BitOR($Style, $iCtrl_BITMAP)) If @error Then Return SetError(5, 0, 0) If $bResize = True Then Local $hBitmap_copy = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) Local $ctrl_details = ControlGetPos("", "", $CtrlId) ; Get dimensions of Control If @error <> 1 and $ctrl_details[2] >=1 and $ctrl_details[3] >= 1 Then Local $hBitmap_Scaled = _GDIPlus_ImageResize($hBitmap_copy, $ctrl_details[2], $ctrl_details[3]) ;Resize image to Control Dimensions $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_Scaled) ; Put resized image into $hBitmap variable. _GDIPlus_BitmapDispose($hBitmap_Scaled) EndIf _GDIPlus_BitmapDispose($hBitmap_copy) EndIf ; set image to the control $hPrev = _SendMessage($hWnd, $iCtrl_SETIMAGE, $IMAGE_BITMAP, $hBitmap_Scaled) ; use scaled image instead of original. If @error Then Return SetError(6, 0, 0) If $hPrev Then _WinAPI_DeleteObject($hPrev) Return 1 You'll need a way of turning on the $bResize variable (since this was a one-off piece of code for a specific application, I just hardcoded it - however adding it to the argument list to make it more generic shouldn't be difficult). I also don't know if any of those functions can error in such a way to corrupt the data or break the script, but it worked in my (virtually non-existent) testing. If someone smarter than me would like to tell me what I've missed, I would also appreciate it. This was the first time I've tried anything with GDI+, so please forgive any heinous mistakes. Cheers.
  6. Hi guys, I'm a low level tech support dude in an organisation supporting approx 6000 users. Alot of our processes are manual, slow, and use outdated tools. While I can't do much about the tools (since most of them are used by the whole company in various forms and I can't just update it myself), I have found that I can automate and greatly speed up the manual and slow processes. I've been working on 3 tools over the last few months. Now I'd like to iterate that I'm low level - I have pretty limited access and realistically, this kind of thing is above my pay grade; not because I can't do it, but because we're dealing with high level managers and corporate-wide communications. Frankly, I shouldn't be taking responsibility for doing things like this. However, I'm the only one in my team smart enough to do it. My managers are insisting that the code be well-documented, maintained, and easily modifiable. They're also insisting that all my code be available for our area (and technically anyone else) to modify if need be. I'm a little conflicted here: I literally spent months working on these, and even learning AutoIT from scratch to do so (I had previous experience with VB and HTAs, so it's not a huge transition, but I'm always learning new things). It's my code, I worked on the vast majority of it on my own time because I was too busy doing tech support at work. There's no one else in my team smart enough to do it. However, in the other teams, there are people smart enough to take my code, modify it, and then claim it as their own. We have no corporate rules about this (we're not a programming organisation and we almost always use external vendors for this.) Even if we do have code we wrote, it's always owned by "the company". I understand this is normal, but I feel a great sense of ownership on my code, that I built, because I took the initiative at work to learn it. I identified the need, I taught myself the language, and I built the app(s) from scratch. And my code will be available for anyone to modify and then show off to their managers "what they've done with it". And who will get the credit then? Does anyone else feel the same way? Do you sometimes restrict access to your code somehow? How do you handle managers who demand that everything you do is technically the property of the company (and these are nazis managers who could make your life miserable if you argue and say the code is yours)? Code that probably couldn't be used in other organisations because it's very specifically coded to your own environment... Ideally I think I'd just like to keep the source at home, and only make the .exe available to the company, but the managers are going on about "single point sensitive" and "team ownership" and the like. I guess I'm just looking at how other people/companies work in this regard, since I'm not sure if I'm just being overly protective of my intellectual property. Alot of you guys have made your code publicly available with UDFs, so I'm curious what you think about this topic.
  7. Kudos and a hearty "hear hear" for this post. I suck at GUI design, I hate it, and my programs look terrible. While "having fun" doesn't necessarily lead to efficient GUI design, you never know when you'll stumble across a diamond in the rough that is just what one needs to spice up a boring grey window with buttons. I vote for more!
  8. Hi, First off, I'd like to thank ISI360 for creating the amazing ISN Studio. It's a very impressive piece of engineering, and of course to all those who wrote UDFs that it relies on. I've been using it for a project at work, and will use it for many more. I found a couple of issues that I'd like to report - I tried to use the Bugtracker and official forum, but those were both in German and I couldn't translate it to make it work. String 899 in english.lng needs to be translated (it's one word, but I noticed it). I had the entire ISN studio crash when I was using the form designer - I had opened the GUI Properties, and clicked on the "..." button for the "Parent GUI" dialog box. The entire application flashed, then became unresponsive. The only recourse was to kill it with task manager. After re-loading the application, I tried again to click on that button, and it worked. Might have been a one-off, and I haven't had time to test more thoroughly. I know this doesn't help, but hopefully more in the future. The crash led to an interesting discovery - the backups made are the ones that are saved to disk - I had spent 30 minutes working on a form, getting everything aligned just right... but I hadn't saved, and it hadn't auto-saved. After the crash, the form was back to square one, and I couldn't find a copy with my changes anywhere. I checked the project folder, the project Backups folder, and the Backups folder in the ISN Studio directory and anything else that looked relevant. I searched the entire HDD for .isf files and the ones I found didn't have my (unsaved) changes made. I don't know if auto-saving a "work in progress" is possible with forms, but it'd be great if it was. Lastly... this is a weird one and I apologise in advance for the lack of detail. When I open an ISF file with the form editor... it seems to remember code changes that I had undone outside of the application. Let me explain: While working on an ISF file, somehow (I genuinely don't know how) in the midst of the GUI creation code, a simple "Exit" line had been put in there. This was causing my program to exit as soon as it loaded. Weird. So I opened the ISF file in notepad, removed the offending line, saved it in notepad. All good. However, I then opened it in the form editor, made some GUI changes, saved it - and somehow the Exit line was back. It's almost like the form editor is working from a backup or something, but I couldn't figure out where that erroneous code was coming from. This has happened consistently enough that I now do all my ISF code edits in Notepad, after using the form studio to design the layout. I haven't done enough research yet to find a reproduceable bug for you, but it definitely happens to me alot. I'm working on a project for work atm that means I have to focus on that, but once it's finished and I have some time to play, I'll try to find a way to show you what I mean. Oh, a feature request based on the above: Is there an option for .ISF files to save the constants in the code instead of just replacing it with numbers? ie, instead of "SetState(-1,144)" it uses "SetState(-1,$GUI_ENABLED)" or whatever. The only reason I ask is because I don't want to open the .ISF files in the form editor after it's created, and it just makes it a little bit more awkward. Once again, thanks for the app, and looking forward to seeing more in the future!
×
×
  • Create New...