I'm trying to integrate the functionality of the Windows.Graphics.Printing3D
API into a WiseJ VB.Net app to create .3mf files.
The Printing3D methods depend on UWP, so I created a sub-domain that allows the methods to function. All is well until it hits my SaveTo3mf()
method, which utilizes FileSavePicker
. At this point I get an InvalidWindowHandle
exception and the method fails on this line:
Dim storageFile = Await savePicker.PickSaveFileAsync()
I've researched the problem and I understand or think I understand the problem is the sub-domain is operating outside the main domain, so it can't retrieve a window handle. My attempt to solve this is shown below by using IInitializeWithWindow
. I used Invoke()
believing it would return the method in question to the main domain, but the error persists.
I cobbled the code together and can't claim any expertise whatsoever in manipulating domains or threading. Is an alternate approach, or is there is a mistake in my implementation? The code compiles fine with the required references.
<ComImport>
<Guid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IInitializeWithWindow
Sub Initialize(ByVal hwnd As IntPtr)
End Interface
Delegate Sub Invoker(localPackage As Printing3D3MFPackage)
Public Async Sub Build3MF()
Dim packages = Await CreatePackageAsync()'method not shown, it seems to work properly once I added the sub-domain
Dim c1 As New FilePicker
Dim msd As Invoker = AddressOf c1.SaveTo3mf
msd.Invoke(packages)
End Sub
Private Class FilePicker
Inherits Page
Public Async Sub SaveTo3mf(localPackage As Printing3D3MFPackage)
Dim savePicker As FileSavePicker = New FileSavePicker()
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary
savePicker.DefaultFileExtension = ".3mf"
savePicker.FileTypeChoices.Add("3MF File", {".3mf"})
Dim hWnd = Me.Handle'I added this to see if it produced a result; it does
Dim initWindow As IInitializeWithWindow = CType(CObj(savePicker), IInitializeWithWindow)
initWindow.Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle)
Dim storageFile = Await savePicker.PickSaveFileAsync()'Fail point
If storageFile Is Nothing Then
Else
Using stream = Await localPackage.SaveAsync()
stream.Seek(0)
Using dataReader = New DataReader(stream)
Await dataReader.LoadAsync(CUInt(stream.Size))
Dim buffer = dataReader.ReadBuffer(CUInt(stream.Size))
Await FileIO.WriteBufferAsync(storageFile, buffer)
End Using
End Using
End If
End Sub
End Class
CodePudding user response:
As it happens for me programming is another word for learning the hard way. My vb.net understanding is being augmented by learning WiseJ. They have a simple function Application.Download(File,"FileName"). This allowed me to take the stream directly and download it applying a file name in the process. It doesn't have the elegance of allowing the user to select a location but the file is downloaded to the "Downloads" folder for the user to access.