Newer
Older
PrismSoftware / ECTrainer2 / myWinUtils.cpp
#include "MyWinUtils.h"

#include <system_error>
#include <fstream>
#include <sstream>

namespace mwut {

	// マルチバイト文字列をワイド文字列(UNICODE)に変換
	std::wstring Multi2Wide(std::string const& src) {
		auto const dest_size = ::MultiByteToWideChar(CP_ACP, 0U, src.data(), -1, nullptr, 0U);
		std::vector<wchar_t> dest(dest_size, L'\0');
		if (::MultiByteToWideChar(CP_ACP, 0U, src.data(), -1, dest.data(), (int)dest.size()) == 0) {
			throw std::system_error{ static_cast<int>(::GetLastError()), std::system_category() };
		}
		dest.resize(std::char_traits<wchar_t>::length(dest.data()));
		dest.shrink_to_fit();
		return std::wstring(dest.begin(), dest.end());
	}

	// 書式付きデバッグ出力
	int DebugPrintf(LPCTSTR format, ...) {
		va_list args;
		va_start(args, format);

		int len = _vsctprintf(format, args) + 1;
		TCHAR* buf = (TCHAR*)malloc(len * sizeof(TCHAR));
		len = _vstprintf_s(buf, len, format, args);

		OutputDebugString(buf);
		free(buf);

		return len;
	}

	// テーブルを読み込み
	bool ReadTable(const std::string& filename, STR_TABLE& table, const char delimiter) {
		// ファイルを開く
		std::fstream filestream(filename);
		if (!filestream.is_open()) return false; // ファイルが開けなかった場合は終了

		// ファイルを読み込む
		while (!filestream.eof()) {
			// 1行読み込む
			std::string buffer;
			filestream >> buffer;

			// ファイルから読み込んだ1行の文字列を区切り文字で分けてリストに追加する
			std::vector<std::string> record;              // 1行分の文字列のリスト
			std::istringstream streambuffer(buffer); // 文字列ストリーム
			std::string token;                       // 1セル分の文字列
			while (std::getline(streambuffer, token, delimiter)) {
				// 1セル分の文字列をリストに追加する
				record.push_back(token);
			}

			// 1行分の文字列を出力引数のリストに追加する
			table.push_back(record);
		}

		return true;
	}

	// マルチディスプレイの情報を取得
	// 要素0:メインウインドウ
	std::vector<RECT> GetDisplayInfo() {
		// ディスプレイ情報取得
		std::vector<RECT> displays;
		EnumDisplayMonitors(NULL, NULL,
			(MONITORENUMPROC)MonitorEnumProc, (LPARAM)&displays);

		// メインモニタを先頭要素に移動
		int mainMonitor = 0;
		for (int i = 0; i < displays.size(); i++) {
			if (displays[i].left == 0 && displays[i].top == 0) mainMonitor = i;
		}
		if (mainMonitor != 0) {
			SWAP<RECT>::DO(displays[0], displays[mainMonitor]);
		}

#ifdef _DEBUG
		for (int i = 0; i < displays.size(); i++) {
			DebugPrintf(_T("Display %d%s  L %d T %d R %d B %d\n"),
				i, i ? _T("") : _T("(main)"), displays[i].left, displays[i].top,
				displays[i].right, displays[i].bottom);
			//std::cout << "Monitor" << i << " : "
			//	<< displays[i].left << "," << displays[i].top << ","
			//	<< displays[i].right << "," << displays[i].bottom << std::endl;
		}
#endif // _DEBUG

		return displays;
	}

	// ディスプレイ情報取得コールバック
	BOOL CALLBACK MonitorEnumProc(
		HMONITOR hMon, HDC hdcMon, LPRECT lpMon, LPARAM dwData) {

		std::vector<RECT>* displays = (std::vector<RECT>*)dwData;
		displays->push_back(*lpMon);
		return TRUE;
	}

	// 安全なデリート
	void SafeDelete(void** ptr) {
		if (*ptr) {
			delete* ptr;
			*ptr = NULL;
		}
	}


	// 高精度タイマークラス

	// コンストラクタ
	HPTimer::HPTimer() {
		QueryPerformanceFrequency(&_nFreq);
		QueryPerformanceCounter(&_nBegin);
	}

	// 経過時間算出
	double HPTimer::Calc(LARGE_INTEGER before) {
		LARGE_INTEGER cur;
		QueryPerformanceCounter(&cur);
		double elapse = (cur.QuadPart - before.QuadPart) * 1000.0 / _nFreq.QuadPart;
		_nLast = cur;
		return elapse;
	}

	// 開始時からの経過時間(ms)
	double HPTimer::Elapse() {
		return this->Calc(_nBegin);
	}

	// 前回からの経過時間(ms)
	double HPTimer::Interval() {
		return this->Calc(_nLast);
	}

	// 開始時間リセット
	void HPTimer::Reset() {
		QueryPerformanceCounter(&_nBegin);
	}

	// 高精度Sleep
	void HPTimer::HPSleep(double delayms) {
		HPTimer timer;
		while (1) {
			if (timer.Elapse() > delayms) break;
			Sleep(0);
		}
	}
}