浏览代码

[WIP] Download zipped game resource file: WinRT (completion)

Lou Yihua 7 年之前
父节点
当前提交
f6a952a32f

+ 5 - 3
winrt/SDLPal.Common/DownloadDialog.xaml

@@ -10,10 +10,12 @@
     Title="正在下载……"
     PrimaryButtonText="停止"
     PrimaryButtonClick="OnPrimaryButtonClick"
-    MinHeight="0" MinWidth="0" Closing="OnClosing" Opened="OnOpened">
+    MinHeight="0" MinWidth="0"
+    Closing="OnClosing" Opened="OnOpened" SizeChanged="OnSizeChanged">
 
     <StackPanel Orientation="Vertical">
-        <ProgressBar x:Name="pbDownload" HorizontalAlignment="Stretch" Height="10" VerticalAlignment="Top" />
-        <TextBlock x:Name="tbProgress" HorizontalAlignment="Right" Text="0 / 0" />
+        <WebView x:Name="DownloadPage" NavigationStarting="OnNavigateStart" DOMContentLoaded="OnDOMContentLoaded" ScrollViewer.HorizontalScrollMode="Auto" ScrollViewer.VerticalScrollMode="Auto" />
+        <ProgressBar x:Name="pbDownload" HorizontalAlignment="Stretch" Height="12" Margin="0,8,0,4" />
+        <TextBlock x:Name="tbProgress" HorizontalAlignment="Right" Height="20" Margin="0,4,0,0" Text="0 / 0" />
     </StackPanel>
 </ContentDialog>

+ 229 - 160
winrt/SDLPal.Common/DownloadDialog.xaml.cpp

@@ -15,6 +15,7 @@
 using namespace SDLPal;
 
 using namespace Platform;
+using namespace Platform::Collections;
 using namespace Windows::Foundation;
 using namespace Windows::Foundation::Collections;
 using namespace Windows::Storage;
@@ -34,6 +35,8 @@ using namespace Windows::Web::Http;
 // https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“内容对话框”项模板
 
 static const uint32_t _buffer_size = 65536;
+static Platform::String^ const _url = "http://pal5q.baiyou100.com/pal5/download/98xjrq.html";
+static const wchar_t _postfix[] = L"/Pal98rqp.zip";
 
 struct zip_file
 {
@@ -44,12 +47,16 @@ struct zip_file
 	zip_file(IStream* s) : stream(s), hr(S_OK), cbBytes(0) {}
 };
 
-SDLPal::DownloadDialog::DownloadDialog(Platform::String^ link, Windows::ApplicationModel::Resources::ResourceLoader^ ldr, Windows::Storage::StorageFolder^ folder, Windows::Storage::Streams::IRandomAccessStream^ stream)
-	: m_link(link), m_stream(stream), m_Closable(false), m_InitialPhase(true), m_totalBytes(0), m_resLdr(ldr), m_folder(folder)
+SDLPal::DownloadDialog::DownloadDialog(Windows::ApplicationModel::Resources::ResourceLoader^ ldr, StorageFolder^ folder, IRandomAccessStream^ stream, double w, double h)
+	: m_stream(stream), m_Closable(false), m_InitialPhase(true), m_totalBytes(0), m_resLdr(ldr), m_folder(folder), m_width(w), m_height(h)
 {
 	InitializeComponent();
 
 	this->IsSecondaryButtonEnabled = false;
+	this->MaxWidth = w;
+	this->MaxHeight = h;
+	pbDownload->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
+	tbProgress->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
 }
 
 Platform::String^ SDLPal::DownloadDialog::FormatProgress()
@@ -85,177 +92,239 @@ void SDLPal::DownloadDialog::OnClosing(Windows::UI::Xaml::Controls::ContentDialo
 
 void SDLPal::DownloadDialog::OnOpened(Windows::UI::Xaml::Controls::ContentDialog^ sender, Windows::UI::Xaml::Controls::ContentDialogOpenedEventArgs^ args)
 {
-	concurrency::create_task([this]() {
-		Exception^ ex = nullptr;
-		auto client = ref new HttpClient();
-		try
-		{
-			concurrency::create_task(client->GetAsync(ref new Uri(m_link), HttpCompletionOption::ResponseHeadersRead)).then(
-				[this](HttpResponseMessage^ response)->IAsyncOperationWithProgress<IInputStream^, uint64_t>^ {
-				response->EnsureSuccessStatusCode();
-
-				bool determinate = response->Content->Headers->HasKey("Content-Length");
-				if (determinate)
-				{
-					m_totalBytes = wcstoull(response->Content->Headers->Lookup("Content-Length")->Data(), nullptr, 10);
-				}
-				this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, determinate]() {
-					pbDownload->Maximum = (double)m_totalBytes;
-					pbDownload->IsIndeterminate = !determinate;
-				}));
-				return response->Content->ReadAsInputStreamAsync();
-			}).then([this, client](IInputStream^ input) {
-				auto buffer = ref new Buffer(_buffer_size);
-				uint64_t bytes = 0;
-				HANDLE hEvent = CreateEventEx(nullptr, nullptr, 0, EVENT_ALL_ACCESS);
-				for (bool looping = true; looping; )
-				{
-					concurrency::create_task(input->ReadAsync(buffer, _buffer_size, InputStreamOptions::None)).then(
-						[this, &bytes, &looping](IBuffer^ result)->IAsyncOperationWithProgress<uint32_t, uint32_t>^ {
-						looping = (result->Length == _buffer_size) && !m_Closable;
-						bytes += result->Length;
-						this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, bytes]() {
-							pbDownload->Value = (double)bytes;
-							tbProgress->Text = FormatProgress();
-							UpdateLayout();
-						}));
-						return m_stream->WriteAsync(result);
-					}).then([this](uint32_t)->IAsyncOperation<bool>^ {
-						return m_stream->FlushAsync();
-					}).wait();
-				}
-				delete buffer;
-				delete client;
-				delete input;
-
-				this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, bytes]() {
-					this->Title = m_resLdr->GetString("Extracting");
-					pbDownload->Value = 0.0;
-					UpdateLayout();
-				}));
-
-				m_stream->Seek(0);
-
-				Microsoft::WRL::ComPtr<IStream> strm;
-				HRESULT hr;
-				if (FAILED(hr = CreateStreamOverRandomAccessStream(m_stream, IID_PPV_ARGS(&strm)))) throw ref new Platform::Exception(hr);
-
-				zlib_filefunc_def funcs = {
-					/* open  */ [](voidpf opaque, const char* filename, int mode)->voidpf { return new zip_file((IStream*)opaque); },
-					/* read  */ [](voidpf opaque, voidpf stream, void* buf, uLong size)->uLong {
-					auto zip = (zip_file*)stream;
-					return SUCCEEDED(zip->hr = zip->stream->Read(buf, size, &zip->cbBytes)) ? zip->cbBytes : 0;
-				},
-					/* write */ [](voidpf opaque, voidpf stream, const void* buf, uLong size)->uLong {
-					auto zip = (zip_file*)stream;
-					return SUCCEEDED(zip->hr = zip->stream->Write(buf, size, &zip->cbBytes)) ? zip->cbBytes : 0;
-				},
-					/* tell  */ [](voidpf opaque, voidpf stream)->long {
-					auto zip = (zip_file*)stream;
-					LARGE_INTEGER liPos = { 0 };
-					ULARGE_INTEGER uliPos;
-					return SUCCEEDED(zip->hr = zip->stream->Seek(liPos, STREAM_SEEK_CUR, &uliPos)) ? uliPos.LowPart : UNZ_ERRNO;
-				},
-					/* seek  */ [](voidpf opaque, voidpf stream, uLong offset, int origin)->long {
-					auto zip = (zip_file*)stream;
-					LARGE_INTEGER liPos = { offset };
-					ULARGE_INTEGER uliPos;
-					return SUCCEEDED(zip->hr = zip->stream->Seek(liPos, origin, &uliPos)) ? 0 : UNZ_ERRNO;
-				},
-					/* close */ [](voidpf opaque, voidpf stream)->int { delete (zip_file*)stream; return 0; },
-					/* error */ [](voidpf opaque, voidpf stream)->int { return reinterpret_cast<zip_file*>(stream)->hr; },
-					strm.Get()
-				};
-				unz_global_info ugi;
-				char szFilename[65536];
-				uLong filenum = 0;
-				bool success = true;
-
-				auto uzf = unzOpen2("", &funcs);
-				unzGetGlobalInfo(uzf, &ugi);
-				this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, ugi]() { pbDownload->Maximum = ugi.number_entry; UpdateLayout(); }));
-				for (auto ret = unzGoToFirstFile(uzf); ret == UNZ_OK; ret = unzGoToNextFile(uzf))
-				{
-					unz_file_info ufi;
-					if (UNZ_OK == unzGetCurrentFileInfo(uzf, &ufi, szFilename, sizeof(szFilename), nullptr, 0, nullptr, 0) &&
-						UNZ_OK == unzOpenCurrentFile(uzf))
+	DownloadPage->Width = m_width - 48;
+	DownloadPage->Height = m_height - 128;
+	UpdateLayout();
+	DownloadPage->Navigate(ref new Uri(_url));
+}
+
+
+void SDLPal::DownloadDialog::OnNavigateStart(Windows::UI::Xaml::Controls::WebView^ sender, Windows::UI::Xaml::Controls::WebViewNavigationStartingEventArgs^ args)
+{
+	auto url = args->Uri->RawUri;
+	args->Cancel = (Platform::String::CompareOrdinal(url, _url) != 0);
+
+	if (url->Length() >= _countof(_postfix) - 1 && _wcsicmp(url->Data() + url->Length() - (_countof(_postfix) - 1), _postfix) == 0)
+	{
+		DownloadPage->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
+		pbDownload->Visibility = Windows::UI::Xaml::Visibility::Visible;
+		tbProgress->Visibility = Windows::UI::Xaml::Visibility::Visible;
+		this->MaxHeight -= DownloadPage->ActualHeight - 48;
+		this->PrimaryButtonText = m_resLdr->GetString("ButtonBack");
+		this->Title = m_title;
+		this->UpdateLayout();
+		
+		concurrency::create_task([this, url]() {
+			Exception^ ex = nullptr;
+			auto client = ref new HttpClient();
+			try
+			{
+				concurrency::create_task(client->GetAsync(ref new Uri(url), HttpCompletionOption::ResponseHeadersRead)).then(
+					[this](HttpResponseMessage^ response)->IAsyncOperationWithProgress<IInputStream^, uint64_t>^ {
+					response->EnsureSuccessStatusCode();
+
+					bool determinate = response->Content->Headers->HasKey("Content-Length");
+					if (determinate)
 					{
-						std::auto_ptr<uint8_t> buf(new uint8_t[ufi.uncompressed_size]);
-						auto len = unzReadCurrentFile(uzf, buf.get(), ufi.uncompressed_size);
-						unzCloseCurrentFile(uzf);
-						if (len != ufi.uncompressed_size)
-						{
-							success = false;
-							break;
-						}
+						m_totalBytes = wcstoull(response->Content->Headers->Lookup("Content-Length")->Data(), nullptr, 10);
+					}
+					this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, determinate]() {
+						pbDownload->Maximum = (double)m_totalBytes;
+						pbDownload->IsIndeterminate = !determinate;
+					}));
+					return response->Content->ReadAsInputStreamAsync();
+				}).then([this, client](IInputStream^ input) {
+					auto buffer = ref new Buffer(_buffer_size);
+					uint64_t bytes = 0;
+					HANDLE hEvent = CreateEventEx(nullptr, nullptr, 0, EVENT_ALL_ACCESS);
+					for (bool looping = true; looping; )
+					{
+						concurrency::create_task(input->ReadAsync(buffer, _buffer_size, InputStreamOptions::None)).then(
+							[this, &bytes, &looping](IBuffer^ result)->IAsyncOperationWithProgress<uint32_t, uint32_t>^ {
+							looping = (result->Length == _buffer_size) && !m_Closable;
+							bytes += result->Length;
+							this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, bytes]() {
+								pbDownload->Value = (double)bytes;
+								tbProgress->Text = FormatProgress();
+								UpdateLayout();
+							}));
+							return m_stream->WriteAsync(result);
+						}).then([this](uint32_t)->IAsyncOperation<bool>^ {
+							return m_stream->FlushAsync();
+						}).wait();
+					}
+					delete buffer;
+					delete client;
+					delete input;
+
+					this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, bytes]() {
+						this->Title = m_resLdr->GetString("Extracting");
+						pbDownload->Value = 0.0;
+						UpdateLayout();
+					}));
+
+					m_stream->Seek(0);
+
+					Microsoft::WRL::ComPtr<IStream> strm;
+					HRESULT hr;
+					if (FAILED(hr = CreateStreamOverRandomAccessStream(m_stream, IID_PPV_ARGS(&strm)))) throw ref new Platform::Exception(hr);
+
+					zlib_filefunc_def funcs = {
+						/* open  */ [](voidpf opaque, const char* filename, int mode)->voidpf { return new zip_file((IStream*)opaque); },
+						/* read  */ [](voidpf opaque, voidpf stream, void* buf, uLong size)->uLong {
+						auto zip = (zip_file*)stream;
+						return SUCCEEDED(zip->hr = zip->stream->Read(buf, size, &zip->cbBytes)) ? zip->cbBytes : 0;
+					},
+						/* write */ [](voidpf opaque, voidpf stream, const void* buf, uLong size)->uLong {
+						auto zip = (zip_file*)stream;
+						return SUCCEEDED(zip->hr = zip->stream->Write(buf, size, &zip->cbBytes)) ? zip->cbBytes : 0;
+					},
+						/* tell  */ [](voidpf opaque, voidpf stream)->long {
+						auto zip = (zip_file*)stream;
+						LARGE_INTEGER liPos = { 0 };
+						ULARGE_INTEGER uliPos;
+						return SUCCEEDED(zip->hr = zip->stream->Seek(liPos, STREAM_SEEK_CUR, &uliPos)) ? uliPos.LowPart : UNZ_ERRNO;
+					},
+						/* seek  */ [](voidpf opaque, voidpf stream, uLong offset, int origin)->long {
+						auto zip = (zip_file*)stream;
+						LARGE_INTEGER liPos = { offset };
+						ULARGE_INTEGER uliPos;
+						return SUCCEEDED(zip->hr = zip->stream->Seek(liPos, origin, &uliPos)) ? 0 : UNZ_ERRNO;
+					},
+						/* close */ [](voidpf opaque, voidpf stream)->int { delete (zip_file*)stream; return 0; },
+						/* error */ [](voidpf opaque, voidpf stream)->int { return reinterpret_cast<zip_file*>(stream)->hr; },
+						strm.Get()
+					};
+					unz_global_info ugi;
+					char szFilename[65536];
+					uLong filenum = 0;
+					bool success = true;
 
-						auto local = m_folder;
-						uLong prev = 0;
-						for (uLong i = 0; i < ufi.size_filename; i++)
+					auto uzf = unzOpen2("", &funcs);
+					unzGetGlobalInfo(uzf, &ugi);
+					this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, ugi]() { pbDownload->Maximum = ugi.number_entry; UpdateLayout(); }));
+					for (auto ret = unzGoToFirstFile(uzf); ret == UNZ_OK; ret = unzGoToNextFile(uzf))
+					{
+						unz_file_info ufi;
+						if (UNZ_OK == unzGetCurrentFileInfo(uzf, &ufi, szFilename, sizeof(szFilename), nullptr, 0, nullptr, 0) &&
+							UNZ_OK == unzOpenCurrentFile(uzf))
 						{
-							if (szFilename[i] != '/') continue;
-							try
+							std::auto_ptr<uint8_t> buf(new uint8_t[ufi.uncompressed_size]);
+							auto len = unzReadCurrentFile(uzf, buf.get(), ufi.uncompressed_size);
+							unzCloseCurrentFile(uzf);
+							if (len != ufi.uncompressed_size)
+							{
+								success = false;
+								break;
+							}
+
+							auto local = m_folder;
+							uLong prev = 0;
+							for (uLong i = 0; i < ufi.size_filename; i++)
 							{
-								concurrency::create_task(local->GetFolderAsync(ConvertString(szFilename + prev, i - prev))).then([&local](StorageFolder^ sub) { local = sub; }).wait();
+								if (szFilename[i] != '/') continue;
+								try
+								{
+									concurrency::create_task(local->GetFolderAsync(ConvertString(szFilename + prev, i - prev))).then([&local](StorageFolder^ sub) { local = sub; }).wait();
+								}
+								catch (Exception^ e)
+								{
+									concurrency::create_task(local->CreateFolderAsync(ConvertString(szFilename + prev, i - prev))).then([&local](StorageFolder^ sub) { local = sub; }).wait();
+								}
+								prev = i + 1;
 							}
-							catch (Exception^ e)
+							if (prev < ufi.size_filename)
 							{
-								concurrency::create_task(local->CreateFolderAsync(ConvertString(szFilename + prev, i - prev))).then([&local](StorageFolder^ sub) { local = sub; }).wait();
+								IRandomAccessStream^ stm = nullptr;
+								StorageFile^ file = nullptr;
+								auto filename = ConvertString(szFilename + prev, ufi.size_filename - prev);
+								concurrency::create_task(local->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting)).then([&](StorageFile^ f)->IAsyncOperation<IRandomAccessStream^>^ {
+									return (file = f)->OpenAsync(Windows::Storage::FileAccessMode::ReadWrite);
+								}).then([&](IRandomAccessStream^ s)->IAsyncOperationWithProgress<uint32_t, uint32_t>^ {
+									return (stm = s)->WriteAsync(NativeBuffer::GetIBuffer(buf.get(), ufi.uncompressed_size));
+								}).then([&](uint32_t size)->IAsyncOperation<bool>^ {
+									if (size < ufi.uncompressed_size) throw ref new Exception(E_FAIL);
+									return stm->FlushAsync();
+								}).wait();
+								delete stm;
+								delete file;
 							}
-							prev = i + 1;
 						}
-						if (prev < ufi.size_filename)
+						else
 						{
-							IRandomAccessStream^ stm = nullptr;
-							StorageFile^ file = nullptr;
-							auto filename = ConvertString(szFilename + prev, ufi.size_filename - prev);
-							concurrency::create_task(local->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting)).then([&](StorageFile^ f)->IAsyncOperation<IRandomAccessStream^>^ {
-								return (file = f)->OpenAsync(Windows::Storage::FileAccessMode::ReadWrite);
-							}).then([&](IRandomAccessStream^ s)->IAsyncOperationWithProgress<uint32_t, uint32_t>^ {
-								return (stm = s)->WriteAsync(NativeBuffer::GetIBuffer(buf.get(), ufi.uncompressed_size));
-							}).then([&](uint32_t size)->IAsyncOperation<bool>^ {
-								if (size < ufi.uncompressed_size) throw ref new Exception(E_FAIL);
-								return stm->FlushAsync();
-							}).wait();
-							delete stm;
-							delete file;
+							success = false;
+							break;
 						}
+						filenum++;
+						this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, filenum, &ugi]() {
+							wchar_t buf[64];
+							swprintf_s(buf, L"%lu/%lu", filenum, ugi.number_entry);
+							pbDownload->Value = (double)filenum;
+							tbProgress->Text = ref new Platform::String(buf);
+							UpdateLayout();
+						}));
 					}
-					else
-					{
-						success = false;
-						break;
-					}
-					filenum++;
-					this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, filenum, &ugi]() {
-						wchar_t buf[64];
-						swprintf_s(buf, L"%lu/%lu", filenum, ugi.number_entry);
-						pbDownload->Value = (double)filenum;
-						tbProgress->Text = ref new Platform::String(buf);
-						UpdateLayout();
-					}));
-				}
-				unzClose(uzf);
+					unzClose(uzf);
 
-				if (!success) throw ref new Exception(E_FAIL);
-			}).wait();
-		}
-		catch (Exception^ e)
+					if (!success) throw ref new Exception(E_FAIL);
+				}).wait();
+			}
+			catch (Exception^ e)
+			{
+				ex = e; 
+			}
+
+			this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, ex]() {
+				Platform::String^ string;
+				if (m_Closable)
+					string = m_resLdr->GetString("MBDownloadCanceled");
+				else if (ex)
+					string = String::Concat(m_resLdr->GetString("MBDownloadError"), ex->Message);
+				else
+					string = m_resLdr->GetString("MBDownloadOK");
+				(ref new MessageDialog(string, m_resLdr->GetString("MBDownloadTitle")))->ShowAsync();
+				m_Closable = true;
+				Hide();
+			}));
+		});
+	}
+}
+
+
+void SDLPal::DownloadDialog::OnDOMContentLoaded(Windows::UI::Xaml::Controls::WebView^ sender, Windows::UI::Xaml::Controls::WebViewDOMContentLoadedEventArgs^ args)
+{
+	m_title = this->Title;
+	this->Title = sender->DocumentTitle;
+	sender->InvokeScriptAsync(ref new String(L"eval"), ref new Vector<String^>(1, ref new String(LR"rs(
+	var elems = document.getElementsByTagName('a');
+	for (var i = 0; i < elems.length; i++)
+	{
+		if (elems[i].href.indexOf('#') === -1)
 		{
-			ex = e; 
+			if (/\/Pal98rqp\.zip$/i.test(elems[i].href))
+			{
+				elems[i].target = '';
+				elems[i].focus();
+				var r = elems[i].getBoundingClientRect();
+				var y = (r.top + r.bottom - window.innerHeight) / 2 + window.scrollY;
+				var x = (r.left + r.right - window.innerWidth) / 2 + window.scrollX;
+				window.scroll(x, y);
+			}
+			else
+			{
+				elems[i].target = '_blank';
+			}
 		}
+	}
+)rs")));
+}
 
-		this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, ex]() {
-			Platform::String^ string;
-			if (m_Closable)
-				string = m_resLdr->GetString("MBDownloadCanceled");
-			else if (ex)
-				string = String::Concat(m_resLdr->GetString("MBDownloadError"), ex->Message);
-			else
-				string = m_resLdr->GetString("MBDownloadOK");
-			(ref new MessageDialog(string, m_resLdr->GetString("MBDownloadTitle")))->ShowAsync();
-			m_Closable = true;
-			Hide();
-		}));
-	});
+
+void SDLPal::DownloadDialog::OnSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e)
+{
+	if (DownloadPage->Visibility == Windows::UI::Xaml::Visibility::Visible)
+	{
+		DownloadPage->Width = e->NewSize.Width - 48;
+		DownloadPage->Height = e->NewSize.Height - 128;
+	}
 }

+ 6 - 2
winrt/SDLPal.Common/DownloadDialog.xaml.h

@@ -13,13 +13,14 @@ namespace SDLPal
 	public ref class DownloadDialog sealed
 	{
 	public:
-		DownloadDialog(Platform::String^ link, Windows::ApplicationModel::Resources::ResourceLoader^ ldr, Windows::Storage::StorageFolder^ folder, Windows::Storage::Streams::IRandomAccessStream^ stream);
+		DownloadDialog(Windows::ApplicationModel::Resources::ResourceLoader^ ldr, Windows::Storage::StorageFolder^ folder, Windows::Storage::Streams::IRandomAccessStream^ stream, double w, double h);
 
 	private:
-		Platform::String^ m_link;
 		Windows::ApplicationModel::Resources::ResourceLoader^ m_resLdr;
 		Windows::Storage::StorageFolder^ m_folder;
 		Windows::Storage::Streams::IRandomAccessStream^ m_stream;
+		Platform::Object^ m_title;
+		double m_width, m_height;
 		uint64_t m_totalBytes;
 		bool m_Closable, m_InitialPhase;
 
@@ -28,5 +29,8 @@ namespace SDLPal
 		void OnPrimaryButtonClick(Windows::UI::Xaml::Controls::ContentDialog^ sender, Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs^ args);
 		void OnClosing(Windows::UI::Xaml::Controls::ContentDialog^ sender, Windows::UI::Xaml::Controls::ContentDialogClosingEventArgs^ args);
 		void OnOpened(Windows::UI::Xaml::Controls::ContentDialog^ sender, Windows::UI::Xaml::Controls::ContentDialogOpenedEventArgs^ args);
+		void OnNavigateStart(Windows::UI::Xaml::Controls::WebView^ sender, Windows::UI::Xaml::Controls::WebViewNavigationStartingEventArgs^ args);
+		void OnDOMContentLoaded(Windows::UI::Xaml::Controls::WebView^ sender, Windows::UI::Xaml::Controls::WebViewDOMContentLoadedEventArgs^ args);
+		void OnSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
 	};
 }

+ 3 - 14
winrt/SDLPal.Common/MainPage.xaml

@@ -5,7 +5,7 @@
     xmlns:local="using:SDLPal"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-    mc:Ignorable="d" Loaded="Page_Loaded">
+    mc:Ignorable="d" Loaded="Page_Loaded" SizeChanged="OnSizeChanged">
 
     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
         <ScrollViewer HorizontalScrollMode="Disabled">
@@ -25,20 +25,9 @@
                         <ColumnDefinition Width="Auto"/>
                     </Grid.ColumnDefinitions>
                     <TextBox x:Name="tbGamePath" x:Uid="GamePath" Grid.Column="0" TextWrapping="Wrap" VerticalAlignment="Top" Header="游戏资源文件夹" IsReadOnly="True" PlaceholderText="未选择游戏资源文件夹"/>
-                    <Button x:Name="btnBrowseGame" x:Uid="ButtonBrowse" Grid.Column="1" Content="浏览" HorizontalAlignment="Left" VerticalAlignment="Bottom" Click="btnBrowseFolder_Click" />
-                </Grid>
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition/>
-                        <ColumnDefinition/>
-                        <ColumnDefinition/>
-                        <ColumnDefinition Width="Auto"/>
-                    </Grid.ColumnDefinitions>
-                    <RadioButton x:Name="rbDownloadLink1" x:Uid="DownloadLink1" Grid.Column="0" GroupName="DownloadLink" Content="地址 1" Tag="http://pal5q.baiyou100.com/pal5/download/98xjrq.html" />
-                    <RadioButton x:Name="rbDownloadLink2" x:Uid="DownloadLink2" Grid.Column="1" GroupName="DownloadLink" Content="地址 2" Tag="http://pal5q.baiyou100.com/pal5/download/98xjrq.html" />
-                    <RadioButton x:Name="rbDownloadLink3" x:Uid="DownloadLink3" Grid.Column="2" GroupName="DownloadLink" Content="地址 3" Tag="http://pal5q.baiyou100.com/pal5/download/98xjrq.html" />
-                    <Button x:Name="btnDownloadGame" x:Uid="ButtonDownload" Grid.Column="3" Content="下载游戏" HorizontalAlignment="Center" VerticalAlignment="Center" Click="btnDownloadGame_Click" IsEnabled="False" />
+                    <Button x:Name="btnBrowseGame" x:Uid="ButtonBrowse" Grid.Column="1" Content="浏览" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Click="btnBrowseFolder_Click" />
                 </Grid>
+                <Button x:Name="btnDownloadGame" x:Uid="ButtonDownload" Content="下载正版游戏资源" HorizontalAlignment="Center" Click="btnDownloadGame_Click" IsEnabled="False" />
                 <CheckBox x:Name="cbUseMsgFile" x:Uid="UseMessageFile" Content="自定义语言文件" Checked="cbUseFile_CheckChanged" Unchecked="cbUseFile_CheckChanged" />
                 <Grid x:Name="gridMsgFile">
                     <Grid.ColumnDefinitions>

+ 21 - 19
winrt/SDLPal.Common/MainPage.xaml.cpp

@@ -18,6 +18,7 @@ using namespace SDLPal;
 using namespace Platform;
 using namespace Windows::Foundation;
 using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::Core;
 using namespace Windows::UI::Popups;
 using namespace Windows::UI::Xaml;
 using namespace Windows::UI::Xaml::Controls;
@@ -34,6 +35,7 @@ static Platform::String^ log_file_exts[] = { ".log" };
 MainPage^ MainPage::Current = nullptr;
 
 MainPage::MainPage()
+	: m_dlg(nullptr)
 {
 	InitializeComponent();
 
@@ -59,10 +61,6 @@ MainPage::MainPage()
 
 	btnDownloadGame->IsEnabled = (tbGamePath->Text->Length() > 0);
 
-	RadioButton^ links[] = { rbDownloadLink1, rbDownloadLink2, rbDownloadLink3 };
-	srand(time(NULL));
-	links[rand() % 3]->IsChecked = true;
-
 	m_resLdr = Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView();
 	if (static_cast<App^>(Application::Current)->LastCrashed)
 	{
@@ -252,6 +250,7 @@ void SDLPal::MainPage::SetPath(Windows::Storage::StorageFolder^ folder)
 	{
 		tbGamePath->Text = folder->Path;
 		tbGamePath->Tag = folder;
+		btnDownloadGame->IsEnabled = true;
 	}
 }
 
@@ -332,18 +331,6 @@ void SDLPal::MainPage::Page_Loaded(Platform::Object^ sender, Windows::UI::Xaml::
 
 void SDLPal::MainPage::btnDownloadGame_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
 {
-	Platform::String^ link = nullptr;
-	Windows::UI::Xaml::Controls::RadioButton^ controls[] = {
-		this->rbDownloadLink1, this->rbDownloadLink2, this->rbDownloadLink3
-	};
-	for (int i = 0; i < 3; i++)
-	{
-		if (controls[i]->IsChecked->Value)
-		{
-			link = static_cast<Platform::String^>(controls[i]->Tag);
-			break;
-		}
-	}
 	auto folder = dynamic_cast<Windows::Storage::StorageFolder^>(tbGamePath->Tag);
 	auto msgbox = ref new MessageDialog(m_resLdr->GetString("MBDownloadMessage"), m_resLdr->GetString("MBDownloadTitle"));
 	msgbox->Commands->Append(ref new UICommand(m_resLdr->GetString("MBButtonOK"), nullptr, 1));
@@ -371,7 +358,7 @@ void SDLPal::MainPage::btnDownloadGame_Click(Platform::Object^ sender, Windows::
 		{
 			return concurrency::create_async([command]()->IUICommand^ { return command; });
 		}
-	}).then([this, folder, link](IUICommand^ command) {
+	}).then([this, folder](IUICommand^ command) {
 		if (command->Id != nullptr)
 		{
 			HANDLE hEvent = CreateEventEx(nullptr, nullptr, 0, EVENT_ALL_ACCESS);
@@ -379,8 +366,11 @@ void SDLPal::MainPage::btnDownloadGame_Click(Platform::Object^ sender, Windows::
 			{
 				auto file = AWait(folder->CreateFileAsync("pal98.zip", Windows::Storage::CreationCollisionOption::ReplaceExisting), hEvent);
 				auto stream = AWait(file->OpenAsync(Windows::Storage::FileAccessMode::ReadWrite), hEvent);
-				concurrency::create_task((ref new DownloadDialog(link, m_resLdr, folder, stream))->ShowAsync()).then(
-					[this, file, stream, hEvent](ContentDialogResult result) {
+				concurrency::create_task(this->Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, folder, file, stream]() {
+					m_dlg = ref new DownloadDialog(m_resLdr, folder, stream, ActualWidth, ActualHeight);
+				}))).then([this]()->IAsyncOperation<ContentDialogResult>^{
+					return m_dlg->ShowAsync();
+				}).then([this, file, stream, hEvent](ContentDialogResult result) {
 					delete stream;
 					AWait(file->DeleteAsync(), hEvent);
 					delete file;
@@ -395,3 +385,15 @@ void SDLPal::MainPage::btnDownloadGame_Click(Platform::Object^ sender, Windows::
 		}
 	});
 }
+
+
+void SDLPal::MainPage::OnSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e)
+{
+	if (m_dlg)
+	{
+		m_dlg->MaxWidth = e->NewSize.Width;
+		if (m_dlg->MaxHeight == e->PreviousSize.Height)
+			m_dlg->MaxHeight = e->NewSize.Height;
+		m_dlg->UpdateLayout();
+	}
+}

+ 2 - 0
winrt/SDLPal.Common/MainPage.xaml.h

@@ -61,6 +61,7 @@ namespace SDLPal
 		Platform::Collections::Map<Platform::String^, ButtonAttribute^>^ m_controls;
 		Windows::ApplicationModel::Resources::ResourceLoader^ m_resLdr;
 		std::map<PALCFG_ITEM, AccessListEntry^> m_acl;
+		Windows::UI::Xaml::Controls::ContentDialog^ m_dlg;
 
 		void btnBrowseFolder_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
 		void cbBGM_SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e);
@@ -77,5 +78,6 @@ namespace SDLPal
 		static MainPage^ Current;
 	private:
 		void btnDownloadGame_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+		void OnSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
 	};
 }

+ 64 - 69
winrt/SDLPal.Common/Strings/en/Resources.resw

@@ -121,25 +121,25 @@
     <value>SDL-based reimplementation of classic Chinese RPG "Xian Jian Qi Xia Zhuan".</value>
   </data>
   <data name="AspectRatio.Header" xml:space="preserve">
-    <value>Keep aspect ratio</value>
+    <value>keep aspect ratio</value>
   </data>
   <data name="AspectRatio.OffContent" xml:space="preserve">
-    <value>No</value>
+    <value>no</value>
   </data>
   <data name="AspectRatio.OnContent" xml:space="preserve">
-    <value>Yes</value>
+    <value>yes</value>
   </data>
   <data name="AudioBuffer.Header" xml:space="preserve">
-    <value>Audio buffer size</value>
+    <value>audio buffer size</value>
   </data>
   <data name="AudioBuffer.PlaceholderText" xml:space="preserve">
-    <value>Choose audio buffer size</value>
+    <value>choose audio buffer size</value>
   </data>
   <data name="BGM.Header" xml:space="preserve">
-    <value>Format of BGM</value>
+    <value>format of BGM</value>
   </data>
   <data name="BGM.PlaceholderText" xml:space="preserve">
-    <value>Choose format of BGM</value>
+    <value>choose format of BGM</value>
   </data>
   <data name="ButtonBrowse.Content" xml:space="preserve">
     <value>browse</value>
@@ -148,7 +148,7 @@
     <value>default setting</value>
   </data>
   <data name="ButtonDownload.Content" xml:space="preserve">
-    <value>download game</value>
+    <value>download a licensed copy of game resource</value>
   </data>
   <data name="ButtonFinish.Content" xml:space="preserve">
     <value>finish setting</value>
@@ -157,76 +157,67 @@
     <value>reset setting</value>
   </data>
   <data name="CD.Header" xml:space="preserve">
-    <value>Format of CD track</value>
+    <value>format of CD track</value>
   </data>
   <data name="CD.PlaceholderText" xml:space="preserve">
-    <value>Choose format of CD track</value>
+    <value>choose format of CD track</value>
   </data>
   <data name="Debug.Content" xml:space="preserve">
-    <value>Debug</value>
+    <value>debug</value>
   </data>
   <data name="Downloading.PrimaryButtonText" xml:space="preserve">
-    <value>Stop</value>
+    <value>stop</value>
   </data>
   <data name="Downloading.Title" xml:space="preserve">
-    <value>Downloading...</value>
-  </data>
-  <data name="DownloadLink1.Content" xml:space="preserve">
-    <value>link 1</value>
-  </data>
-  <data name="DownloadLink2.Content" xml:space="preserve">
-    <value>link 2</value>
-  </data>
-  <data name="DownloadLink3.Content" xml:space="preserve">
-    <value>link 3</value>
+    <value>downloading...</value>
   </data>
   <data name="EnableAVI.Header" xml:space="preserve">
-    <value>Enable AVI animation</value>
+    <value>enable AVI animation</value>
   </data>
   <data name="EnableAVI.OffContent" xml:space="preserve">
-    <value>No</value>
+    <value>no</value>
   </data>
   <data name="EnableAVI.OnContent" xml:space="preserve">
-    <value>Yes</value>
+    <value>yes</value>
   </data>
   <data name="Error.Content" xml:space="preserve">
-    <value>Error</value>
+    <value>error</value>
   </data>
   <data name="Extracting" xml:space="preserve">
-    <value>Extracting...</value>
+    <value>extracting...</value>
   </data>
   <data name="Fatal.Content" xml:space="preserve">
-    <value>Fatal</value>
+    <value>fatal</value>
   </data>
   <data name="FontFile.PlaceholderText" xml:space="preserve">
-    <value>No customized font file</value>
+    <value>no customized font file</value>
   </data>
   <data name="GamePath.Header" xml:space="preserve">
-    <value>Folder of game resource</value>
+    <value>folder of game resource files</value>
   </data>
   <data name="GamePath.PlaceholderText" xml:space="preserve">
-    <value>No folder selected</value>
+    <value>no folder selected</value>
   </data>
   <data name="Information.Content" xml:space="preserve">
-    <value>Informational</value>
+    <value>informational</value>
   </data>
   <data name="LogFile.PlaceholderText" xml:space="preserve">
-    <value>No logging file</value>
+    <value>no logging file</value>
   </data>
   <data name="LogFileType" xml:space="preserve">
-    <value>Log files</value>
+    <value>log files</value>
   </data>
   <data name="LogLevel.Header" xml:space="preserve">
-    <value>Logging level</value>
+    <value>logging level</value>
   </data>
   <data name="LogLevel.PlaceholderText" xml:space="preserve">
-    <value>Choose logging level</value>
+    <value>choose logging level</value>
   </data>
   <data name="MBButtonCancel" xml:space="preserve">
-    <value>&amp;cancel</value>
+    <value>cancel</value>
   </data>
   <data name="MBButtonOK" xml:space="preserve">
-    <value>&amp;ok</value>
+    <value>ok</value>
   </data>
   <data name="MBCrashContent" xml:space="preserve">
     <value>The program is abnormally terminated last time. The setting page has been launched for you. Please check if there are any incorrect settings.</value>
@@ -238,9 +229,9 @@
     <value>Download aborted due to error: </value>
   </data>
   <data name="MBDownloadMessage" xml:space="preserve">
-    <value>This App is about to download the free &amp; publicly available game resource from baiyou100.com to the folder you've just chosen.
-Please notice that all the copyright of the downloaded game resource belongs to its creator, Softstar, Inc. This App provides the download function here only for convenient purpose, and Softstar, Inc. may remove the download links at any time. Furthermore, you should take full responsibility for using the downloaded game resource which is completely irrelevant to the developers of this App.
-You have to agree the above declaration before you click 'ok' to start the downloading process. Otherwise, please click 'cancel' to return.</value>
+    <value>You're going to be brought to the download page provided by baiyou100.com, from where you can download the game resource to the folder you've just chosen. The download link will be automatically centered so that anyone who don't understand Chinese can download it without trouble.
+Please note that this download page is not provided by this App's creator, so we can't guarantee the availablity of the donwload link.
+Click 'ok' to continue or click 'cancel' to return.</value>
   </data>
   <data name="MBDownloadOK" xml:space="preserve">
     <value>Game resource has been successfully downloaded!</value>
@@ -259,95 +250,96 @@ You can use the main menu option inside the game to return to this page.</value>
     <value>Setting finished</value>
   </data>
   <data name="MBStartupMessage" xml:space="preserve">
-    <value>You need to choose the game resource folder before you can start the game. And for anyone who doesn't have the game resource for now, you can download it from its publisher for free by clicking the 'downloading game' button.
+    <value>You need to choose the folder that contains game resource files before you can start the game, because such files are NOT bundled due to copyright restrictions.
+But fortunately, these files can be downloaded freely from baiyou100.com, the publisher's website.  You'll be brought to this website by clicking the 'download' button after you've chosen a folder to save the downloaded files.
 Once you've finished the setting process, you will be brought to the game directly at next launch.</value>
   </data>
   <data name="MBStartupTitle" xml:space="preserve">
     <value>Welcome to SDLPal!</value>
   </data>
   <data name="MessageFile.PlaceholderText" xml:space="preserve">
-    <value>No customized message file</value>
+    <value>no customized message file</value>
   </data>
   <data name="MusicVolume.Header" xml:space="preserve">
-    <value>Music volume</value>
+    <value>music volume</value>
   </data>
   <data name="OPL.Header" xml:space="preserve">
-    <value>Type of OPL emulator</value>
+    <value>type of OPL emulator</value>
   </data>
   <data name="OPL.PlaceholderText" xml:space="preserve">
-    <value>Choose type of OPL emulator</value>
+    <value>choose type of OPL emulator</value>
   </data>
   <data name="OPLSR.Header" xml:space="preserve">
-    <value>Sample rate of OPL emulator</value>
+    <value>sample rate of OPL emulator</value>
   </data>
   <data name="OPLSR.PlaceholderText" xml:space="preserve">
-    <value>Choose sample rate of OPL emulator</value>
+    <value>choose sample rate of OPL emulator</value>
   </data>
   <data name="Publisher" xml:space="preserve">
     <value>SDLPAL development team</value>
   </data>
   <data name="Quality.Header" xml:space="preserve">
-    <value>Audio quality</value>
+    <value>audio quality</value>
   </data>
   <data name="Samplerate.Header" xml:space="preserve">
-    <value>Sample rate of audio output</value>
+    <value>sample rate of audio output</value>
   </data>
   <data name="Samplerate.PlaceholderText" xml:space="preserve">
-    <value>Choose sample rate of audio output</value>
+    <value>choose sample rate of audio output</value>
   </data>
   <data name="SoundVolume.Header" xml:space="preserve">
-    <value>Sound volume</value>
+    <value>sound volume</value>
   </data>
   <data name="Stereo.Header" xml:space="preserve">
-    <value>Stereo</value>
+    <value>stereo</value>
   </data>
   <data name="Stereo.OffContent" xml:space="preserve">
-    <value>No</value>
+    <value>no</value>
   </data>
   <data name="Stereo.OnContent" xml:space="preserve">
-    <value>Yes</value>
+    <value>yes</value>
   </data>
   <data name="SurroundOPL.Header" xml:space="preserve">
-    <value>Use surround OPL</value>
+    <value>use surround OPL</value>
   </data>
   <data name="SurroundOPL.OffContent" xml:space="preserve">
-    <value>No</value>
+    <value>no</value>
   </data>
   <data name="SurroundOPL.OnContent" xml:space="preserve">
-    <value>Yes</value>
+    <value>yes</value>
   </data>
   <data name="Title.Text" xml:space="preserve">
-    <value>Setting mode</value>
+    <value>setting mode</value>
   </data>
   <data name="TouchOverlay.Header" xml:space="preserve">
-    <value>Use touch overlay</value>
+    <value>use touch overlay</value>
   </data>
   <data name="TouchOverlay.OffContent" xml:space="preserve">
-    <value>No</value>
+    <value>no</value>
   </data>
   <data name="TouchOverlay.OnContent" xml:space="preserve">
-    <value>Yes</value>
+    <value>yes</value>
   </data>
   <data name="UseFontFile.Content" xml:space="preserve">
-    <value>Use customized font file</value>
+    <value>use customized font file</value>
   </data>
   <data name="UseLogFile.Content" xml:space="preserve">
-    <value>Log to file</value>
+    <value>log to file</value>
   </data>
   <data name="UseMessageFile.Content" xml:space="preserve">
-    <value>Customized message file</value>
+    <value>customized message file</value>
   </data>
   <data name="Verbose.Content" xml:space="preserve">
-    <value>Verbose</value>
+    <value>verbose</value>
   </data>
   <data name="Warning.Content" xml:space="preserve">
-    <value>Warning</value>
+    <value>warning</value>
   </data>
   <data name="MBButtonNo" xml:space="preserve">
-    <value>No</value>
+    <value>no</value>
   </data>
   <data name="MBButtonYes" xml:space="preserve">
-    <value>Yes</value>
+    <value>yes</value>
   </data>
   <data name="MBDownloadOverwrite" xml:space="preserve">
     <value>The current game resource in destination folder will be overwrited on a successful download. Continue?</value>
@@ -356,4 +348,7 @@ Once you've finished the setting process, you will be brought to the game direct
     <value>Missing required game resource in folder '{0}'.
 Please choose the correct folder or download game resource from the offical website!</value>
   </data>
+  <data name="ButtonBack" xml:space="preserve">
+    <value>back</value>
+  </data>
 </root>

+ 11 - 16
winrt/SDLPal.Common/Strings/zh-hans/Resources.resw

@@ -148,7 +148,7 @@
     <value>默认设置</value>
   </data>
   <data name="ButtonDownload.Content" xml:space="preserve">
-    <value>下载游戏资源</value>
+    <value>下载正版游戏资源</value>
   </data>
   <data name="ButtonFinish.Content" xml:space="preserve">
     <value>完成设置</value>
@@ -166,20 +166,11 @@
     <value>调试信息</value>
   </data>
   <data name="Downloading.PrimaryButtonText" xml:space="preserve">
-    <value>停止</value>
+    <value>返回</value>
   </data>
   <data name="Downloading.Title" xml:space="preserve">
     <value>正在下载……</value>
   </data>
-  <data name="DownloadLink1.Content" xml:space="preserve">
-    <value>地址 1</value>
-  </data>
-  <data name="DownloadLink2.Content" xml:space="preserve">
-    <value>地址 2</value>
-  </data>
-  <data name="DownloadLink3.Content" xml:space="preserve">
-    <value>地址 3</value>
-  </data>
   <data name="EnableAVI.Header" xml:space="preserve">
     <value>启用 AVI 过场动画</value>
   </data>
@@ -226,7 +217,7 @@
     <value>取消</value>
   </data>
   <data name="MBButtonOK" xml:space="preserve">
-    <value>确定(&amp;O)</value>
+    <value>确定</value>
   </data>
   <data name="MBCrashContent" xml:space="preserve">
     <value>上次程序异常退出,已显示设置页供您检查设置是否正确。</value>
@@ -238,9 +229,9 @@
     <value>下载已被如下错误中止:</value>
   </data>
   <data name="MBDownloadMessage" xml:space="preserve">
-    <value>本应用即将为您从baiyou100.com网站下载免费的《仙剑奇侠传 98柔情篇》游戏资源文件并保存于您所选择的文件夹中。
-您应知晓,该数据文件的版权归游戏开发方大宇资讯所有,本应用仅出于方便您进行游戏的目的在此提供下载功能,游戏开发方可能会随时移除相关下载链接。您同意,您对下载资源文件的使用仅代表您个人意愿,与本应用的开发者无关
-如您同意此约定,请点击“确定”按钮开始下载,否则请点击“取消”返回设置页面。</value>
+    <value>您即将进入由baiyou100.com提供的游戏资源文件下载页,您可从该页面下载免费的正版游戏资源文件并保存于您所选择的文件夹中。
+您应知晓,上述资源文件并非由本应用的开发方提供,故我们无法保证上述下载链接的可用性
+请点击“确定”按钮开始下载,或点击“取消”返回设置页面。</value>
   </data>
   <data name="MBDownloadOK" xml:space="preserve">
     <value>游戏资源下载已成功完成!</value>
@@ -259,7 +250,8 @@
     <value>设置已完成</value>
   </data>
   <data name="MBStartupMessage" xml:space="preserve">
-    <value>请您首先在设置页面中选择游戏资源所在文件夹后方可进入游戏;如您尚未拥有可执行的游戏资源,您也可以在选择文件夹后点击“下载游戏”按钮从游戏发行方网站下载免费游戏资源。
+    <value>由于受版权限制,游戏资源文件并未包含在本应用当中,您需要首先在设置页面中选择游戏资源所在文件夹后方可进入游戏。
+对于尚未拥有游戏资源者,目前可从baiyou100.com上下载免费的正版游戏资源,请在选择文件夹后点击“下载”按钮进入下载页面。
 一旦您完成设置,在您下一次启动本应用时将直接开始游戏进程。</value>
   </data>
   <data name="MBStartupTitle" xml:space="preserve">
@@ -355,4 +347,7 @@
   <data name="MBRequired" xml:space="preserve">
     <value>在文件夹“{0}”中缺少必需的游戏资源文件,请选择正确的文件夹或从官方网站下载游戏数据文件!</value>
   </data>
+  <data name="ButtonBack" xml:space="preserve">
+    <value>停止</value>
+  </data>
 </root>

+ 11 - 16
winrt/SDLPal.Common/Strings/zh-hant/Resources.resw

@@ -148,7 +148,7 @@
     <value>默認設定</value>
   </data>
   <data name="ButtonDownload.Content" xml:space="preserve">
-    <value>下載遊戲</value>
+    <value>下載正版遊戲資源</value>
   </data>
   <data name="ButtonFinish.Content" xml:space="preserve">
     <value>完成設定</value>
@@ -171,15 +171,6 @@
   <data name="Downloading.Title" xml:space="preserve">
     <value>正在下載……</value>
   </data>
-  <data name="DownloadLink1.Content" xml:space="preserve">
-    <value>地址 1</value>
-  </data>
-  <data name="DownloadLink2.Content" xml:space="preserve">
-    <value>地址 2</value>
-  </data>
-  <data name="DownloadLink3.Content" xml:space="preserve">
-    <value>地址 3</value>
-  </data>
   <data name="EnableAVI.Header" xml:space="preserve">
     <value>啟用 AVI 過場動畫</value>
   </data>
@@ -223,10 +214,10 @@
     <value>選擇日誌記錄級別</value>
   </data>
   <data name="MBButtonCancel" xml:space="preserve">
-    <value>取消(&amp;C)</value>
+    <value>取消</value>
   </data>
   <data name="MBButtonOK" xml:space="preserve">
-    <value>確定(&amp;O)</value>
+    <value>確定</value>
   </data>
   <data name="MBCrashContent" xml:space="preserve">
     <value>上次程式異常退出,已顯示設定頁供您檢查設定是否正確。</value>
@@ -238,9 +229,9 @@
     <value>下載已被如下錯誤中止:</value>
   </data>
   <data name="MBDownloadMessage" xml:space="preserve">
-    <value>本應用即將為您從baiyou100.com網站下載免費的《仙劍奇俠傳 98柔情篇》遊戲資源檔並保存於您所選擇的資料夾中。
-您應知曉,該資源檔的版權歸遊戲開發方大宇資訊所有,本應用僅出於方便您進行遊戲的目的在此提供下載功能,遊戲開發方可能會隨時移除相關下載連結。您同意,您對下載資源檔的使用僅代表您個人意願,與本應用的開發者無關
-如您同意此約定,請點擊「確定」按鈕開始下載,否則請點擊「取消」返回設置頁面。</value>
+    <value>您即將進入由baiyou100.com提供的遊戲資源檔下載頁,您可從該頁面下載免費的正版遊戲資源檔並保存於您所選擇的資料夾中。
+您應知曉,上述資源檔並非由本應用的開發方提供,故我們無法保證上述下載連結的可用性
+請點擊「確定」按鈕開始下載,或點擊「取消」返回設置頁面。</value>
   </data>
   <data name="MBDownloadOK" xml:space="preserve">
     <value>遊戲資源下載已成功完成!</value>
@@ -259,7 +250,8 @@
     <value>設定已完成</value>
   </data>
   <data name="MBStartupMessage" xml:space="preserve">
-    <value>請您首先在設置頁面中選擇遊戲資源所在資料夾後方可進入遊戲;如您尚未擁有可執行的遊戲資源,您也可以在選擇資料夾後點擊「下載遊戲」按鈕從遊戲發行方網站下載免費遊戲資源。
+    <value>由於受智慧產權限制,遊戲資源檔並未包含在本應用當中,您需要首先在設置頁面中選擇遊戲資源所在資料夾後方可進入遊戲。
+對於尚未擁有遊戲資源者,目前可從baiyou100.com上下載免費的正版遊戲資源,請在選擇資料夾後點擊「下載」按鈕進入下載頁面。
 一旦您完成設置,在您下一次啟動本應用時將直接開始遊戲進程。</value>
   </data>
   <data name="MBStartupTitle" xml:space="preserve">
@@ -355,4 +347,7 @@
   <data name="MBRequired" xml:space="preserve">
     <value>在檔案夾「{0}」中缺少必需的遊戲資源檔,請選擇正確的檔案夾或從官方網站下載遊戲資料檔案!</value>
   </data>
+  <data name="ButtonBack" xml:space="preserve">
+    <value>返回</value>
+  </data>
 </root>