Solution46
LibUtility.cpp
[詳解]
1 //=============================================================================
2 /// @file
3 /// ユーティリティライブラリ実装ファイル
4 ///
5 /// ユーティリティライブラリ実装ファイルです。
6 ///
7 /// $Id: LibUtility.cpp 254 2019-03-25 19:47:20Z admin $
8 /// $Date: 2019-03-26 04:47:20 +0900 (2019/03/26 (火)) $
9 /// $Author: admin $
10 ///
11 /// @attention なし
12 
13 #pragma managed( push, off )
14 
15 //=============================================================================
16 // インクルードファイル
17 #include <LibUtility.h>
18 #include <stdio.h>
19 #include <tlhelp32.h>
20 
21 //=============================================================================
22 // 共通ライブラリ名前空間
23 namespace LibCommon {
24  //=========================================================================
25  // グローバル関数
26  //-------------------------------------------------------------------------
27  // 致命的エラー発生通知関数
28  void UtilNotifyFatalError( wchar_t const* pszFileName, wchar_t const* pszFuncName, UINT uLineNumber ) noexcept {
29  // 実行ファイル名を取得する
30  wchar_t szExeName[ MAX_PATH ];
31  GetExeFileName( szExeName, MAX_PATH );
32 
33  // ソースファイル名を取得する
34  wchar_t szFileName[ MAX_PATH ];
35  GetFileName( szFileName, MAX_PATH, pszFileName );
36 
37  // カレントプロセスIDを取得する
38  DWORD dwProcessId = ::GetCurrentProcessId();
39 
40  // カレントスレッドIDを取得する
41  DWORD dwThreadId = ::GetCurrentThreadId();
42 
43  // デバッグ出力する
44  wchar_t szBuffer[ 2048 ];
45  ::swprintf_s( szBuffer, L"★以下の場所で致命的エラーが発生したためプログラムを終了します。\n"
46  "実行ファイル名:%s\n"
47  "ファイル名:%s\n"
48  "関数名:%s\n"
49  "行番号:%u\n"
50  "プロセスID:0x%04X\n"
51  "スレッドID:0x%04X\n"
52  , szExeName
53  , szFileName
54  , pszFuncName
55  , uLineNumber
56  , dwProcessId
57  , dwThreadId );
58  OutputDebugFormat( szBuffer );
59 
60  // メッセージボックスを表示する
61  int nResult = ::MessageBoxW( nullptr, szBuffer, L"★致命的エラー", MB_OKCANCEL | MB_ICONHAND );
62  if ( IDOK == nResult ) {
63  // アプリケーションを終了する
64  // ::abort();
65  ::exit( -1 );
66  }
67  }
68 
69  //-------------------------------------------------------------------------
70  // DLLメイン関数実行通知関数
71  void UtilNotifyDllMain( HINSTANCE hInstance, DWORD dwReason ) noexcept {
72  // 処理ブロック
73  do {
74  // 関数を呼び出す理由を調べる
75  wchar_t const* pszReason = nullptr;
76  switch ( dwReason ) {
77  case DLL_PROCESS_ATTACH: pszReason = L"プロセスアタッチ"; break;
78  case DLL_THREAD_ATTACH: pszReason = L"スレッドアタッチ"; break;
79  case DLL_THREAD_DETACH: pszReason = L"スレッドデタッチ"; break;
80  case DLL_PROCESS_DETACH: pszReason = L"プロセスデタッチ"; break;
81  }
82 
83  // 文字列ポインタを調べる
84  if ( nullptr == pszReason ) {
85  // 失敗!
86  break;
87  }
88 
89  // 実行ファイル名を取得する
90  wchar_t szExeFile[ MAX_PATH ];
91  GetExeFileName( szExeFile, MAX_PATH );
92 
93  // モジュールファイル名を取得する
94  wchar_t szPath[ MAX_PATH ];
95  ::GetModuleFileNameW( hInstance, szPath, MAX_PATH );
96 
97  // カレントプロセスIDを取得する
98  DWORD dwProcessId = ::GetCurrentProcessId();
99 
100  // カレントスレッドIDを取得する
101  DWORD dwThreadId = ::GetCurrentThreadId();
102 
103  // デバッグ出力する
104  OutputDebugFormat( L"★%s:[%04X:%04X] %s, %s\n", pszReason, dwProcessId, dwThreadId, szExeFile, szPath );
105  } while ( false );
106  }
107 
108  //-------------------------------------------------------------------------
109  // コンストラクタ実行通知関数
110  void UtilNotifyConstructor( wchar_t const* pszFuncName ) noexcept {
111  // 実行ファイル名を取得する
112  wchar_t szExeFile[ MAX_PATH ];
113  GetExeFileName( szExeFile, MAX_PATH );
114 
115  // カレントプロセスIDを取得する
116  DWORD dwProcessId = ::GetCurrentProcessId();
117 
118  // カレントスレッドIDを取得する
119  DWORD dwThreadId = ::GetCurrentThreadId();
120 
121  // デバッグ出力する
122  OutputDebugFormat( L"▼コンストラクタ:[%04X:%04X] %s!%s\n", dwProcessId, dwThreadId, szExeFile, pszFuncName );
123  }
124 
125  //-------------------------------------------------------------------------
126  // デストラクタ実行通知関数
127  void UtilNotifyDestructor( wchar_t const* pszFuncName ) noexcept {
128  // 実行ファイル名を取得する
129  wchar_t szExeFile[ MAX_PATH ];
130  GetExeFileName( szExeFile, MAX_PATH );
131 
132  // カレントプロセスIDを取得する
133  DWORD dwProcessId = ::GetCurrentProcessId();
134 
135  // カレントスレッドIDを取得する
136  DWORD dwThreadId = ::GetCurrentThreadId();
137 
138  // デバッグ出力する
139  OutputDebugFormat( L"▲デストラクタ:[%04X:%04X] %s!%s\n", dwProcessId, dwThreadId, szExeFile, pszFuncName );
140  }
141 
142  //-------------------------------------------------------------------------
143  // メッセージ表示関数
144  int ShowMessage( wchar_t const* pszMessage, HWND hWnd, UINT uType ) noexcept {
145  // 処理ブロック
146  int result = 0;
147  do {
148  // ウィンドウハンドルを調べる
149  wchar_t szCaption[ MAX_PATH ] = L"メッセージ";
150  if ( nullptr != hWnd ) {
151  // ウィンドウタイトルを取得する
152  ::GetWindowTextW( hWnd, szCaption, MAX_PATH );
153  }
154 
155  // メッセージボックスを表示する
156  result = ::MessageBoxW( hWnd, pszMessage, szCaption, uType );
157  } while ( false );
158 
159  // 実行結果を返す
160  return result;
161  }
162 
163  //-------------------------------------------------------------------------
164  // デバッグ出力関数
165  void OutputDebugFormat( wchar_t const* pszFormat, ... ) noexcept {
166  // 処理ブロック
167  do {
168  // 書式設定文字列ポインタを調べる
169  if ( nullptr == pszFormat ) {
170  // 失敗!
171  break;
172  }
173 
174  // 引数リストを作成する
175  va_list vaArgs;
176  va_start( vaArgs, pszFormat );
177 
178  // 書式設定文字列を展開する
179  wchar_t szBuffer[ MAX_PATH ];
180  if ( !ExpandFormatArgs( szBuffer, ( MAX_PATH ), pszFormat, vaArgs ) ) {
181  // 失敗!
182  break;
183  }
184 
185  // 引数リストを解放する
186  va_end( vaArgs );
187 
188  // デバッグコンソールに文字列を出力する
189  ::OutputDebugStringW( szBuffer );
190  } while ( false );
191  }
192 
193  //-------------------------------------------------------------------------
194  // 書式設定文字列展開関数
195  bool ExpandFormatArgs( wchar_t* pszBuffer, size_t uSize, wchar_t const* pszFormat, va_list vaArgs ) noexcept {
196  // 処理ブロック
197  bool result = false;
198  do {
199  // 文字列バッファポインタを調べる
200  if ( nullptr == pszBuffer ) {
201  // 失敗!
202  break;
203  }
204  // 書式設定文字列ポインタを調べる
205  else if ( nullptr == pszFormat ) {
206  // 失敗!
207  break;
208  }
209  // 書式設定文字列を展開する
210  else if ( 0 >= ::vswprintf_s( pszBuffer, uSize, pszFormat, vaArgs ) ) {
211  // 失敗!
212  break;
213  }
214 
215  // 成功!
216  result = true;
217  } while ( false );
218 
219  // 実行結果を返す
220  return result;
221  }
222 
223  //-------------------------------------------------------------------------
224  // 実行ファイルパス取得関数
225  wchar_t const* GetExeFilePath( wchar_t* pszBuffer, size_t uSize ) noexcept {
226  // 処理ブロック
227  wchar_t const* result = nullptr;
228  do {
229  // 文字列バッファポインタを調べる
230  if ( nullptr == pszBuffer ) {
231  // 失敗!
232  break;
233  }
234 
235  // 実行ファイルパスを取得する
236  ::GetModuleFileNameW( nullptr, pszBuffer, static_cast< DWORD >( uSize ) );
237 
238  // 成功!
239  result = pszBuffer;
240  } while ( false );
241 
242  // 実行結果を返す
243  return result;
244  }
245 
246  //-------------------------------------------------------------------------
247  // 実行ファイルディレクトリパス取得関数
248  wchar_t const* GetExeFileDir( wchar_t* pszBuffer, size_t uSize ) noexcept {
249  // 処理ブロック
250  wchar_t const* result = nullptr;
251  do {
252  // 文字列バッファポインタを調べる
253  if ( nullptr == pszBuffer ) {
254  // 失敗!
255  break;
256  }
257 
258  // 実行ファイルパスを取得する
259  wchar_t szPath[ MAX_PATH ];
260  GetExeFilePath( szPath, MAX_PATH );
261 
262  // ディレクトリパスを取得する
263  result = GetDirPath( pszBuffer, uSize, szPath );
264  } while ( false );
265 
266  // 実行結果を返す
267  return result;
268  }
269 
270  //-------------------------------------------------------------------------
271  // 実行ファイル名取得関数
272  wchar_t const* GetExeFileName( wchar_t* pszBuffer, size_t uSize ) noexcept {
273  // 処理ブロック
274  wchar_t const* result = nullptr;
275  do {
276  // 文字列バッファポインタを調べる
277  if ( nullptr == pszBuffer ) {
278  // 失敗!
279  break;
280  }
281 
282  // 実行ファイルパスを取得する
283  wchar_t szPath[ MAX_PATH ];
284  GetExeFilePath( szPath, MAX_PATH );
285 
286  // ファイル名を取得する
287  result = GetFileName( pszBuffer, uSize, szPath );
288  } while ( false );
289 
290  // 実行結果を返す
291  return result;
292  }
293 
294  //-------------------------------------------------------------------------
295  // ディレクトリパス取得関数
296  wchar_t const* GetDirPath( wchar_t* pszBuffer, size_t uSize, wchar_t const* pszPath ) noexcept {
297  // 処理ブロック
298  wchar_t const* result = nullptr;
299  do {
300  // 文字列バッファポインタを調べる
301  if ( nullptr == pszBuffer ) {
302  // 失敗!
303  break;
304  }
305  // ファイルパス文字列ポインタを調べる
306  else if ( nullptr == pszPath ) {
307  // 失敗!
308  break;
309  }
310 
311  // ファイルパスを分解する
312  wchar_t szDrive[ _MAX_DRIVE ];
313  wchar_t szDir [ _MAX_DIR ];
314  wchar_t szFName[ _MAX_FNAME ];
315  wchar_t szExt [ _MAX_EXT ];
316  ::_wsplitpath_s( pszPath, szDrive, szDir, szFName, szExt );
317 
318  // ディレクトリパスを取得する
319  ::swprintf_s( pszBuffer, uSize, L"%s%s", szDrive, szDir );
320 
321  // 成功!
322  result = pszBuffer;
323  } while ( false );
324 
325  // 実行結果を返す
326  return result;
327  }
328 
329  //-------------------------------------------------------------------------
330  // ファイル名取得関数
331  wchar_t const* GetFileName( wchar_t* pszBuffer, size_t uSize, wchar_t const* pszPath ) noexcept {
332  // 処理ブロック
333  wchar_t const* result = nullptr;
334  do {
335  // 文字列バッファポインタを調べる
336  if ( nullptr == pszBuffer ) {
337  // 失敗!
338  break;
339  }
340  // ファイルパス文字列ポインタを調べる
341  else if ( nullptr == pszPath ) {
342  // 失敗!
343  break;
344  }
345 
346  // ファイルパスを分解する
347  wchar_t szDrive[ _MAX_DRIVE ];
348  wchar_t szDir [ _MAX_DIR ];
349  wchar_t szFName[ _MAX_FNAME ];
350  wchar_t szExt [ _MAX_EXT ];
351  ::_wsplitpath_s( pszPath, szDrive, szDir, szFName, szExt );
352 
353  // ファイル名を取得する
354  ::swprintf_s( pszBuffer, uSize, L"%s%s", szFName, szExt );
355 
356  // 成功!
357  result = pszBuffer;
358  } while ( false );
359 
360  // 実行結果を返す
361  return result;
362  }
363 
364  //-------------------------------------------------------------------------
365  // モジュール名取得関数
366  wchar_t const* GetModuleName( HINSTANCE hInstance, wchar_t* pszBuffer, size_t uSize ) noexcept {
367  // 処理ブロック
368  wchar_t const* result = nullptr;
369  do {
370  // モジュール名を取得する
371  static wchar_t szPath[ MAX_PATH ];
372  ::GetModuleFileNameW( hInstance, szPath, MAX_PATH );
373 
374  // 文字列ポインタを取得する
375  result = szPath;
376 
377  // 文字列バッファポインタを調べる
378  if ( nullptr != pszBuffer ) {
379  // 文字列をコピーする
380  ::wcscpy_s( pszBuffer, uSize, szPath );
381 
382  // 文字列ポインタを取得する
383  result = pszBuffer;
384  }
385  } while ( false );
386 
387  // 実行結果を返す
388  return result;
389  }
390 
391  //-------------------------------------------------------------------------
392  // 文字コード比較関数
393  bool CompareCharCode( wchar_t ch1, wchar_t ch2, bool bIgnore ) noexcept {
394  // 処理ブロック
395  bool result = false;
396  do {
397  // 大小文字無視フラグを調べる
398  if ( bIgnore ) {
399  // 小文字に変換する
400  ch1 = ::towlower( ch1 );
401  ch2 = ::towlower( ch2 );
402  }
403 
404  // 文字コードを比較する
405  if ( ch1 != ch2 ) {
406  // 失敗!
407  break;
408  }
409 
410  // 成功!
411  result = true;
412  } while ( false );
413 
414  // 実行結果を返す
415  return result;
416  }
417 
418  //-------------------------------------------------------------------------
419  // 文字コード比較関数
420  bool CompareCharCode( wchar_t ch, wchar_t const* pszString, bool bIgnore ) noexcept {
421  // 処理ブロック
422  bool result = false;
423  do {
424  // 比較先文字列ポインタを調べる
425  if ( nullptr == pszString ) {
426  // 失敗!
427  break;
428  }
429  // 巡回する
430  else for ( ;; ) {
431  // 比較先文字コードを取得する
432  wchar_t ch2 = *pszString++;
433  if ( L'\0' == ch2 ) {
434  // 失敗!
435  break;
436  }
437  // 文字コードを比較する
438  else if ( CompareCharCode( ch, ch2, bIgnore ) ) {
439  // 成功!
440  result = true;
441  break;
442  }
443  }
444  } while ( false );
445 
446  // 実行結果を返す
447  return result;
448  }
449 
450  //-------------------------------------------------------------------------
451  // ウィンドウ表示位置設定関数
452  bool SetWindowPosition( HWND hWnd, EWindowPosition ePos ) noexcept {
453  // 処理ブロック
454  bool result = false;
455  do {
456  // ウィンドウ表示位置のモニタハンドルを取得する
457  HMONITOR hMonitor = ::MonitorFromWindow( hWnd, MONITOR_DEFAULTTONEAREST );
458  if ( nullptr == hMonitor ) {
459  // 失敗!
460  break;
461  }
462 
463  // モニタ作業領域サイズを取得する
464  MONITORINFO sMonitorInfo = { sizeof( MONITORINFO ) };
465  if ( 0 == ::GetMonitorInfo( hMonitor, &sMonitorInfo ) ) {
466  // 失敗!
467  break;
468  }
469 
470  // モニタ作業領域サイズを取得する
471  int nWidth = ( sMonitorInfo.rcWork.right - sMonitorInfo.rcWork.left );
472  int nHeight = ( sMonitorInfo.rcWork.bottom - sMonitorInfo.rcWork.top );
473 
474  // 表示位置種別を調べる
475  int nLeft = sMonitorInfo.rcWork.left;
476  int nTop = sMonitorInfo.rcWork.top;
477  bool bFailure = false;
478  switch ( ePos ) {
479  case EWindowPosition::Left: nWidth /= 2; break; // 左端
480  case EWindowPosition::Top: nHeight /= 2; break; // 上端
481  case EWindowPosition::Right: nWidth /= 2; nLeft += nWidth; break; // 右端
482  case EWindowPosition::Bottom: nHeight /= 2; nTop += nHeight; break; // 下端
483  case EWindowPosition::Full: break; // フルサイズ
484  default: bFailure = true; break; // 失敗!
485  }
486 
487  // 失敗フラグを調べる
488  if ( bFailure ) {
489  // 失敗!
490  break;
491  }
492 
493  // ウィンドウ表示領域を設定する
494  ::SetWindowPos( hWnd, HWND_TOP, nLeft, nTop, nWidth, nHeight, ( SWP_NOACTIVATE | SWP_SHOWWINDOW ) );
495  ::UpdateWindow( hWnd );
496 
497  // 成功!
498  result = true;
499  } while ( false );
500 
501  // 実行結果を返す
502  return result;
503  }
504 
505  //-------------------------------------------------------------------------
506  // プロセス検索関数
507  DWORD SearchProcess( wchar_t const* pszPath ) {
508  // 処理ブロック
509  DWORD result = 0;
510  do {
511  // プロセススナップショットを作成する
512  HANDLE hSnapProcess = ::CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
513  if ( nullptr == hSnapProcess ) {
514  // 失敗!
515  break;
516  }
517 
518  // プロセス情報を巡回する
519  PROCESSENTRY32W sProcessEntry = { sizeof( PROCESSENTRY32 ) };
520  bool bResult = ( 0 != ::Process32FirstW( hSnapProcess, &sProcessEntry ) );
521  for ( ; !result && bResult; bResult = ( 0 != ::Process32NextW( hSnapProcess, &sProcessEntry ) ) ) {
522  // モジュールスナップショットを作成する
523  HANDLE hSnapModule = ::CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, sProcessEntry.th32ProcessID );
524  if ( nullptr == hSnapModule ) {
525  // 失敗!
526  break;
527  }
528 
529  // モジュール情報を巡回する
530  MODULEENTRY32W sModuleEntry = { sizeof( MODULEENTRY32 ) };
531  bool bResult = ( 0 != ::Module32FirstW( hSnapModule, &sModuleEntry ) );
532  for ( ; bResult; bResult = ( 0 != ::Module32NextW( hSnapModule, &sModuleEntry ) ) ) {
533  // プロセス実行ファイルパスを調べる
534  if ( 0 == ::_wcsicmp( pszPath, sModuleEntry.szExePath ) ) {
535  // 成功!
536  result = sProcessEntry.th32ProcessID;
537  break;
538  }
539  }
540  }
541  } while ( false );
542 
543  // 実行結果を返す
544  return result;
545  }
546 }
547 
548 #pragma managed( pop )
LIB_COMMON_API void UtilNotifyDllMain(HINSTANCE hInstance, DWORD dwReason) noexcept
DLLメイン関数実行通知関数
Definition: LibUtility.cpp:71
LIB_COMMON_API bool CompareCharCode(wchar_t ch1, wchar_t ch2, bool bIgnore) noexcept
文字コード比較関数
Definition: LibUtility.cpp:393
LIB_COMMON_API int ShowMessage(wchar_t const *pszMessage, HWND hWnd=nullptr, UINT uType=(MB_OK|MB_ICONEXCLAMATION)) noexcept
メッセージ表示関数
Definition: LibUtility.cpp:144
LIB_COMMON_API void UtilNotifyConstructor(wchar_t const *pszFuncName) noexcept
コンストラクタ実行通知関数
Definition: LibUtility.cpp:110
EWindowPosition
ウィンドウ表示位置種別列挙体
Definition: LibUtility.h:39
LIB_COMMON_API bool ExpandFormatArgs(wchar_t *pszBuffer, size_t uSize, wchar_t const *pszFormat, va_list vaArgs) noexcept
書式設定文字列展開関数
Definition: LibUtility.cpp:195
共通ライブラリ名前空間
Definition: CArray.h:23
LIB_COMMON_API void UtilNotifyDestructor(wchar_t const *pszFuncName) noexcept
デストラクタ実行通知関数
Definition: LibUtility.cpp:127
LIB_COMMON_API wchar_t const * GetDirPath(wchar_t *pszBuffer, size_t uSize, wchar_t const *pszPath) noexcept
ディレクトリパス取得関数
Definition: LibUtility.cpp:296
LIB_COMMON_API wchar_t const * GetModuleName(HINSTANCE hInstance, wchar_t *pszBuffer=nullptr, size_t uSize=0) noexcept
モジュール名取得関数
Definition: LibUtility.cpp:366
LIB_COMMON_API void UtilNotifyFatalError(wchar_t const *pszFileName, wchar_t const *pszFuncName, UINT uLineNumber) noexcept
致命的エラー発生通知関数
Definition: LibUtility.cpp:28
LIB_COMMON_API void OutputDebugFormat(wchar_t const *pszFormat,...) noexcept
デバッグ出力関数
Definition: LibUtility.cpp:165
LIB_COMMON_API wchar_t const * GetExeFileName(wchar_t *pszBuffer, size_t uSize) noexcept
実行ファイル名取得関数
Definition: LibUtility.cpp:272
LIB_COMMON_API wchar_t const * GetExeFilePath(wchar_t *pszBuffer, size_t uSize) noexcept
実行ファイルパス取得関数
Definition: LibUtility.cpp:225
LIB_COMMON_API wchar_t const * GetExeFileDir(wchar_t *pszBuffer, size_t uSize) noexcept
実行ファイルディレクトリパス取得関数
Definition: LibUtility.cpp:248
LIB_COMMON_API DWORD SearchProcess(wchar_t const *pszPath)
プロセス検索関数
Definition: LibUtility.cpp:507
LIB_COMMON_API bool SetWindowPosition(HWND hWnd, EWindowPosition ePos) noexcept
ウィンドウ表示位置設定関数
Definition: LibUtility.cpp:452
ユーティリティライブラリヘッダファイル
LIB_COMMON_API wchar_t const * GetFileName(wchar_t *pszBuffer, size_t uSize, wchar_t const *pszPath) noexcept
ファイル名取得関数
Definition: LibUtility.cpp:331