When using GetOpenFileName
, if the user types an URL in the open box, the function (at least in Windows 11) downloads in the background the file then it caches in a local folder somewhere under %user%\AppData\Local
and returns it to the user.
OPENFILENAME of = { 0 };
of.lStructSize = sizeof(of);
of.lpstrFilter = L"*.xml\0*.xml\0\0";
wchar_t fil[1000] = {};
of.lpstrFile = fil;
of.nMaxFile = 1000;
GetOpenFileName(&of); // if you paste an URL to the box, it gets it.
Best,
On modern Windows, GetOpenFileName is implemented by using the newer IFileOpenDialog interface.
You can use IFileOpenDialog
yourself directly instead using a code like this:
int main()
{
CoInitialize(nullptr);
IFileOpenDialog* dlg;
CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&dlg));
if (dlg)
{
if (SUCCEEDED(dlg->Show(nullptr)))
{
IShellItem* result;
if (SUCCEEDED(dlg->GetResult(&result)))
{
// a download or a cache access may happen here
IStream* stream;
if (SUCCEEDED(result->BindToHandler(nullptr, BHID_Stream, IID_PPV_ARGS(&stream))))
{
// you will get here if the download succeeded or if the url's download result was already in the cache
... read from the stream ...
stream->Release();
}
else
{
// the url download probably failed
}
result->Release();
}
}
dlg->Release();)
}
CoUninitialize();
}
Note in the case of urls, when we call IFileOpenDialog::GetResult
(s), we will get IShellItem
(s) back with their name being the url itself.
With these items, we can call IShellItem::BindToHandler
and ask for an IStream
interface. If the underlying operation succeeds (something is downloaded from the url or from a local cache), we can then read from that stream (note it's a readonly stream) to read the content w/o knowing where it was actually downloaded locally.
AFAIK there's no way to customize anything to these workings.
Internally it relies on SHParseDisplayName (from the desktop) and higher-level alike functions, so for example, you can do this too:
SHCreateItemFromParsingName(L"http://www.example.com", nullptr, IID_PPV_ARGS(&item));
item->BindToHandler(nullptr, BHID_Stream, IID_PPV_ARGS(&stream));