Loading Image from Content to StorageFile^ in Metro C++ - c++

I am trying Share an Image in Windows 8 Metro C++ Application using Share Charm. To do so, I need to load image to StorageFile^ first. I assume it should looks like:
create_task(imageFile->GetFileFromPathAsync("Textures/title.png")).then([this](StorageFile^ storageFile)
{
imageFile = storageFile;
});
where imageFile is defined in header file
Windows::Storage::StorageFile^ imageFile;
This actual code would throw this exeption
An invalid parameter was passed to a function that considers invalid parameters fatal.
This seems to be very trivial, but there is a very little documentation about Sharing in Metro, and the only Microsoft example shows how to do sharing using FilePicker.
Would be very grateful if someone knows how to do it properly.

If "Textures" is coming from your application package, you should use StorageFile::GetFileFromApplicationUriAsync instead:
Uri^ uri = ref new Uri("ms-appx:///Assets/Logo.png");
create_task(StorageFile::GetFileFromApplicationUriAsync(uri)).then([](task<StorageFile^> t)
{
auto storageFile = t.get();
auto f = storageFile->FileType;
});
You can also use a task-based continuation (as I show above) in order to inspect the exception information more closely. In your case, the inner exception is: The specified path (Assets/Logo.png) contains one or more invalid characters.
This is due to the forward-slash, if you change it to a backslash you'll see: The specified path (Assets\Logo.png) is not an absolute path, and relative paths are not permitted.
If you want to use GetFileFromPathAsync I would recommend using
Windows::ApplicationModel::Package::Current->InstalledLocation
To figure out where your application is installed and building up your path from there.

Related

VSIX how to get current snapshot document name?

I have been trying to to create an extension that highlights specific line numbers for me in Visual Studio in the margins.
I manged to get my marking in the margins using predefined line number but for it to work properly I need to know what the current document FullName is (Path and filename)
After much googling I figured out how to do it with the sample code (which is not ideal)
DTE2 dte = (DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.15.0");
var activeDocument = dte.ActiveDocument;
var docName = activeDocument.Name;
var docFullName = activeDocument.FullName;
Now I know the problems here
is that is for specific version bases on the text
there is no way to select which instance (when running more than one VS)
It seems to be very slow
I have a feeling I should be doing this with MEF Attributes but the MS docs examples are so simple that they do not work for me. I scanned a few SO questions too and I just cannot get them to work. They mostly talk about Services.. which I do not have and have no idea how to get.
The rest of my code uses SnapshotSpans as in the example Extension of Todo_Classification examples which is great if you do NOT need to know the file name.
I have never done any extensions development. Please can somebody help me do this correctly.
You can use following code to get a file from a snapshot without any dependencies.
public string GetDocumentPath(Microsoft.VisualStudio.Text.ITextSnapshot ts)
{
Microsoft.VisualStudio.Text.ITextDocument textDoc;
bool rc = ts.TextBuffer.Properties.TryGetProperty(
typeof(Microsoft.VisualStudio.Text.ITextDocument), out textDoc);
if (rc && textDoc != null)
return textDoc.FilePath;
return null;
}
If you don't mind adding Microsoft.CodeAnalysis.EditorFeatures.Text to your project it will provide you with an extension method Document GetOpenDocumentInCurrentContextWithChanges() on the Microsoft.VisualStudio.Text.Snapshot class. (Plus many other Rosyln based helpers)
using Microsoft.CodeAnalysis.Text;
Document doc = span.Snapshot.GetOpenDocumentInCurrentContextWithChanges();

How to get localized names for Windows default folders in Qt

Using Qt, I can get some default path where I can create files via e. g. QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) which works fine on both Linux and Windows. I also saw that one can get a localized name for the respective location via QStandardPaths::displayName.
The "problem" is that, on Windows, the names of some default folders are displayed localized. For the above command, I get – according to the documentation – C:/Users/some_user/Documents. This is probably the actual path on the disk. But what the user (with a German locale) sees is a translated version: C:/Benutzer/some_user/Eigene Dokumente in this case.
So, not only the last folder is translated (the string I could get via the QStandardPaths::displayName call), but also the base directory.
Is there a reliable standard Qt way to be able to display the directory names the user knows from his other Windows programs?
It's not exactly what you are looking for but I think that can give an idea. You can get a default path by accessing to the Windows Environment Variables:
In C++ is really, we have a native function for that purpose:
inline auto get_environement_variable(const char* key ) {
char * val = getenv(key);
return (val == NULL) ? "" : std::string(val);
}
Some of the default environment variables:
auto programFiles = get_environement_variable("%ProgramW6432%");
auto programFilesX86 = get_environement_variable("%ProgramFiles(x86)%");
auto userProfile = get_environement_variable("%USERPROFILE%");
Maybe I'm wrong but I think that this is the one for the documents folder:
auto userProfile = get_environement_variable("%USERPROFILE%\Documents");
My OS is in English so I cannot confirm that the returned string is the translated one.

Convert URI to path

I am working on a Windows C++ App, where I get a URI similar to file:///C:/test 1/file.foo. Now I want to e.g. open that URI with ifstream.
Is there any C/C++ API available on Windows to convert such a path?
My Google Foo seems to be weak today.
There are multiple file URI "versions" so you should not parse it yourself, some of the APIs are broken as well.
If you just want a Windows style path, call PathCreateFromUrl.
If you don't want to convert the path then you must use CreateURLMonikerEx or SHParseDisplayName (with a bind context) but then you end up with a Windows IStream instead.
There is PathCreateFromUrl() :
https://msdn.microsoft.com/en-us/library/bb773581(v=vs.85).aspx

WinRT API WIndows::System::Launcher::LaunchFileAsync() usage from C++

I'm trying to launch an image using WinRT API WIndows::System::Launcher::LaunchFileAsync().
Code snippet is as follows:
RoInitialize(RO_INIT_MULTITHREADED);
String^ imagePath = ref new String(L"C:\\Users\\GoodMan\\Pictures\\wood.png");
auto file = Storage::StorageFile::GetFileFromPathAsync(imagePath);
Windows::System::Launcher::LaunchFileAsync(file);
I'm getting this error from the LaunchFileAsync() API:
error C2665: 'Windows::System::Launcher::LaunchFileAsync' : none of
the 2 overloads could convert all the argument types
Can I please get help how to solve this. I'm very new to WinRT C++ coding .
The method GetFileFromPathAsync does not return a StorageFile, but it returns IAsyncOperation<StorageFile>^. What you have to do is convert the latter to the former, as follows:
using namespace concurrency;
String^ imagePath = ref new String(L"C:\\Users\\GoodMan\\Pictures\\wood.png");
auto task = create_task(Windows::Storage::StorageFile::GetFileFromPathAsync(imagePath));
task.then([this](Windows::Storage::StorageFile^ file)
{
Windows::System::Launcher::LaunchFileAsync(file);
});
Generally all Windows Store app framework methods that end in Async will return either an IAsyncOperation, or a task. These methods are what are known as asynchronous methods, and require some special handling. See this article for more info: Asynchronous programming in C++ .
So now everything is great, correct? Well, not quite. There is another issue with your code. It is that when you run the code above, you will get an access-denied error. The reason is that Windows Store Apps are sandboxed, and you cannot generally access just any file on the filesystem.
You are in luck, though, because you are trying to access a file in your Pictures folder. The Pictures folder is a special folder that Windows Store apps have access to. You can get at it using the KnownFolders class:
using namespace concurrency;
Windows::Storage::StorageFolder^ pictures =
Windows::Storage::KnownFolders::PicturesLibrary;
auto task = create_task(pictures->GetFileAsync("wood.png"));
task.then([this](Windows::Storage::StorageFile^ file)
{
Windows::System::Launcher::LaunchFileAsync(file);
});
Note that in order to access the Pictures folder your application has to declare it in the project manifest. To do so, double click on the Package.appmanifest file in the project "tree" in Visual Studio, and select the Capabilities tab. Then under Capabilities, check Pictures Library.

How to disable cache in Windows 8 Xaml based ListView?

What I'm trying to do is to fill ListView in Windows 8 Metro application dynamically with pre-loaded images.
for each item (URI) I'm doing it plain simple with the code like this (C++):
Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapSrc =
ref new Windows::UI::Xaml::Media::Imaging::BitmapImage();
bitmapSrc->CreateOptions = Windows::UI::Xaml::Media::Imaging::BitmapCreateOptions::IgnoreImageCache;
bitmapSrc->UriSource = uri;
img->Source = bitmapSrc;
LoadListView->Items->Append(img);
but when I delete (in the app) source image described by URI and I create new file with the same name and try to reload it into the list then I fail and image shown is the old one (deleted). I presume some cache works here. I tried to avoid caching by IgnoreImageCache value in CreateOptions but it didn't work.
Any clues how to disable caching of BitmapSource (Image) potentially bound to ListView in Windows 8 app?
I tried several directions inspired by Silverlight and WPF, none worked unfortunately.
Encouraged by comments, I put answer I've found myself.
Broader context (and also C# perspective) is explained here:
http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/171dfe66-78b5-4340-bd78-244337f31287/
Shortly I believe it's a problem with reference counting here.
WinRT keeps the image loaded (cached) in BitmapImage^ as long as Uri is valid and asigned to the object instance, that in my example is added to the list.
Cleaning Uri from BitmapImage^ prior to releasing it from the list solved problem in my case.
According to example in question, below code solves the problem (included in the part where the list removal is performed):
auto item = (Image^)LoadListView->Items->GetAt(selected);
auto src = (Windows::UI::Xaml::Media::Imaging::BitmapImage^)item->Source;
src->UriSource = nullptr; //this line is critical
LoadListView->Items->RemoveAt(selected);