872 lines
24 KiB
C++
Raw Normal View History

2015-05-29 01:47:26 +09:00
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <Commctrl.h>
#include <tchar.h>
#include <string>
#include <thread>
#include <atomic>
2015-06-03 03:01:56 +09:00
#include <chrono>
2015-05-29 01:47:26 +09:00
#include <boost/filesystem.hpp>
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <opencv2/opencv.hpp>
2015-05-29 01:47:26 +09:00
#include "resource.h"
#include "../common/waifu2x.h"
#include "CDialog.h"
#include "CControl.h"
#define WM_FAILD_CREATE_DIR (WM_APP + 5)
2015-06-03 03:01:56 +09:00
#define WM_ON_WAIFU2X_ERROR (WM_APP + 6)
2015-05-29 01:47:26 +09:00
#define WM_END_THREAD (WM_APP + 7)
const size_t AR_PATH_MAX(1024);
const int MinCommonDivisor = 50;
const int DefaultCommonDivisor = 128;
2015-05-29 01:47:26 +09:00
// http://stackoverflow.com/questions/10167382/boostfilesystem-get-relative-path
boost::filesystem::path relativePath(const boost::filesystem::path &path, const boost::filesystem::path &relative_to)
{
// create absolute paths
boost::filesystem::path p = boost::filesystem::absolute(path);
boost::filesystem::path r = boost::filesystem::absolute(relative_to);
// if root paths are different, return absolute path
if (p.root_path() != r.root_path())
return p;
// initialize relative path
boost::filesystem::path result;
// find out where the two paths diverge
boost::filesystem::path::const_iterator itr_path = p.begin();
boost::filesystem::path::const_iterator itr_relative_to = r.begin();
while (*itr_path == *itr_relative_to && itr_path != p.end() && itr_relative_to != r.end()) {
++itr_path;
++itr_relative_to;
}
// add "../" for each remaining token in relative_to
if (itr_relative_to != r.end()) {
++itr_relative_to;
while (itr_relative_to != r.end()) {
result /= "..";
++itr_relative_to;
}
}
// add remaining path
while (itr_path != p.end()) {
result /= *itr_path;
++itr_path;
}
return result;
}
std::vector<int> CommonDivisorList(const int N)
{
std::vector<int> list;
const int sq = sqrt(N);
for (int i = 1; i <= sq; i++)
{
if (N % i == 0)
list.push_back(i);
}
const int sqs = list.size();
for (int i = 0; i < sqs; i++)
list.push_back(N / list[i]);
std::sort(list.begin(), list.end());
return list;
}
2015-05-29 01:47:26 +09:00
// <20>_<EFBFBD>C<EFBFBD>A<EFBFBD><41><EFBFBD>O<EFBFBD>p
class DialogEvent
{
private:
HWND dh;
std::string input_str;
std::string output_str;
std::string mode;
int noise_level;
double scale_ratio;
std::string process;
std::string outputExt;
std::string inputFileExt;
int crop_size;
int batch_size;
std::vector<std::string> extList;
2015-05-29 01:47:26 +09:00
std::thread processThread;
std::atomic_bool cancelFlag;
std::string autoSetAddName;
bool isLastError;
2015-06-03 03:01:56 +09:00
std::string logMessage;
std::string usedProcess;
std::chrono::system_clock::duration cuDNNCheckTime;
std::chrono::system_clock::duration InitTime;
std::chrono::system_clock::duration ProcessTime;
2015-05-29 01:47:26 +09:00
private:
std::string AddName() const
{
std::string addstr("(" + mode + ")");
2015-05-29 01:47:26 +09:00
if (mode.find("noise") != mode.npos || mode.find("auto_scale") != mode.npos)
addstr += "(Level" + std::to_string(noise_level) + ")";
if (mode.find("scale") != mode.npos)
addstr += "(x" + std::to_string(scale_ratio) + ")";
return addstr;
}
bool SyncMember(const bool NotSyncCropSize)
2015-05-29 01:47:26 +09:00
{
bool ret = true;
{
char buf[AR_PATH_MAX] = "";
GetWindowTextA(GetDlgItem(dh, IDC_EDIT_INPUT), buf, _countof(buf));
buf[_countof(buf) - 1] = '\0';
input_str = buf;
}
{
char buf[AR_PATH_MAX] = "";
GetWindowTextA(GetDlgItem(dh, IDC_EDIT_OUTPUT), buf, _countof(buf));
buf[_countof(buf) - 1] = '\0';
output_str = buf;
}
if (SendMessage(GetDlgItem(dh, IDC_RADIO_MODE_NOISE), BM_GETCHECK, 0, 0))
mode = "noise";
else if (SendMessage(GetDlgItem(dh, IDC_RADIO_MODE_SCALE), BM_GETCHECK, 0, 0))
mode = "scale";
else if (SendMessage(GetDlgItem(dh, IDC_RADIO_MODE_NOISE_SCALE), BM_GETCHECK, 0, 0))
mode = "noise_scale";
else
mode = "auto_scale";
if (SendMessage(GetDlgItem(dh, IDC_RADIONOISE_LEVEL1), BM_GETCHECK, 0, 0))
noise_level = 1;
else
noise_level = 2;
{
char buf[AR_PATH_MAX] = "";
GetWindowTextA(GetDlgItem(dh, IDC_EDIT_SCALE_RATIO), buf, _countof(buf));
buf[_countof(buf) - 1] = '\0';
char *ptr = nullptr;
scale_ratio = strtod(buf, &ptr);
if (!ptr || *ptr != '\0' || scale_ratio <= 0.0)
2015-05-29 01:47:26 +09:00
{
scale_ratio = 2.0;
ret = false;
MessageBox(dh, TEXT("<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>0.0<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD><EFBFBD><EFBFBD><EFBFBD>K<EFBFBD>v<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD>"), TEXT("<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>["), MB_OK | MB_ICONERROR);
2015-05-29 01:47:26 +09:00
}
}
{
char buf[AR_PATH_MAX] = "";
GetWindowTextA(GetDlgItem(dh, IDC_EDIT_OUT_EXT), buf, _countof(buf));
buf[_countof(buf) - 1] = '\0';
outputExt = buf;
if (outputExt.length() > 0 && outputExt[0] != '.')
outputExt = "." + outputExt;
}
if (SendMessage(GetDlgItem(dh, IDC_RADIO_MODE_CPU), BM_GETCHECK, 0, 0))
process = "cpu";
else
process = "gpu";
{
char buf[AR_PATH_MAX] = "";
GetWindowTextA(GetDlgItem(dh, IDC_EDIT_INPUT_EXT_LIST), buf, _countof(buf));
buf[_countof(buf) - 1] = '\0';
inputFileExt = buf;
// input_extention_list<73>𕶎<EFBFBD><F095B68E><EFBFBD><EFBFBD>̔z<CC94><7A><EFBFBD>ɂ<EFBFBD><C982><EFBFBD>
typedef boost::char_separator<char> char_separator;
typedef boost::tokenizer<char_separator> tokenizer;
char_separator sep(":", "", boost::drop_empty_tokens);
tokenizer tokens(inputFileExt, sep);
for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter)
extList.push_back("." + *tok_iter);
2015-05-29 01:47:26 +09:00
}
if (!NotSyncCropSize)
{
char buf[AR_PATH_MAX] = "";
GetWindowTextA(GetDlgItem(dh, IDC_COMBO_CROP_SIZE), buf, _countof(buf));
buf[_countof(buf) - 1] = '\0';
char *ptr = nullptr;
crop_size = strtol (buf, &ptr, 10);
if (!ptr || *ptr != '\0' || crop_size <= 0)
{
crop_size = 128;
ret = false;
MessageBox(dh, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD><EFBFBD><EFBFBD><EFBFBD>K<EFBFBD>v<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD>"), TEXT("<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>["), MB_OK | MB_ICONERROR);
}
}
2015-05-29 01:47:26 +09:00
return ret;
}
void SetCropSizeList(const boost::filesystem::path &input_path)
{
HWND hcrop = GetDlgItem(dh, IDC_COMBO_CROP_SIZE);
int gcd = 1;
if (boost::filesystem::is_directory(input_path))
{
BOOST_FOREACH(const boost::filesystem::path& p, std::make_pair(boost::filesystem::recursive_directory_iterator(input_path),
boost::filesystem::recursive_directory_iterator()))
{
if (!boost::filesystem::is_directory(p) && std::find(extList.begin(), extList.end(), p.extension().string()) != extList.end())
{
auto mat = cv::imread(p.string(), cv::IMREAD_UNCHANGED);
if (mat.empty())
continue;
auto size = mat.size();
mat.release();
gcd = boost::math::gcd(size.width, size.height);
}
}
}
else
{
auto mat = cv::imread(input_path.string(), cv::IMREAD_UNCHANGED);
if (mat.empty())
return;
auto size = mat.size();
mat.release();
gcd = boost::math::gcd(size.width, size.height);
}
while (SendMessage(hcrop, CB_GETCOUNT, 0, 0) != 0)
SendMessage(hcrop, CB_DELETESTRING, 0, 0);
// <20>ő<EFBFBD><C591><EFBFBD><EFBFBD>񐔂̖񐔂̃<F1909482><CC83>X<EFBFBD>g<EFBFBD>
std::vector<int> list(CommonDivisorList(gcd));
// MinCommonDivisor<6F><72><EFBFBD><EFBFBD><EFBFBD>̖񐔍폜
list.erase(std::remove_if(list.begin(), list.end(), [](const int v)
{
return v < MinCommonDivisor;
}
), list.end());
if (list.size() == 0)
{
// gcd<63><64>MinCommonDivisor<6F><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>̗ݏ<CC97><DD8F><EFBFBD><EFBFBD>K<EFBFBD><4B><EFBFBD>ɒlj<C992><C789><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD>
for (int i = 64; i <= 512; i *= 2)
list.push_back(i);
}
else
{
int mindiff = INT_MAX;
for (int i = 0; i < list.size(); i++)
mindiff = std::min(mindiff, abs(DefaultCommonDivisor - list[i]));
// <20>S<EFBFBD>Ă̌<C482><CC8C>񐔂<EFBFBD>DefaultCommonDivisor<6F>Ƃ̍ŏ<CC8D><C58F>̍<EFBFBD><CC8D><EFBFBD>64<36>ȏ<EFBFBD><C88F>Ȃ<EFBFBD>DefaultCommonDivisor<6F>lj<EFBFBD>
if (mindiff >= 64)
{
list.push_back(DefaultCommonDivisor);
std::sort(list.begin(), list.end());
}
}
int mindiff = INT_MAX;
int defaultIndex = 0;
for (int i = 0; i < list.size(); i++)
{
const int n = list[i];
std::string str(std::to_string(n));
SendMessageA(hcrop, CB_ADDSTRING, 0, (LPARAM)str.c_str());
const int diff = abs(DefaultCommonDivisor - n);
if (diff < mindiff)
{
mindiff = diff;
defaultIndex = i;
}
}
if (GetWindowTextLength(hcrop) == 0)
SendMessage(hcrop, CB_SETCURSEL, defaultIndex, 0);
}
2015-05-29 01:47:26 +09:00
void ProcessWaifu2x()
{
const boost::filesystem::path input_path(boost::filesystem::absolute(input_str));
2015-06-03 03:01:56 +09:00
std::vector<std::pair<std::string, std::string>> file_paths;
2015-05-29 01:47:26 +09:00
if (boost::filesystem::is_directory(input_path)) // input_path<74><68><EFBFBD>t<EFBFBD>H<EFBFBD><48><EFBFBD>_<EFBFBD>Ȃ炻<C882>̃f<CC83>B<EFBFBD><42><EFBFBD>N<EFBFBD>g<EFBFBD><67><EFBFBD>ȉ<EFBFBD><C889>̉摜<CC89>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϊ<EFBFBD>
{
boost::filesystem::path output_path(output_str);
output_path = boost::filesystem::absolute(output_path);
if (!boost::filesystem::exists(output_path))
{
if (!boost::filesystem::create_directory(output_path))
{
SendMessage(dh, WM_FAILD_CREATE_DIR, (WPARAM)&output_path, 0);
PostMessage(dh, WM_END_THREAD, 0, 0);
// printf("<22>o<EFBFBD>̓t<CD83>H<EFBFBD><48><EFBFBD>_<EFBFBD>u%s<>v<EFBFBD>̍쐬<CC8D>Ɏ<EFBFBD><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>\n", output_path.string().c_str());
return;
}
}
// <20>ϊ<EFBFBD><CF8A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̓<EFBFBD><CC93>́A<CD81>o<EFBFBD>̓p<CD83>X<EFBFBD><58><EFBFBD>
const auto func = [this, &input_path, &output_path, &file_paths](const boost::filesystem::path &path)
2015-05-29 01:47:26 +09:00
{
BOOST_FOREACH(const boost::filesystem::path& p, std::make_pair(boost::filesystem::recursive_directory_iterator(path),
boost::filesystem::recursive_directory_iterator()))
{
if (!boost::filesystem::is_directory(p) && std::find(extList.begin(), extList.end(), p.extension().string()) != extList.end())
{
const auto out_relative = relativePath(p, input_path);
const auto out_absolute = output_path / out_relative;
const auto out = (out_absolute.branch_path() / out_absolute.stem()).string() + outputExt;
file_paths.emplace_back(p.string(), out);
}
}
return true;
};
if (!func(input_path))
return;
for (const auto &p : file_paths)
{
const boost::filesystem::path out_path(p.second);
const boost::filesystem::path out_dir(out_path.parent_path());
if (!boost::filesystem::exists(out_dir))
{
if (!boost::filesystem::create_directories(out_dir))
{
SendMessage(dh, WM_FAILD_CREATE_DIR, (WPARAM)&out_dir, 0);
PostMessage(dh, WM_END_THREAD, 0, 0);
//printf("<22>o<EFBFBD>̓t<CD83>H<EFBFBD><48><EFBFBD>_<EFBFBD>u%s<>v<EFBFBD>̍쐬<CC8D>Ɏ<EFBFBD><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>\n", out_absolute.string().c_str());
return;
}
}
}
}
else
file_paths.emplace_back(input_str, output_str);
bool isFirst = true;
const auto ProgessFunc = [this, &isFirst](const int ProgressFileMax, const int ProgressFileNow)
{
if (isFirst)
{
isFirst = true;
SendMessage(GetDlgItem(dh, IDC_PROGRESS), PBM_SETRANGE32, 0, ProgressFileMax);
}
SendMessage(GetDlgItem(dh, IDC_PROGRESS), PBM_SETPOS, ProgressFileNow, 0);
};
2015-06-03 03:01:56 +09:00
const auto cuDNNCheckStartTime = std::chrono::system_clock::now();
2015-06-03 03:01:56 +09:00
if (process == "gpu")
Waifu2x::can_use_cuDNN();
2015-06-03 03:01:56 +09:00
const auto cuDNNCheckEndTime = std::chrono::system_clock::now();
Waifu2x::eWaifu2xError ret;
Waifu2x w;
ret = w.init(__argc, __argv, mode, noise_level, scale_ratio, "models", process, crop_size, batch_size);
2015-06-03 03:01:56 +09:00
if(ret != Waifu2x::eWaifu2xError_OK)
SendMessage(dh, WM_ON_WAIFU2X_ERROR, (WPARAM)&ret, 0);
else
2015-05-29 01:47:26 +09:00
{
2015-06-03 03:01:56 +09:00
const auto InitEndTime = std::chrono::system_clock::now();
2015-05-29 01:47:26 +09:00
2015-06-03 03:01:56 +09:00
for (const auto &p : file_paths)
{
ret = w.waifu2x(p.first, p.second, [this]()
{
return cancelFlag;
});
if (ret != Waifu2x::eWaifu2xError_OK)
{
SendMessage(dh, WM_ON_WAIFU2X_ERROR, (WPARAM)&ret, (LPARAM)&p);
if (ret == Waifu2x::eWaifu2xError_Cancel)
break;
}
}
const auto ProcessEndTime = std::chrono::system_clock::now();
cuDNNCheckTime = cuDNNCheckEndTime - cuDNNCheckStartTime;
InitTime = InitEndTime - cuDNNCheckEndTime;
ProcessTime = ProcessEndTime - InitEndTime;
usedProcess = w.used_process();
}
2015-05-29 01:47:26 +09:00
PostMessage(dh, WM_END_THREAD, 0, 0);
}
void ReplaceAddString()
{
SyncMember(true);
2015-05-29 01:47:26 +09:00
const boost::filesystem::path output_path(output_str);
std::string stem = output_path.stem().string();
if (stem.length() > 0 && stem.length() >= autoSetAddName.length())
{
const std::string base = stem.substr(0, stem.length() - autoSetAddName.length());
stem.erase(0, base.length());
if (stem == autoSetAddName)
{
const std::string addstr(AddName());
autoSetAddName = addstr;
boost::filesystem::path new_out_path = output_path.branch_path() / (base + addstr + outputExt);
SetWindowTextA(GetDlgItem(dh, IDC_EDIT_OUTPUT), new_out_path.string().c_str());
}
}
}
2015-06-03 03:01:56 +09:00
void AddLogMessage(const char *msg)
{
if (logMessage.length() == 0)
logMessage += msg;
else
logMessage += std::string("\r\n") + msg;
SetWindowTextA(GetDlgItem(dh, IDC_EDIT_LOG), logMessage.c_str());
}
void Waifu2xTime()
{
char msg[1024 * 2];
char *ptr = msg;
{
std::string p(usedProcess);
if (p == "cpu")
p = "CPU";
else if (p == "gpu")
p = "CUDA";
2015-06-03 03:01:56 +09:00
else if (p == "cudnn")
p = "cuDNN";
ptr += sprintf(ptr, "<EFBFBD>g<EFBFBD>p<EFBFBD>v<EFBFBD><EFBFBD><EFBFBD>Z<EFBFBD>b<EFBFBD>T<EFBFBD>[<5B><><EFBFBD>[<5B>h: %s\r\n", p.c_str());
}
{
uint64_t t = std::chrono::duration_cast<std::chrono::milliseconds>(ProcessTime).count();
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %02d:%02d:%02d.%d\r\n", hour, min, sec, msec);
}
{
uint64_t t = std::chrono::duration_cast<std::chrono::milliseconds>(InitTime).count();
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %02d:%02d:%02d.%d\r\n", hour, min, sec, msec);
}
if (process == "gpu" || process == "cudnn")
{
uint64_t t = std::chrono::duration_cast<std::chrono::milliseconds>(cuDNNCheckTime).count();
const int msec = t % 1000; t /= 1000;
const int sec = t % 60; t /= 60;
const int min = t % 60; t /= 60;
const int hour = (int)t;
ptr += sprintf(ptr, "cuDNN<EFBFBD>`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD><EFBFBD>: %02d:%02d:%02d.%d", hour, min, sec, msec);
}
AddLogMessage(msg);
}
2015-05-29 01:47:26 +09:00
public:
DialogEvent() : dh(nullptr), mode("noise_scale"), noise_level(1), scale_ratio(2.0), process("gpu"), outputExt("png"), inputFileExt("png:jpg:jpeg:tif:tiff:bmp"),
crop_size(128), batch_size(1), isLastError(false)
2015-05-29 01:47:26 +09:00
{
}
void Exec(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{
if (processThread.joinable())
return;
SyncMember(false);
2015-05-29 01:47:26 +09:00
if (input_str.length() == 0)
{
MessageBox(dh, TEXT("<EFBFBD><EFBFBD><EFBFBD>̓p<EFBFBD>X<EFBFBD><EFBFBD><EFBFBD>w<EFBFBD><EFBFBD>ĉ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TEXT("<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>["), MB_OK | MB_ICONERROR);
return;
}
if (output_str.length() == 0)
{
MessageBox(dh, TEXT("<EFBFBD>o<EFBFBD>̓p<EFBFBD>X<EFBFBD><EFBFBD><EFBFBD>w<EFBFBD><EFBFBD>ĉ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TEXT("<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>["), MB_OK | MB_ICONERROR);
return;
}
if (outputExt.length() == 0)
{
MessageBox(dh, TEXT("<EFBFBD>o<EFBFBD>͊g<EFBFBD><EFBFBD><EFBFBD>q<EFBFBD><EFBFBD><EFBFBD>w<EFBFBD><EFBFBD>ĉ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TEXT("<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>["), MB_OK | MB_ICONERROR);
return;
}
SendMessage(GetDlgItem(dh, IDC_PROGRESS), PBM_SETPOS, 0, 0);
cancelFlag = false;
isLastError = false;
processThread = std::thread(std::bind(&DialogEvent::ProcessWaifu2x, this));
EnableWindow(GetDlgItem(dh, IDC_BUTTON_CANCEL), TRUE);
EnableWindow(GetDlgItem(dh, IDC_BUTTON_EXEC), FALSE);
EnableWindow(GetDlgItem(dh, IDC_BUTTON_CHECK_CUDNN), FALSE);
SetWindowTextA(GetDlgItem(hWnd, IDC_EDIT_LOG), "");
2015-06-03 03:01:56 +09:00
logMessage.clear();
2015-05-29 01:47:26 +09:00
}
void WaitThreadExit(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{
processThread.join();
EnableWindow(GetDlgItem(dh, IDC_BUTTON_CANCEL), FALSE);
EnableWindow(GetDlgItem(dh, IDC_BUTTON_EXEC), TRUE);
EnableWindow(GetDlgItem(dh, IDC_BUTTON_CHECK_CUDNN), TRUE);
2015-05-29 01:47:26 +09:00
if (!isLastError)
{
2015-06-03 03:01:56 +09:00
if (!cancelFlag)
AddLogMessage("<EFBFBD>ϊ<EFBFBD><EFBFBD>ɐ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>");
2015-06-03 03:01:56 +09:00
Waifu2xTime();
MessageBeep(MB_ICONASTERISK);
}
2015-06-03 03:01:56 +09:00
else
MessageBoxA(dh, "<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>", "<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>[", MB_OK | MB_ICONERROR);
}
2015-05-29 01:47:26 +09:00
void OnDialogEnd(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{
if (!processThread.joinable())
PostQuitMessage(0);
else
MessageBeep(MB_ICONEXCLAMATION);
}
void OnFaildCreateDir(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{
const boost::filesystem::path *p = (const boost::filesystem::path *)wParam;
// <20>o<EFBFBD>̓t<CD83>H<EFBFBD><48><EFBFBD>_<EFBFBD>u%s<>v<EFBFBD>̍쐬<CC8D>Ɏ<EFBFBD><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>\n", out_absolute.string().c_str());
std::wstring msg(L"<EFBFBD>o<EFBFBD>̓t<EFBFBD>H<EFBFBD><EFBFBD><EFBFBD>_\r\n<EFBFBD>u");
msg += p->wstring();
msg += L"<EFBFBD>v\r\n<EFBFBD>̍쐬<EFBFBD>Ɏ<EFBFBD><EFBFBD>s<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>";
MessageBox(dh, msg.c_str(), TEXT("<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>["), MB_OK | MB_ICONERROR);
isLastError = true;
}
2015-06-03 03:01:56 +09:00
void OnWaifu2xError(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
2015-05-29 01:47:26 +09:00
{
2015-06-03 03:01:56 +09:00
const Waifu2x::eWaifu2xError ret = *(const Waifu2x::eWaifu2xError *)wParam;
2015-05-29 01:47:26 +09:00
2015-06-03 03:01:56 +09:00
if (ret != Waifu2x::eWaifu2xError_OK)
2015-05-29 01:47:26 +09:00
{
char msg[1024] = "";
2015-06-03 03:01:56 +09:00
if (lParam == 0)
2015-05-29 01:47:26 +09:00
{
2015-06-03 03:01:56 +09:00
switch (ret)
{
case Waifu2x::eWaifu2xError_Cancel:
sprintf(msg, "<EFBFBD>L<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Z<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>");
break;
case Waifu2x::eWaifu2xError_InvalidParameter:
sprintf(msg, "<EFBFBD>p<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>[<5B>^<5E><><EFBFBD>s<EFBFBD><73><EFBFBD>ł<EFBFBD>");
break;
case Waifu2x::eWaifu2xError_FailedOpenModelFile:
sprintf(msg, "<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD><EFBFBD><EFBFBD>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD><EFBFBD>ł<EFBFBD><C582><EFBFBD>");
break;
case Waifu2x::eWaifu2xError_FailedParseModelFile:
sprintf(msg, "<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD><EFBFBD><EFBFBD>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD>");
break;
case Waifu2x::eWaifu2xError_FailedConstructModel:
sprintf(msg, "<EFBFBD>l<EFBFBD>b<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>[<5B>N<EFBFBD>̍\<EFBFBD>z<EFBFBD>Ɏ<EFBFBD><EFBFBD>s<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>");
break;
}
2015-05-29 01:47:26 +09:00
}
2015-06-03 03:01:56 +09:00
else
2015-05-29 01:47:26 +09:00
{
2015-06-03 03:01:56 +09:00
const auto &fp = *(const std::pair<std::string, std::string> *)lParam;
2015-05-29 01:47:26 +09:00
2015-06-03 03:01:56 +09:00
switch (ret)
2015-05-29 01:47:26 +09:00
{
2015-06-03 03:01:56 +09:00
case Waifu2x::eWaifu2xError_Cancel:
sprintf(msg, "<EFBFBD>L<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Z<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>");
break;
case Waifu2x::eWaifu2xError_InvalidParameter:
2015-05-29 01:47:26 +09:00
sprintf(msg, "<EFBFBD>p<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>[<5B>^<5E><><EFBFBD>s<EFBFBD><73><EFBFBD>ł<EFBFBD>");
break;
2015-06-03 03:01:56 +09:00
case Waifu2x::eWaifu2xError_FailedOpenInputFile:
sprintf(msg, "<EFBFBD><EFBFBD><EFBFBD>͉摜<EFBFBD>u%s<>v<EFBFBD><76><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD><EFBFBD>ł<EFBFBD><C582><EFBFBD>", fp.first.c_str());
2015-05-29 01:47:26 +09:00
break;
2015-06-03 03:01:56 +09:00
case Waifu2x::eWaifu2xError_FailedOpenOutputFile:
sprintf(msg, "<EFBFBD>o<EFBFBD>͉摜<EFBFBD><EFBFBD><EFBFBD>u%s<>v<EFBFBD>ɏ<EFBFBD><C98F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߂܂<DF82><DC82><EFBFBD><EFBFBD>ł<EFBFBD><C582><EFBFBD>", fp.second.c_str());
2015-05-29 01:47:26 +09:00
break;
2015-06-03 03:01:56 +09:00
case Waifu2x::eWaifu2xError_FailedProcessCaffe:
2015-05-29 01:47:26 +09:00
sprintf(msg, "<EFBFBD><EFBFBD><EFBFBD>ԏ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ɏ<EFBFBD><EFBFBD>s<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>");
break;
}
}
2015-06-03 03:01:56 +09:00
AddLogMessage(msg);
2015-05-29 01:47:26 +09:00
2015-06-03 03:01:56 +09:00
if (ret != Waifu2x::eWaifu2xError_Cancel)
isLastError = true;
2015-05-29 01:47:26 +09:00
}
}
void Create(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{
dh = hWnd;
SendMessage(GetDlgItem(hWnd, IDC_RADIO_MODE_NOISE_SCALE), BM_SETCHECK, BST_CHECKED, 0);
SendMessage(GetDlgItem(hWnd, IDC_RADIONOISE_LEVEL1), BM_SETCHECK, BST_CHECKED, 0);
SendMessage(GetDlgItem(hWnd, IDC_RADIO_MODE_GPU), BM_SETCHECK, BST_CHECKED, 0);
EnableWindow(GetDlgItem(dh, IDC_BUTTON_CANCEL), FALSE);
char text[] = "2.00";
SetWindowTextA(GetDlgItem(hWnd, IDC_EDIT_SCALE_RATIO), text);
SetWindowTextA(GetDlgItem(hWnd, IDC_EDIT_OUT_EXT), outputExt.c_str());
SetWindowTextA(GetDlgItem(hWnd, IDC_EDIT_INPUT_EXT_LIST), inputFileExt.c_str());
}
void Cancel(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{
cancelFlag = true;
EnableWindow(GetDlgItem(dh, IDC_BUTTON_CANCEL), FALSE);
}
void RadioButtom(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{
ReplaceAddString();
}
void CheckCUDNN(HWND hWnd, WPARAM wParam, LPARAM lParam, LPVOID lpData)
{
switch (Waifu2x::can_use_cuDNN())
{
case Waifu2x::eWaifu2xcuDNNError_OK:
2015-05-29 01:47:26 +09:00
MessageBox(dh, TEXT("cuDNN<EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD>"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), MB_OK | MB_ICONINFORMATION);
break;
case Waifu2x::eWaifu2xcuDNNError_NotFind:
MessageBox(dh, TEXT("cuDNN<EFBFBD>͎g<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>\r\n<EFBFBD>ucudnn64_65.dll<6C>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD>‚<EFBFBD><C282><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), MB_OK | MB_ICONERROR);
break;
case Waifu2x::eWaifu2xcuDNNError_OldVersion:
MessageBox(dh, TEXT("cuDNN<EFBFBD>͎g<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>\r\n<EFBFBD>ucudnn64_65.dll<6C>v<EFBFBD>̃o<CC83>[<5B>W<EFBFBD><57><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Â<EFBFBD><C382>ł<EFBFBD><C582>Bv2<76><32><EFBFBD>g<EFBFBD><67><EFBFBD>ĉ<EFBFBD><C489><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), MB_OK | MB_ICONERROR);
break;
case Waifu2x::eWaifu2xcuDNNError_CannotCreate:
MessageBox(dh, TEXT("cuDNN<EFBFBD>͎g<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>\r\ncuDNN<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>o<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), MB_OK | MB_ICONERROR);
break;
default:
2015-05-29 01:47:26 +09:00
MessageBox(dh, TEXT("cuDNN<EFBFBD>͎g<EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD><EFBFBD>"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), MB_OK | MB_ICONERROR);
}
2015-05-29 01:47:26 +09:00
}
// <20><><EFBFBD><EFBFBD><EFBFBD>œn<C593><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>hWnd<6E><64>IDC_EDIT<49><54>HWND(<28>R<EFBFBD><52><EFBFBD>g<EFBFBD><67><EFBFBD>[<5B><><EFBFBD>̃C<CC83>x<EFBFBD><78><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
LRESULT DropInput(HWND hWnd, WPARAM wParam, LPARAM lParam, WNDPROC OrgSubWnd, LPVOID lpData)
{
char szTmp[AR_PATH_MAX];
// <20>h<EFBFBD><68><EFBFBD>b<EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
UINT FileNum = DragQueryFileA((HDROP)wParam, 0xFFFFFFFF, szTmp, _countof(szTmp));
if (FileNum >= 1)
{
DragQueryFileA((HDROP)wParam, 0, szTmp, _countof(szTmp));
boost::filesystem::path path(szTmp);
if (!boost::filesystem::exists(path))
{
MessageBox(dh, TEXT("<EFBFBD><EFBFBD><EFBFBD>̓t<EFBFBD>@<40>C<EFBFBD><43>/<2F>t<EFBFBD>H<EFBFBD><48><EFBFBD>_<EFBFBD><5F><EFBFBD><EFBFBD><EFBFBD>݂<EFBFBD><DD82>܂<EFBFBD><DC82><EFBFBD>"), TEXT("<EFBFBD>G<EFBFBD><EFBFBD><EFBFBD>["), MB_OK | MB_ICONERROR);
return 0L;
}
if (!SyncMember(true))
2015-05-29 01:47:26 +09:00
return 0L;
if (boost::filesystem::is_directory(path))
{
HWND ho = GetDlgItem(dh, IDC_EDIT_OUTPUT);
const std::string addstr(AddName());
autoSetAddName = AddName();
auto str = (path.branch_path() / (path.stem().string() + addstr)).string();
SetWindowTextA(ho, str.c_str());
SetWindowTextA(hWnd, szTmp);
}
else
{
HWND ho = GetDlgItem(dh, IDC_EDIT_OUTPUT);
std::string outputFileName = szTmp;
const auto tailDot = outputFileName.find_last_of('.');
if (tailDot != outputFileName.npos)
outputFileName.erase(tailDot, outputFileName.length());
2015-05-29 01:47:26 +09:00
const std::string addstr(AddName());
autoSetAddName = addstr;
outputFileName += addstr + outputExt;
SetWindowTextA(ho, outputFileName.c_str());
SetWindowTextA(hWnd, szTmp);
}
SetCropSizeList(path);
2015-05-29 01:47:26 +09:00
}
return 0L;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>œn<C593><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>hWnd<6E><64>IDC_EDIT<49><54>HWND(<28>R<EFBFBD><52><EFBFBD>g<EFBFBD><67><EFBFBD>[<5B><><EFBFBD>̃C<CC83>x<EFBFBD><78><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
LRESULT DropOutput(HWND hWnd, WPARAM wParam, LPARAM lParam, WNDPROC OrgSubWnd, LPVOID lpData)
{
TCHAR szTmp[AR_PATH_MAX];
// <20>h<EFBFBD><68><EFBFBD>b<EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
UINT FileNum = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, szTmp, AR_PATH_MAX);
if (FileNum >= 1)
{
DragQueryFile((HDROP)wParam, 0, szTmp, AR_PATH_MAX);
SetWindowText(hWnd, szTmp);
}
return 0L;
}
LRESULT TextInput(HWND hWnd, WPARAM wParam, LPARAM lParam, WNDPROC OrgSubWnd, LPVOID lpData)
{
const auto ret = CallWindowProc(OrgSubWnd, hWnd, WM_CHAR, wParam, lParam);
ReplaceAddString();
return ret;
}
};
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// CDialog<6F>N<EFBFBD><4E><EFBFBD>X<EFBFBD>Ń_<C583>C<EFBFBD>A<EFBFBD><41><EFBFBD>O<EFBFBD><4F><EFBFBD><EFBFBD><EC90AC><EFBFBD><EFBFBD>
CDialog cDialog;
CDialog cDialog2;
// IDC_EDIT<49>̃T<CC83>u<EFBFBD>N<EFBFBD><4E><EFBFBD>X
CControl cControlInput(IDC_EDIT_INPUT);
CControl cControlOutput(IDC_EDIT_OUTPUT);
CControl cControlScale(IDC_EDIT_SCALE_RATIO);
CControl cControlOutExt(IDC_EDIT_OUT_EXT);
// <20>o<EFBFBD>^<5E><><EFBFBD><EFBFBD><EFBFBD>֐<EFBFBD><D690><EFBFBD><EFBFBD>܂Ƃ߂<C682><DF82><EFBFBD>N<EFBFBD><4E><EFBFBD>X
// <20>O<EFBFBD><4F><EFBFBD>[<5B>o<EFBFBD><6F><EFBFBD>֐<EFBFBD><D690><EFBFBD><EFBFBD>g<EFBFBD><67><EFBFBD>΃N<CE83><4E><EFBFBD>X<EFBFBD>ɂ܂Ƃ߂<C682><DF82>K<EFBFBD>v<EFBFBD>͂Ȃ<CD82><C882><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̕<EFBFBD><CC95>@<40><><EFBFBD>𗧂‚<F097A782><C282>Ƃ<EFBFBD><C682><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͂<EFBFBD>
DialogEvent cDialogEvent;
// <20>N<EFBFBD><4E><EFBFBD>X<EFBFBD>̊֐<CC8A><D690><EFBFBD><EFBFBD>o<EFBFBD>^<5E><><EFBFBD><EFBFBD><EFBFBD>
// IDC_EDIT<49><54>WM_DROPFILES<45><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>Ɏ<EFBFBD><C98E>s<EFBFBD><73><EFBFBD><EFBFBD><EFBFBD>֐<EFBFBD><D690>̓o<CC93>^
cControlInput.SetEventCallBack(SetClassCustomFunc(DialogEvent::DropInput, &cDialogEvent), NULL, WM_DROPFILES);
cControlOutput.SetEventCallBack(SetClassCustomFunc(DialogEvent::DropOutput, &cDialogEvent), NULL, WM_DROPFILES);
cControlScale.SetEventCallBack(SetClassCustomFunc(DialogEvent::TextInput, &cDialogEvent), NULL, WM_CHAR);
cControlOutExt.SetEventCallBack(SetClassCustomFunc(DialogEvent::TextInput, &cDialogEvent), NULL, WM_CHAR);
// <20>R<EFBFBD><52><EFBFBD>g<EFBFBD><67><EFBFBD>[<5B><><EFBFBD>̃T<CC83>u<EFBFBD>N<EFBFBD><4E><EFBFBD>X<EFBFBD><58><EFBFBD>o<EFBFBD>^
cDialog.AddControl(&cControlInput);
cDialog.AddControl(&cControlOutput);
cDialog.AddControl(&cControlScale);
cDialog.AddControl(&cControlOutExt);
// <20>e<EFBFBD>R<EFBFBD><52><EFBFBD>g<EFBFBD><67><EFBFBD>[<5B><><EFBFBD>̃C<CC83>x<EFBFBD><78><EFBFBD>g<EFBFBD>Ŏ<EFBFBD><C58E>s<EFBFBD><73><EFBFBD><EFBFBD><EFBFBD>֐<EFBFBD><D690>̓o<CC93>^
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::Exec, &cDialogEvent), NULL, IDC_BUTTON_EXEC);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::Cancel, &cDialogEvent), NULL, IDC_BUTTON_CANCEL);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::RadioButtom, &cDialogEvent), NULL, IDC_RADIO_MODE_NOISE);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::RadioButtom, &cDialogEvent), NULL, IDC_RADIO_MODE_SCALE);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::RadioButtom, &cDialogEvent), NULL, IDC_RADIO_MODE_NOISE_SCALE);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::RadioButtom, &cDialogEvent), NULL, IDC_RADIO_AUTO_SCALE);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::RadioButtom, &cDialogEvent), NULL, IDC_RADIONOISE_LEVEL1);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::RadioButtom, &cDialogEvent), NULL, IDC_RADIONOISE_LEVEL2);
2015-05-29 01:47:26 +09:00
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::RadioButtom, &cDialogEvent), NULL, IDC_RADIO_MODE_CPU);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::RadioButtom, &cDialogEvent), NULL, IDC_RADIO_MODE_GPU);
cDialog.SetCommandCallBack(SetClassFunc(DialogEvent::CheckCUDNN, &cDialogEvent), NULL, IDC_BUTTON_CHECK_CUDNN);
// <20>_<EFBFBD>C<EFBFBD>A<EFBFBD><41><EFBFBD>O<EFBFBD>̃C<CC83>x<EFBFBD><78><EFBFBD>g<EFBFBD>Ŏ<EFBFBD><C58E>s<EFBFBD><73><EFBFBD><EFBFBD><EFBFBD>֐<EFBFBD><D690>̓o<CC93>^
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::Create, &cDialogEvent), NULL, WM_INITDIALOG);
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnDialogEnd, &cDialogEvent), NULL, WM_CLOSE);
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnFaildCreateDir, &cDialogEvent), NULL, WM_FAILD_CREATE_DIR);
2015-06-03 03:01:56 +09:00
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::OnWaifu2xError, &cDialogEvent), NULL, WM_ON_WAIFU2X_ERROR);
2015-05-29 01:47:26 +09:00
cDialog.SetEventCallBack(SetClassFunc(DialogEvent::WaitThreadExit, &cDialogEvent), NULL, WM_END_THREAD);
// <20>_<EFBFBD>C<EFBFBD>A<EFBFBD><41><EFBFBD>O<EFBFBD><4F><EFBFBD>\<5C><>
cDialog.DoModal(hInstance, IDD_DIALOG);
return 0;
}