Posted an updated example project for how to make platform http error codes generic AND platform specific 😛
No. Not IE.
// there are issues with this style // 1. you can only select one file // 2. If folder is already opened, it doesn't select the file Declare Function ShellExecuteW lib "shell32" (hwnd as Integer, lpOperation as WString, lpFile as WString, lpParameters as WString, lpDirectory as Integer, nShowCmnd as Integer) as Integer Dim err as Integer Dim param As String param = "/select, """ + f.AbsolutePath + """" err = ShellExecuteW(Window(0).WinHWND, "Open", "explorer", param, 0, 1)
EDIT – a better version has been written by Julian Samphire
He’s given me permission to post it here. Note there are two methods. One takes an array of file paths. The second overloads things to accept paramarry that then calls into the version that takes an array
Public Function ShowSelectedInExplorer(path As String, files() As String) as Int32 Declare Function CoInitialize Lib "Ole32.dll" Alias "CoInitialize" (pvReserved As Integer) As Int32 Declare Function ILCreateFromPathW Lib "Shell32.dll" Alias "ILCreateFromPathW" (pszPath As WString) As Ptr Declare Function SHOpenFolderAndSelectItems Lib "Shell32.dll" Alias "SHOpenFolderAndSelectItems" (pidlFolder As Ptr, cidl As UInt32, apidl As Ptr, dwFlags As UInt32) As Int32 Declare Sub ILFree Lib "Shell32.dll" Alias "ILFree" (pidl As Ptr) Call CoInitialize(0) Dim pidl As Ptr = ILCreateFromPathW(path) If pidl = Nil Then Return 0 'If path wasn't found then return End If Dim mb As New MemoryBlock(COM.SIZEOF_PTR * (files.Ubound + 1)) 'Get a pidl for each file and store it For i As Integer = 0 To files.Ubound mb.Ptr(i * COM.SIZEOF_PTR) = ILCreateFromPathW(files(i)) Next Dim ok As Int32 = SHOpenFolderAndSelectItems(pidl, files.Ubound + 1, mb, 0) ILFree(pidl) Return ok End Function Public Function ShowSelectedInExplorer(path As String, ParamArray files As String) as Int32 'Build an array from the param array and pass it back to ShowSelectedInExplorer so we can support both methods Dim arrayOfFiles() As String For Each f As String In files arrayOfFiles.Append(f) Next Return ShowSelectedInExplorer(path, arrayOfFiles) End Function
This has probably been posted in the forums. Its just not always easy to find.
Declare Function NSClassFromString Lib "Cocoa" (name As CFStringRef) As Ptr Declare Function sharedWorkspace Lib "AppKit" selector "sharedWorkspace" ( obj As ptr ) As ptr Declare Function selectFile Lib "AppKit" selector "selectFile:inFileViewerRootedAtPath:" ( obj As ptr, fPath As CFStringRef, rootFullPath As CFStringRef ) As Boolean Dim workspace As ptr = sharedWorkspace( NSClassFromString( "NSWorkspace" ) ) Call selectFile( workspace, f.NativePath, "")
Sometime when you’re debugging your application you run into a situation where you get funky behaviour.
You might do something like Javier mentioned in his recent blog post on Xojo’s blog :
Dim ASource() As Integer = Array(1,2,3,4,5,6,7,8) Dim ATarget() As Integer ATarget = ASource
And, as he noted, you cant figure out why when you change one array you also appear to alter the other. This can also happen with other reference types as I noted in other posts.
For instance I’ve seen
Dim d As New Date Dim d1 As date d1 = d d1.month = 2
and then the question of “why did d change?” arises
Again this has been covered before and it has to do with both arrays and dates, as well as many other type, being reference types.
One way to see that in fact these are the same object is not well documented in the Xojo documentation. Its buried in the Debugging pane of the preferences – Show Object IDs in variable lists.
Once you enable this setting what you see in the debugger pane makes it much easier to see when you have two references to the same object.
When viewing the following code
Dim ASource() As Integer = Array(1,2,3,4,5,6,7,8) Dim ATarget() As Integer ATarget = ASource
You can clearly see that ATarget and ASource have the same objectID. In Xojo’s runtime this means they are the same object – objectsID’s are unique to every instance and the only way you get two objectID’s that are the same is when two references refer to the same object.
I’d recommend always turning this setting on when debugging.
This question isnt asked that often. But I think it should be.
When you create classes, modules, layouts or anything else in Xojo you should make everything as private as it needs to be. And no more. And as public as it needs to be. And no more.
But exactly what does that mean ?
I would say that you should normally start with most things in classes being protected. This means that any subclasses can access the items in the class. But code outside the class cant access it. This gives you a decent way to sort out what API you want the class to expose and grow that exposed API over time rather than just making everything publicly accessible all the time.
Code and controls on layouts I would treat similarly and make them all private since you only have private or public to chose from.
For modules public is also a good default for many of the same reasons. But in the case of a method or property in a module that is public it CAN be accessed by code outside the module it just has to be fully qualified so there’s no ambiguity when you are using such a thing.
In my time as a product engineer at Xojo I fixed a lot of bugs and many times the issue turned out to be code outside some class, module or layout that was accessing and changing or calling a method that wasnt protected or private and it was doing so at an inopportune time and so it appeared to be a bug in the Xojo framework.
Properly encapsulate your code and expose only as much as needs to be exposed whether thats by methods, events or properties. And by doing this you will prevent all kinds of weird coding bugs in your own projects.
After writing the post about stable sorts I ported a version of stable quicksort to Xojo and have now posted it on GitHub
Often you want to sort into alphabetical order or numerical order. And there are various ways to accomplish this.
But what if you need to sort first numerically and then alphabetically and maybe several other additional criteria ? How does this affect the overall result ?
It might be nice to make it so that the second sort doesn’t break the ordering the first sort did. And there are sorting schemes that do this.
For instance if you had the following data :
and used a “stable sorting algorithm” then you should see the following (note that items have been numbered so its possible to keep track of which item is where in the newly sorted data)
Note that 26 appears twice in the input and, in the output the two instances of 26 retain their relative order. The 26 at item 6 appears in the output before the 26 in item 8.
Wikipedia defines a “stable sort” as
Stable sorting algorithms maintain the relative order of records with equal keys (i.e. values). That is, a sorting algorithm is stable if whenever there are two records R and S with the same key and with R appearing before S in the original list, R will appear before S in the sorted list.https://en.wikipedia.org/wiki/Category:Stable_sorts
Fortunately Xojo uses a RADIX sort which IS a stable sort so subsequent sorting wont ruin the relative order of elements. This code shows this occurring.
Dim rawData() As Integer = Array(35,33, 42,10,14,19,26,44,26,31) Dim indexes() As Integer Dim data() As Integer For i As Integer = 0 To rawData.Ubound indexes.append 0i data.append rawData(i) Next data.sortwith indexes Break
Whats harder to see is that if you then sort the data in another way that the relative orders are preserved in the result.
The following more complex code shows this. We first sort by ascending numeric value, and then by ascending alphabetical value.
Dim rawData() As Integer = Array(35,33, 42,10,14,19,26,44,26,31) Dim alphaRawData() As String = Array("f", "z", "c", "d", "e", "a", "b", "q", "s", "b") Dim indexes() As Integer Dim data() As Integer For i As Integer = 0 To rawData.Ubound indexes.append i data.append rawData(i) Next data.sortwith indexes, alphaRawData Break alphaRawData.SortWith data, indexes Break
Again note that the 26’s retain their relative order. Sorting multiple times doesnt ruin the relative order of the input items.
Even if we chnage the data so that the two 26’s use the same alphabetic value they will retain their relative order.
A question I was asked recently posed an interesting question about exceptions and the cost of using them as a general error handling mechanism.
Xojo uses whats know as “zero cost exception handling”. Essentially at runtime there is no penalty for having exception handling in place. It imposes no runtime overhead when NO exceptions are encountered. But, when exceptions are encountered, it can be “expensive”.
Expensive in this sense can mean it induces slowness or requires more memory. Or both.
So I put together a simple example that demonstrates the cost of using exception handling instead of error codes. Its very simple and uses a deprecated API that reported error codes instead of the newer one that raised an exception instead.
Its just a simple desktop application with a textarea on the default window and this code in the Window’s Open event
Dim f As folderitem = SpecialFolder.Desktop.Child("foo") Dim errorcodeStart As Double = Microseconds Dim errorCodeCount As Integer For i As Integer = 1 To 1000 Dim ts As TextInputStream = f.OpenasTextFile If f.LastErrorCode <> 0 Then errorCodeCount = errorCodeCount + 1 End If Next Dim errorcodeEnd As Double = Microseconds Dim exceptionStart As Double = Microseconds Dim exceptionCount As Integer For i As Integer = 1 To 1000 Try Dim ts As TextInputStream = TextInputStream.Open(f) Catch IOX As IOException exceptionCount = exceptionCount + 1 End Try Next Dim exceptionEnd As Double = Microseconds Dim errorTotal As Double = errorcodeEnd - errorcodeStart Dim exceptionTotal As Double = exceptionEnd - exceptionStart TextArea1.AppendText "1000 iterations" + EndOfLine TextArea1.AppendText "Error Code = " + Str(errorTotal) + "ms" + EndOfLine TextArea1.AppendText "Exceptions = " + Str(exceptionTotal) + "ms" + EndOfLine
In a debug run on my compute I get the following output.
1000 iterations Error Code = 28096.87ms Exceptions = 41711.62ms
The version using exceptions is juts about 50% slower over 1000 iterations when debugging.
In a version compiled with the DEFAULT setting the difference is less, but still present.
1000 iterations Error Code = 28367.42ms Exceptions = 35925.94ms
Exceptions are still about 25% slower than error codes. The Moderate optimization setting is similar
1000 iterations Error Code = 29292.96ms Exceptions = 34415.9ms
Aggressive settings remain similar
1000 iterations Error Code = 28222.49ms Exceptions = 35309.52ms
There are some advantages to exceptions. Unlike error codes they are impossible to ignore at runtime. At some point you MUST put code in place to handle them or your application will just quit with an unhandled exception error.
However, there’s nothing in Xojo that helps you make sure you have handled the possible exceptions that can be raised, and also nothing that tells you what exceptions might be raised.
So heads up before you dive into using exceptions everywhere as a general error handling mechanism in your applications. There are costs to doing this and they could manifest themselves in slower code or code that requires more memory. Or both.
Something I never really gave much thought about made me do a bit of a double take today.
If you assign a color literal to a color variable you get what might look like “funny” behaviour when compared to other types of variables.
For instance, if you do
Dim c As Color = &c12345
what you get in the color is the color value &c12345000, a right zero fill, instead of &c00012345, a left zero fill.
If however you do something like
Dim i32 As Int32 = &h12345
what you get is a 32 bit value that is analogous to &h00012345 and its left zero filled.
So why does a color do a zero fill on the “right” and yet an integer, which is also a 32 bit value, you get what looks like a zero fill on the left ?
I suppose internally the compiler is actually doing something like
Dim i32 As Int32 = Int32 (&h12345) Dim c As Color = Color(i32)
It first converts the &c notation into an Int32 which is then recast as a color and since a color, in hex, is actually AARRGGBB where a color is RRGGBBAA this is why you get the apparent “right zero fill” for a color.
One of those things you just take for granted and never really think about.
Now what got me even thinking about this ? The code editors display of a color literal.
It struck me that IF a color literal was left zero filled like you might assume it would be then this image SHOULD look like this
But, since I assume the compiler is doing the conversion of a color via an Int32. you get LEFT zero filling on the color constant and it shows up the way it does.
One of those things I just never really thought of in all the time I’ve used Xojo.
On the forum there was a suggestion that a person should use a container control that had a few controls embedded in it at design time. And then when using that container control that they should skip providing an API that the container presented and just reach inside the container and manipulate the controls it contain directly.
Personally I would recommend against this.
I’d start by saying when you create a container control ALL the controls in it should be private by default to prevent this. And that if you want to expose functionality of the controls on the container you do so by defining methods and events on the container that any code OUTSIDE the container can call or react to just as if the container control was any other single control and not a composite one like it is.
Why would I make such a recommendation ?
- good habits
- long term flexibility and maintainability
The first point is just that this is a good habit to get into. And the reason its a good habit is because of points 2, 3 and 4. Properly encapsulating and hiding the details from other bits of your code is a good thing. Code outside the container doesnt need to know HOW the container does what it does. Just that it does what is expected when you call its methods, change its properties and react to the events it exposes. Thats it. It should be a black box like the built in Xojo listbox, pushbutton, or any other built in control is. You dont need to know how those do what they do, just that they do what you expect when you call the methods, set the properties and react to their events.
And the bonus to doing this is that it makes the likelihood you, or others, can reuse your control in more places in your project or in other projects much higher because the control is self contained.
Long term it also lets you do things like completely swap out the implementation of the container for some other means and as long as you dont need to change the API nothing outside the container control even needs to be aware this has happened. This makes your own code easier to maintain since you no longer have to look through all the code outside of the container to know if you also need to alter it because something in the container changed.
These are all good things regardless of whether this code is for your own use, more general distribution or possibly for sale or to give away.
I’d encourage everyone to keep these things in mind when ever they write their own custom controls.