Solution46
CConsole.cpp
[詳解]
1 //=============================================================================
2 /// @file
3 /// コンソール入出力クラス実装コンソール
4 ///
5 /// コンソール入出力クラス実装コンソールです。
6 ///
7 /// $Id: CConsole.cpp 245 2019-03-20 15:03:41Z admin $
8 /// $Date: 2019-03-21 00:03:41 +0900 (2019/03/21 (木)) $
9 /// $Author: admin $
10 ///
11 /// @attention なし
12 
13 #pragma managed( push, off )
14 
15 //=============================================================================
16 // インクルードファイル
17 #include <CConsole.h>
18 #include <CSyncAuto.h>
19 #include <CTimer.h>
20 #include <LibUtility.h>
21 
22 //=============================================================================
23 // 共通ライブラリ名前空間
24 namespace LibCommon {
25  //=========================================================================
26  // コンソール入出力クラス
27  //=========================================================================
28  // 構築子と解体子
29  //-------------------------------------------------------------------------
30  // コンストラクタ
31  CConsole::CConsole() noexcept
32  // 基底クラスコンストラクタ
33  : CMutex()
34  , CStream()
35  // メンバ変数初期化
36  , m_szBuffer()
37  , m_sRecordBuffer()
38  , m_nRecordPos( 0 )
39  , m_nRecordCount( 0 )
40  , m_sMaxCursor()
41  , m_cThreadSub()
42  , m_bStopInput( false )
43  {
44  // コンストラクタ実行通知
46 
47  // ミューテックスを作成する
48  if ( !CMutex::Create() ) {
49  // 致命的エラー!
51  }
52  // サブスレッドを起動する
53  else if ( !m_cThreadSub.Create( SubThreadProc, this ) ) {
54  // 致命的エラー!
56  }
57  }
58 
59  //-------------------------------------------------------------------------
60  // デストラクタ
61  CConsole::~CConsole() noexcept {
62  // デストラクタ実行通知
64 
65  // サブスレッドをクローズする
67  }
68 
69  //=========================================================================
70  // 公開関数
71  //-------------------------------------------------------------------------
72  // 文字列出力関数
73  bool CConsole::OutputString( wchar_t const* pszString ) noexcept {
74  // 処理ブロック
75  bool result = false;
76  do {
77  // 文字列ポインタを調べる
78  if ( nullptr == pszString ) {
79  // 失敗!
80  break;
81  }
82 
83  // 標準出力ハンドルを取得する
84  HANDLE hOutput = ::GetStdHandle( STD_OUTPUT_HANDLE );
85 
86  // 文字列長を取得する
87  int nCount = static_cast< int >( ::wcslen( pszString ) );
88  if ( BUFFER_SIZE >= nCount ) {
89  // 標準出力に文字列出力する
90  ::WriteConsoleW( hOutput, pszString, static_cast< DWORD >( nCount ), nullptr, nullptr );
91  }
92  // 巡回する
93  else for ( int nIndex = 0, nSize = 0; nCount > nIndex; nIndex += nSize, nCount -= nSize ) {
94  // 1回に出力する文字数を取得する
95  if ( BUFFER_SIZE > nCount ) {
96  nSize = nCount;
97  }
98  else {
99  nSize = BUFFER_SIZE;
100  }
101 
102  // 文字列バッファにコピーする
103  ::wcsncpy_s( m_szBuffer, &pszString[ nIndex ], nSize );
104 
105  // 終端文字コードを設定する
106  m_szBuffer[ nSize ] = L'\0';
107 
108  // 標準出力に文字列出力する
109  ::WriteConsoleW( hOutput, m_szBuffer, static_cast< DWORD >( nSize ), nullptr, nullptr );
110  }
111 
112  // カーソル位置を取得する
113  COORD sCursor;
114  if ( GetCursor( sCursor ) ) {
115  // 垂直位置を調べる
116  if ( m_sMaxCursor.Y < sCursor.Y ) {
117  // 最大カーソル位置を更新する
118  m_sMaxCursor = sCursor;
119  }
120  }
121 
122  // 成功!
123  result = true;
124  } while ( false );
125 
126  // 実行結果を返す
127  return result;
128  }
129 
130  //-------------------------------------------------------------------------
131  // 1文字入力関数
132  bool CConsole::InputChar( wchar_t& rCh, DWORD dwTime ) noexcept {
133  // 処理ブロック
134  bool result = false;
135  do {
136  // タイマを設定する
137  CTimer cTimer( dwTime );
138 
139  // 巡回する
140  while ( !result ) {
141  // 入力中止要求フラグを調べる
142  if ( m_bStopInput ) {
143  // 入力中止要求フラグをクリアする
144  m_bStopInput = false;
145 
146  // 失敗!
147  break;
148  }
149 
150  // 入力レコードを取得する
151  SInputRecord sRecord;
152  if ( InputRecord( sRecord, 0 ) ) {
153  // 文字コードを取得する
154  rCh = sRecord.m_sEvent.Event.KeyEvent.uChar.UnicodeChar;
155  if ( L'\0' != rCh ) {
156  // 文字コードを調べる
157  if ( L'\r' == rCh ) {
158  // 文字コードを変更する
159  rCh = L'\n';
160  }
161 
162  // 成功!
163  result = true;
164  break;
165  }
166  }
167  // タイマを調べる
168  else if ( cTimer.Wait( 0 ) ) {
169  // 失敗!
170  break;
171  }
172  // サブスレッドの状態を調べる
173  else if ( m_cThreadSub.Wait( 0 ) ) {
174  // 失敗!
175  break;
176  }
177  }
178  } while ( false );
179 
180  // 実行結果を返す
181  return result;
182  }
183 
184  //-------------------------------------------------------------------------
185  // 文字列入力関数
186  int CConsole::InputString( wchar_t* pszBuffer, int nSize, wchar_t const* pszString, DWORD dwTime ) noexcept {
187  // 処理ブロック
188  int result = 0;
189  do {
190  // 文字列バッファポインタを調べる
191  if ( nullptr == pszBuffer ) {
192  // 失敗!
193  break;
194  }
195 
196  // スクリーンバッファサイズを取得する
197  int nSizeX, nSizeY;
198  GetSize( nSizeX, nSizeY);
199 
200  // 先頭カーソル位置を取得する
201  COORD sCursorFirst, sCursorLast;
202  GetCursor( sCursorFirst );
203  sCursorLast = sCursorFirst;
204 
205  // 文字列ポインタと先頭文字を調べる
206  int nCount = 0;
207  int nPos = 0;
208  if ( ( nullptr != pszString ) && ( L'\0' != *pszString ) ) {
209  // 巡回する
210  bool bResult = true;
211  for ( int nIndex = 0; bResult; ++nIndex ) {
212  // 文字コードを調べる
213  if ( L'\0' == *pszString ) {
214  // 入力位置を設定する
215  nPos = nCount;
216 
217  // 最後尾カーソル位置を取得する
218  GetCursor( sCursorLast );
219 
220  // 成功!
221  break;
222  }
223  // インデックスを調べる
224  else if ( ( nSize - 1 ) > nIndex ) {
225  // 1文字コピーする
226  pszBuffer[ nCount++ ] = *pszString;
227 
228  // 1文字出力する
229  bResult &= OutputChar( *pszString++ );
230  }
231  }
232 
233  // 実行結果を調べる
234  if ( !bResult ) {
235  // 失敗!
236  break;
237  }
238  }
239 
240  // 巡回する
241  for ( ;; ) {
242  // 入力中止要求フラグを調べる
243  if ( m_bStopInput ) {
244  // 入力中止要求フラグをクリアする
245  m_bStopInput = false;
246 
247  // 失敗!
248  break;
249  }
250 
251  // 入力レコードを取得する
252  SInputRecord sRecord;
253  if ( !InputRecord( sRecord, dwTime ) ) {
254  // 失敗!
255  break;
256  }
257 
258  // 文字コードを取得する
259  wchar_t ch = sRecord.m_sEvent.Event.KeyEvent.uChar.UnicodeChar;
260  if ( L'\033' == ch ) {
261  // 中止!
262  break;
263  }
264 
265  // 再表示開始位置を初期化する
266  int nRedrawPos = -1;
267 
268  // 文字コードを調べる
269  if ( L'\r' == ch ) {
270  // 終端文字コードを設定する
271  pszBuffer[ nCount ] = L'\0';
272 
273  // 成功!
274  result = nCount;
275  break;
276  }
277  // 文字コードを調べる
278  else if ( 0 != ::iswprint( ch ) ) {
279  // 入力文字数を調べる
280  if ( ( nSize - 1 ) > nCount ) {
281  // 入力位置を調べる
282  if ( nCount == nPos ) {
283  // 1文字追加する
284  pszBuffer[ nCount++ ] = ch;
285  ++nPos;
286 
287  // 1文字出力する
288  if ( !OutputChar( ch ) ) {
289  // 失敗!
290  break;
291  }
292 
293  // 最後尾カーソル位置を取得する
294  GetCursor( sCursorLast );
295  }
296  else {
297  // 再表示開始位置を設定する
298  nRedrawPos = static_cast< int >( nPos );
299 
300  // 1文字挿入する
301  for ( int nIndex = nCount; nPos < nIndex; --nIndex ) {
302  pszBuffer[ nIndex ] = pszBuffer[ nIndex - 1 ];
303  }
304  pszBuffer[ nPos++ ] = ch;
305  nCount++;
306  }
307  }
308  }
309  // 文字コードを調べる
310  else if ( L'\b' == ch ) {
311  // 入力位置を調べる
312  if ( 0 < nPos ) {
313  // 1文字削除する
314  for ( int nIndex = nPos; nCount > nIndex; ++nIndex ) {
315  pszBuffer[ nIndex - 1 ] = pszBuffer[ nIndex ];
316  }
317 
318  // 再表示開始位置を設定する
319  nRedrawPos = 0;
320 
321  // 入力文字数と入力位置をデクリメントする
322  --nCount;
323  --nPos;
324  }
325  }
326  else {
327  // 仮想キーコードを調べる
328  WORD wVKey = sRecord.m_sEvent.Event.KeyEvent.wVirtualKeyCode;
329  if ( VK_HOME == wVKey ) {
330  // 入力位置を設定する
331  nPos = 0;
332 
333  // カーソル位置を設定する
334  SetCursor( sCursorFirst );
335  }
336  // 仮想キーコードを調べる
337  else if ( VK_END == wVKey ) {
338  // 入力位置を設定する
339  nPos = nCount;
340 
341  // カーソル位置を設定する
342  SetCursor( sCursorLast );
343  }
344  // 仮想キーコードを調べる
345  else if ( VK_RIGHT == wVKey ) {
346  // 入力位置を調べる
347  if ( nCount > nPos ) {
348  // 再表示開始位置を設定する
349  nRedrawPos = nPos;
350 
351  // 入力位置をインクリメントする
352  ++nPos;
353  }
354  }
355  // 仮想キーコードを調べる
356  else if ( VK_LEFT == wVKey ) {
357  // 入力位置を調べる
358  if ( 0 < nPos ) {
359  // 再表示開始位置を設定する
360  nRedrawPos = 0;
361 
362  // 入力位置をデクリメントする
363  --nPos;
364  }
365  }
366  // 仮想キーコードを調べる
367  else if ( VK_DELETE == wVKey ) {
368  // 入力位置を調べる
369  if ( nCount > nPos ) {
370  // 1文字削除する
371  for ( int nIndex = nPos; ( nCount - 1 ) > nIndex; ++nIndex ) {
372  pszBuffer[ nIndex ] = pszBuffer[ nIndex + 1 ];
373  }
374 
375  // 再表示開始位置を設定する
376  nRedrawPos = nPos;
377 
378  // 入力文字数をデクリメントする
379  --nCount;
380  }
381  }
382  // コントロールキー押下状態を調べる
383  else if ( sRecord.m_bControl ) {
384  // 仮想キーコードを調べる
385  if ( 'V' == wVKey ) {
386  // クリップボードをオープンする
387  if ( 0 != ::OpenClipboard( nullptr ) ) {
388  // クリップボードデータハンドルを取得する
389  HANDLE hClipBoard = ::GetClipboardData( CF_UNICODETEXT );
390  if ( nullptr != hClipBoard ) {
391  // クリップボードデータをロックする
392  LPCWSTR pszText = static_cast< LPCWSTR >( ::GlobalLock( hClipBoard ) );
393  if ( nullptr != pszText ) {
394  // 入力位置を調べる
395  if ( nCount == nPos ) {
396  // 終端文字を設定する
397  pszBuffer[ nCount ] = L'\0';
398 
399  // 文字列を追加する
400  ::wcscat_s( pszBuffer, nSize, pszText );
401 
402  // 文字数を取得する
403  nCount = static_cast< int >( ::wcslen( pszBuffer ) );
404  nPos = nCount;
405 
406  // 文字列を出力する
407  if ( !OutputString( pszText ) ) {
408  // 失敗!
409  break;
410  }
411 
412  // 最後尾カーソル位置を取得する
413  GetCursor( sCursorLast );
414  }
415  else {
416  // 再表示開始位置を設定する
417  nRedrawPos = nPos;
418 
419  // 文字列を挿入する
420  int nLen = static_cast< int >( ::wcslen( pszText ) );
421  if ( ( nSize - 1 ) < ( nCount + nLen ) ) {
422  nLen = ( nSize - nCount - 1 );
423  }
424  wchar_t const* pszSrc = &pszBuffer[ nCount - 1 ];
425  wchar_t* pszDst = &pszBuffer[ nCount + nLen - 1 ];
426  for ( int nIndex = 0, uCount2 = ( nCount - nPos ); uCount2 > nIndex; ++nIndex ) {
427  *pszDst-- = *pszSrc--;
428  }
429  pszDst = &pszBuffer[ nPos ];
430  for ( int nIndex = 0; nLen > nIndex; ++nIndex ) {
431  *pszDst++ = *pszText++;
432  }
433  nCount += nLen;
434  nPos += nLen;
435  }
436  }
437 
438  // クリップボードデータをロック解除する
439  ::GlobalUnlock( hClipBoard );
440  }
441 
442  // クリップボードをクローズする
443  ::CloseClipboard();
444  }
445  }
446  }
447  }
448 
449  // 再表示開始位置を調べる
450  if ( 0 <= nRedrawPos ) {
451  // 再表示開始文字列ポインタを取得する
452  pszString = &pszBuffer[ nRedrawPos ];
453 
454  // 再表示開始位置を調べる
455  if ( 0 == nRedrawPos ) {
456  // カーソル位置を設定する
457  SetCursor( sCursorFirst );
458  }
459 
460  // 現在のカーソル位置を保存する
461  COORD sCursor;
462  GetCursor( sCursor );
463 
464  // 巡回する
465  bool bResult = true;
466  for ( int nIndex = nRedrawPos; bResult; ++nIndex ) {
467  // インデックスを調べる
468  if ( nPos == nIndex ) {
469  // 再表示後のカーソル位置を取得する
470  GetCursor( sCursor );
471  }
472 
473  // インデックスを調べる
474  if ( nCount <= nIndex ) {
475  // 最後尾カーソル位置を取得する
476  GetCursor( sCursorLast );
477 
478  // 空白文字列を出力する
479  bResult &= OutputString( L" " );
480 
481  // カーソル位置を設定する
482  SetCursor( sCursor );
483 
484  // 終了!
485  break;
486  }
487 
488  // 1文字出力する
489  bResult &= OutputChar( *pszString++ );
490  }
491 
492  // 実行結果を調べる
493  if ( !bResult ) {
494  // 失敗!
495  break;
496  }
497  }
498  }
499 
500  // カーソル位置を設定する
501  SetCursor( sCursorLast );
502  } while ( false );
503 
504  // 実行結果を返す
505  return result;
506  }
507 
508  //-------------------------------------------------------------------------
509  // 入力バッファクリア関数
510  void CConsole::ClearInputBuffer() noexcept {
511  // 処理ブロック
512  do {
513  // サブスレッド実行状態を調べる
514  if ( WAIT_OBJECT_0 != ::WaitForSingleObject( m_cThreadSub.GetHandle(), 0 ) ) {
515  // 同期処理ブロック
516  do {
517  CSyncAuto cSyncAuto( *this );
518 
519  // 入力レコード先頭位置をクリアする
520  m_nRecordPos = 0;
521 
522  // 入力レコードカウントをクリアする
523  m_nRecordCount = 0;
524 
525  // コンソール入力バッファ未読レコードを破棄する
526  ::FlushConsoleInputBuffer( GetInputHandle() );
527  } while ( false );
528  }
529  else {
530  // 入力レコード先頭位置をクリアする
531  m_nRecordPos = 0;
532 
533  // 入力レコードカウントをクリアする
534  m_nRecordCount = 0;
535 
536  // コンソール入力バッファ未読レコードを破棄する
537  ::FlushConsoleInputBuffer( GetInputHandle() );
538  }
539  } while ( false );
540  }
541 
542  //-------------------------------------------------------------------------
543  // 入力レコード取得関数
544  bool CConsole::InputRecord( SInputRecord& rsRecord, DWORD dwTime ) noexcept {
545  // 処理ブロック
546  bool result = false;
547  do {
548  // タイマを設定する
549  CTimer cTimer( dwTime );
550 
551  // 巡回する
552  while ( !result ) {
553  // 同期処理ブロック
554  do {
555  CSyncAuto cSyncAuto( *this );
556 
557  // 入力レコードカウントを調べる
558  if ( 0 < m_nRecordCount ) {
559  // 入力レコードを取得する
560  rsRecord = m_sRecordBuffer[ m_nRecordPos ];
561 
562  // 入力レコードカウントをデクリメントする
563  if ( 0 == --m_nRecordCount ) {
564  // 入力レコード先頭位置をクリアする
565  m_nRecordPos = 0;
566  }
567  else {
568  // 入力レコード先頭位置を更新する
569  m_nRecordPos = ( ( m_nRecordPos + 1 ) % RECORD_SIZE );
570  }
571 
572  // 成功!
573  result = true;
574  }
575  } while ( false );
576 
577  // タイマを調べる
578  if ( cTimer.Wait( 0 ) ) {
579  // 失敗!
580  break;
581  }
582  // サブスレッドの状態を調べる
583  else if ( m_cThreadSub.Wait( 0 ) ) {
584  // 失敗!
585  break;
586  }
587  }
588  } while ( false );
589 
590  // 実行結果を返す
591  return result;
592  }
593 
594  //-------------------------------------------------------------------------
595  // キー入力待ち関数
596  int CConsole::HitAnyKey( wchar_t const* pszString, DWORD dwTime ) noexcept {
597  // 処理ブロック
598  int result = -1;
599  do {
600  // 文字列ポインタを調べる
601  if ( nullptr != pszString ) {
602  // 文字列を出力する
603  OutputString( pszString );
604  }
605 
606  // 入力バッファをクリアする
608 
609  // 1文字入力する
610  wchar_t ch;
611  if ( !InputChar( ch, dwTime ) ) {
612  // 失敗!
613  break;
614  }
615 
616  // 成功!
617  result = ch;
618  } while ( false );
619 
620  // 実行結果を返す
621  return result;
622  }
623 
624  //-------------------------------------------------------------------------
625  // 確認入力待ち関数
626  bool CConsole::YesNoKey( wchar_t const* pszString, DWORD dwTime ) noexcept {
627  // 処理ブロック
628  bool result = false;
629  do {
630  // 文字列ポインタを調べる
631  if ( nullptr != pszString ) {
632  // 文字列を出力する
633  OutputString( pszString );
634  OutputString( L" " );
635  }
636 
637  // 入力バッファをクリアする
639 
640  // 巡回する
641  for ( ;; ) {
642  // 1文字入力する
643  wchar_t ch;
644  if ( !InputChar( ch, dwTime ) ) {
645  // 失敗!
646  ConsoleNewLine();
647  ConsoleLine( L"1文字入力できませんでした。" );
648  break;
649  }
650 
651  // 文字コードを調べる
652  ch = ::towupper( ch );
653  if ( L'\033' == ch ) {
654  // 失敗!
655  ConsoleLine( L"⇒ いや間違えました… (*^。^*)" );
656  break;
657  }
658  // 文字コードを調べる
659  else if ( L'N' == ch ) {
660  // 失敗!
661  ConsoleLine( L"⇒ いいえ <`ヘ´>" );
662  break;
663  }
664  // 文字コードを調べる
665  else if ( L'Y' == ch ) {
666  // 成功!
667  ConsoleLine( L"⇒ は~い! \(^o^)/" );
668  result = true;
669  break;
670  }
671  // 文字コードを調べる
672  else if ( ( L'\r' == ch ) || ( L'\n' == ch ) ) {
673  // 成功!
674  ConsoleLine( L"⇒ はい、まあなんとか (~_~メ)" );
675  result = true;
676  break;
677  }
678  }
679  } while ( false );
680 
681  // 実行結果を返す
682  return result;
683  }
684 
685  //=========================================================================
686  // 静的公開関数
687  //-------------------------------------------------------------------------
688  // フォントサイズ取得関数
689  bool CConsole::GetFontSize( int& rnWidth, int& rnHeight ) noexcept {
690  // 処理ブロック
691  bool result = false;
692  do {
693  // コンソールフォント情報を取得する
694  CONSOLE_FONT_INFO sFontInfo;
695  if ( 0 == ::GetCurrentConsoleFont( GetOutputHandle(), false, &sFontInfo ) ) {
696  // 失敗!
697  break;
698  }
699 
700  // フォントサイズを取得する
701  rnWidth = sFontInfo.dwFontSize.X;
702  rnHeight = sFontInfo.dwFontSize.Y;
703 
704  // 成功!
705  result = true;
706  } while ( false );
707 
708  // 実行結果を返す
709  return result;
710  }
711 
712  //-------------------------------------------------------------------------
713  // 出力バッファサイズ取得関数
714  bool CConsole::GetSize( int& rnWidth, int& rnHeight ) noexcept {
715  // 処理ブロック
716  bool result = false;
717  do {
718  // コンソールスクリーンバッファ情報を取得する
719  CONSOLE_SCREEN_BUFFER_INFO sInfo;
720  if ( 0 == ::GetConsoleScreenBufferInfo( GetOutputHandle(), &sInfo ) ) {
721  // 失敗!
722  break;
723  }
724 
725  // バッファサイズを取得する
726  rnWidth = sInfo.dwSize.X;
727  rnHeight = sInfo.dwSize.Y;
728 
729  // 成功!
730  result = true;
731  } while ( false );
732 
733  // 実行結果を返す
734  return result;
735  }
736 
737  //-------------------------------------------------------------------------
738  // 出力バッファサイズ設定関数
739  bool CConsole::SetBufferSize( int nWidth, int nHeight ) noexcept {
740  // 処理ブロック
741  bool result = false;
742  do {
743  // スクリーンバッファサイズを設定する
744  COORD sCoord = { static_cast< SHORT >( nWidth ), static_cast< SHORT >( nHeight ) };
745  if ( 0 == ::SetConsoleScreenBufferSize( GetOutputHandle(), sCoord ) ) {
746  // 失敗!
747  break;
748  }
749 
750  // 成功!
751  result = true;
752  } while ( false );
753 
754  // 実行結果を返す
755  return result;
756  }
757 
758  //-------------------------------------------------------------------------
759  // 出力バッファ表示位置取得関数
760  bool CConsole::GetBufferPosition( int& rnLeft, int& rnTop ) noexcept {
761  // 処理ブロック
762  bool result = false;
763  do {
764  // コンソールスクリーンバッファ情報を取得する
765  CONSOLE_SCREEN_BUFFER_INFO sInfo;
766  if ( 0 == ::GetConsoleScreenBufferInfo( GetOutputHandle(), &sInfo ) ) {
767  // 失敗!
768  break;
769  }
770 
771  // 表示位置を取得する
772  rnLeft = sInfo.srWindow.Left;
773  rnTop = sInfo.srWindow.Top;
774 
775  // 成功!
776  result = true;
777  } while ( false );
778 
779  // 実行結果を返す
780  return result;
781  }
782 
783  //-------------------------------------------------------------------------
784  // 出力バッファ表示位置設定関数
785  bool CConsole::SetBufferPosition( int nLeft, int nTop ) noexcept {
786  // 処理ブロック
787  bool result = false;
788  do {
789  // コンソールスクリーンバッファ情報を取得する
790  CONSOLE_SCREEN_BUFFER_INFO sInfo;
791  if ( 0 == ::GetConsoleScreenBufferInfo( GetOutputHandle(), &sInfo ) ) {
792  // 失敗!
793  break;
794  }
795 
796  // コンソール表示領域を設定する
797  SMALL_RECT sRect = {
798  static_cast< SHORT >( nLeft ),
799  static_cast< SHORT >( nTop ),
800  static_cast< SHORT >( nLeft + sInfo.srWindow.Right - sInfo.srWindow.Left ),
801  static_cast< SHORT >( nTop + sInfo.srWindow.Bottom - sInfo.srWindow.Top ) };
802  if ( 0 == ::SetConsoleWindowInfo( GetOutputHandle(), true, &sRect ) ) {
803  // 失敗!
804  break;
805  }
806 
807  // 成功!
808  result = true;
809  } while ( false );
810 
811  // 実行結果を返す
812  return result;
813  }
814 
815  //-------------------------------------------------------------------------
816  // 出力バッファ表示領域取得関数
817  bool CConsole::GetBufferArea( int& rnLeft, int& rnTop, int& rnWidth, int& rnHeight ) noexcept {
818  // 処理ブロック
819  bool result = false;
820  do {
821  // コンソールスクリーンバッファ情報を取得する
822  CONSOLE_SCREEN_BUFFER_INFO sInfo;
823  if ( 0 == ::GetConsoleScreenBufferInfo( GetOutputHandle(), &sInfo ) ) {
824  // 失敗!
825  break;
826  }
827 
828  // ウィンドウ表示領域を取得する
829  rnLeft = sInfo.srWindow.Left;
830  rnTop = sInfo.srWindow.Top;
831  rnWidth = ( sInfo.srWindow.Right - rnLeft + 1 );
832  rnHeight = ( sInfo.srWindow.Bottom - rnTop + 1 );
833 
834  // 成功!
835  result = true;
836  } while ( false );
837 
838  // 実行結果を返す
839  return result;
840  }
841 
842  //-------------------------------------------------------------------------
843  // 出力バッファ表示領域設定関数
844  bool CConsole::SetBufferArea( int nLeft, int nTop, int nWidth, int nHeight ) noexcept {
845  // 処理ブロック
846  bool result = false;
847  do {
848  // コンソール表示領域を設定する
849  SMALL_RECT sRect = {
850  static_cast< SHORT >( nLeft ),
851  static_cast< SHORT >( nTop ),
852  static_cast< SHORT >( nLeft + nWidth - 1 ),
853  static_cast< SHORT >( nTop + nHeight - 1 ) };
854  if ( 0 == ::SetConsoleWindowInfo( GetOutputHandle(), true, &sRect ) ) {
855  // 失敗!
856  break;
857  }
858 
859  // 成功!
860  result = true;
861  } while ( false );
862 
863  // 実行結果を返す
864  return result;
865  }
866 
867  //-------------------------------------------------------------------------
868  // ウィンドウ表示領域取得関数
869  bool CConsole::GetWindowArea( int& rnLeft, int& rnTop, int& rnWidth, int& rnHeight ) noexcept {
870  // 処理ブロック
871  bool result = false;
872  do {
873  // ウィンドウ情報を取得する
874  WINDOWINFO sWndInfo = { sizeof( WINDOWINFO ) };
875  if ( 0 == ::GetWindowInfo( GetWindowHandle(), &sWndInfo ) ) {
876  // 失敗!
877  break;
878  }
879 
880  // ウィンドウ表示領域を取得する
881  rnLeft = sWndInfo.rcWindow.left;
882  rnTop = sWndInfo.rcWindow.top;
883  rnWidth = ( sWndInfo.rcWindow.right - sWndInfo.rcWindow.left + 1 );
884  rnHeight = ( sWndInfo.rcWindow.bottom - sWndInfo.rcWindow.top + 1 );
885 
886  // 成功!
887  result = true;
888  } while ( false );
889 
890  // 実行結果を返す
891  return result;
892  }
893 
894  //-------------------------------------------------------------------------
895  // ウィンドウ表示領域設定関数
896  bool CConsole::SetWindowArea( int nLeft, int nTop, int nWidth, int nHeight ) noexcept {
897  // 処理ブロック
898  bool result = false;
899  do {
900  // ウィンドウ表示位置を設定する
901  ::SetWindowPos( GetWindowHandle(), HWND_TOP, nLeft, nTop, nWidth, nHeight, ( SWP_NOACTIVATE | SWP_SHOWWINDOW ) );
902  ::UpdateWindow( GetWindowHandle() );
903 
904  // 成功!
905  result = true;
906  } while ( false );
907 
908  // 実行結果を返す
909  return result;
910  }
911 
912  //-------------------------------------------------------------------------
913  // カーソル位置取得関数
914  bool CConsole::GetCursorPosition( int& rnX, int& rnY ) noexcept {
915  // 処理ブロック
916  bool result = false;
917  do {
918  // コンソールスクリーンバッファ情報を取得する
919  CONSOLE_SCREEN_BUFFER_INFO sInfo;
920  if ( 0 == ::GetConsoleScreenBufferInfo( GetOutputHandle(), &sInfo ) ) {
921  // 失敗!
922  break;
923  }
924 
925  // カーソル位置を取得する
926  rnX = static_cast< int >( sInfo.dwCursorPosition.X );
927  rnY = static_cast< int >( sInfo.dwCursorPosition.Y );
928 
929  // 成功!
930  result = true;
931  } while ( false );
932 
933  // 実行結果を返す
934  return result;
935  }
936 
937  //-------------------------------------------------------------------------
938  // カーソル位置設定関数
939  bool CConsole::SetCursorPosition( int nX, int nY ) noexcept {
940  // 処理ブロック
941  bool result = false;
942  do {
943  // コンソールスクリーンバッファカーソル位置を設定する
944  COORD sCoord = { static_cast< SHORT >( nX ), static_cast< SHORT >( nY ) };
945  if ( 0 == ::SetConsoleCursorPosition( GetOutputHandle(), sCoord ) ) {
946  // 失敗!
947  break;
948  }
949 
950  // 成功!
951  result = true;
952  } while ( false );
953 
954  // 実行結果を返す
955  return result;
956  }
957 
958  //-------------------------------------------------------------------------
959  // カーソル位置取得関数
960  bool CConsole::GetCursor( COORD& rsCursor ) noexcept {
961  // 処理ブロック
962  bool result = false;
963  do {
964  // コンソールスクリーンバッファ情報を取得する
965  CONSOLE_SCREEN_BUFFER_INFO sInfo;
966  if ( 0 == ::GetConsoleScreenBufferInfo( GetOutputHandle(), &sInfo ) ) {
967  // 失敗!
968  break;
969  }
970 
971  // カーソル位置を取得する
972  rsCursor = sInfo.dwCursorPosition;
973 
974  // 成功!
975  result = true;
976  } while ( false );
977 
978  // 実行結果を返す
979  return result;
980  }
981 
982  //-------------------------------------------------------------------------
983  // カーソル位置設定関数
984  bool CConsole::SetCursor( COORD const& rsCursor ) noexcept {
985  // 処理ブロック
986  bool result = false;
987  do {
988  // コンソールスクリーンバッファカーソル位置を設定する
989  if ( 0 == ::SetConsoleCursorPosition( GetOutputHandle(), rsCursor ) ) {
990  // 失敗!
991  break;
992  }
993 
994  // 成功!
995  result = true;
996  } while ( false );
997 
998  // 実行結果を返す
999  return result;
1000  }
1001 
1002  //-------------------------------------------------------------------------
1003  // ウィンドウスクロール関数
1004  bool CConsole::ScrollWindow( int nX, int nY ) noexcept {
1005  // 処理ブロック
1006  bool result = false;
1007  do {
1008  // コンソール表示領域を設定する
1009  SMALL_RECT sRect = {
1010  static_cast< SHORT >( nX ),
1011  static_cast< SHORT >( nY ),
1012  static_cast< SHORT >( nX ),
1013  static_cast< SHORT >( nY ) };
1014  if ( 0 == ::SetConsoleWindowInfo( GetOutputHandle(), false, &sRect ) ) {
1015  // 失敗!
1016  break;
1017  }
1018 
1019  // 成功!
1020  result = true;
1021  } while ( false );
1022 
1023  // 実行結果を返す
1024  return result;
1025  }
1026 
1027  //-------------------------------------------------------------------------
1028  // コンソール入力バッファ直接入力関数
1029  bool CConsole::InputDirect( wchar_t& rCh ) noexcept {
1030  // 処理ブロック
1031  bool result = false;
1032  do {
1033  // コンソール入力イベントレコードを読み取る
1034  INPUT_RECORD sRecord;
1035  DWORD dwCount;
1036  if ( 0 == ::PeekConsoleInputW( GetInputHandle(), &sRecord, 1, &dwCount ) ) {
1037  // 失敗!
1038  break;
1039  }
1040  // 入力レコード数を調べる
1041  else if ( 0 == dwCount ) {
1042  // 失敗!
1043  break;
1044  }
1045  // コンソール入力イベントレコードをバッファから削除する
1046  else if ( 0 == ::ReadConsoleInputW( GetInputHandle(), &sRecord, 1, &dwCount ) ) {
1047  // 失敗!
1048  break;
1049  }
1050  // 入力レコード数を調べる
1051  else if ( 0 == dwCount ) {
1052  // 失敗!
1053  break;
1054  }
1055 
1056  // 文字コードを取得する
1057  rCh = sRecord.Event.KeyEvent.uChar.UnicodeChar;
1058 
1059  // 成功!
1060  result = true;
1061  } while ( false );
1062 
1063  // 実行結果を返す
1064  return result;
1065  }
1066 
1067  //-------------------------------------------------------------------------
1068  // コンソール入力バッファ直接検査関数
1069  bool CConsole::KbHitDirect() noexcept {
1070  // 処理ブロック
1071  bool result = false;
1072  do {
1073  // コンソール入力バッファにある未読の入力レコード数を取得する
1074  DWORD dwCount;
1075  if ( 0 == ::GetNumberOfConsoleInputEvents( GetInputHandle(), &dwCount ) ) {
1076  // 失敗!
1077  break;
1078  }
1079  // 入力レコード数を調べる
1080  else if ( 0 == dwCount ) {
1081  // 失敗!
1082  break;
1083  }
1084  // 入力レコード数を調べる
1085  else if ( KBHIT_RECORD_SIZE < dwCount ) {
1086  // 入力レコード数を設定する
1087  dwCount = KBHIT_RECORD_SIZE;
1088  }
1089 
1090  // コンソール入力バッファからデータを読み取る
1091  INPUT_RECORD sInputRecord[ KBHIT_RECORD_SIZE ];
1092  if ( 0 == ::PeekConsoleInputW( GetInputHandle(), sInputRecord, dwCount, &dwCount ) ) {
1093  // 失敗!
1094  break;
1095  }
1096  // 巡回する
1097  else for ( DWORD dwIndex = 0; dwCount > dwIndex; ++dwIndex ) {
1098  // イベント種別を調べる
1099  if ( KEY_EVENT == sInputRecord[ dwIndex ].EventType ) {
1100  // 成功!
1101  result = true;
1102  break;
1103  }
1104  }
1105  } while ( false );
1106 
1107  // 実行結果を返す
1108  return result;
1109  }
1110 
1111  //=========================================================================
1112  // 静的限定公開関数
1113  //-------------------------------------------------------------------------
1114  // サブスレッド関数
1115  DWORD CConsole::SubThreadProc( LPVOID lpParam ) noexcept {
1116  // 処理ブロック
1117  DWORD result = 0;
1118  do {
1119  // インスタンスポインタを取得する
1120  CConsole*& rpcInstance = reinterpret_cast< CConsole*& >( lpParam );
1121  if ( nullptr == rpcInstance ) {
1122  // 致命的エラー!
1123  NotifyFatalError();
1124  break;
1125  }
1126  // 巡回する
1127  else for ( ;; ) {
1128  // コンソール入力イベントを取得する
1129  INPUT_RECORD sEvent = {};
1130  DWORD dwCount = 0;
1131  if ( ( 0 == ::ReadConsoleInputW( GetInputHandle(), &sEvent, 1, &dwCount ) ) || ( 0 == dwCount ) ) {
1132  // コンソール入力バッファがシグナル状態になるのを待つ
1133  ::WaitForSingleObject( GetInputHandle(), INFINITE );
1134 
1135  // 継続!
1136  continue;
1137  }
1138  // イベント種別を調べる
1139  else if ( MOUSE_EVENT == sEvent.EventType ) {
1140  // ホイールイベントか調べる
1141  if ( MOUSE_WHEELED == sEvent.Event.MouseEvent.dwEventFlags ) {
1142  // スクロール量を取得する
1143  short nDelta = HIWORD( sEvent.Event.MouseEvent.dwButtonState );
1144  int nScroll = ( -nDelta / WHEEL_DELTA );
1145 
1146  // 上下方向にスクロールする
1147  ScrollWindow( 0, nScroll );
1148  }
1149 
1150  // 継続!
1151  continue;
1152  }
1153  // イベント種別を調べる
1154  else if ( KEY_EVENT != sEvent.EventType ) {
1155  // 継続!
1156  continue;
1157  }
1158  // キー押下状態を調べる
1159  else if ( 0 == sEvent.Event.KeyEvent.bKeyDown ) {
1160  // 継続!
1161  continue;
1162  }
1163 
1164  // 入力レコードを作製する
1165  SInputRecord sRecord = {};
1166  sRecord.m_sEvent = sEvent;
1167  sRecord.m_bShift = ( 0 != ( 0x8000 & ::GetKeyState( VK_SHIFT ) ) );
1168  sRecord.m_bControl = ( 0 != ( 0x8000 & ::GetKeyState( VK_CONTROL ) ) );
1169  sRecord.m_bMenu = ( 0 != ( 0x8000 & ::GetKeyState( VK_MENU ) ) );
1170 
1171  // コントロールキー押下状態を調べる
1172  if ( sRecord.m_bControl ) {
1173  // 入力レコード追加無効フラグをセットする
1174  bool bInvalid = true;
1175 
1176  // オルトキー押下状態を調べる
1177  if ( sRecord.m_bMenu) {
1178  // 仮想キーコードを調べる
1179  switch ( sEvent.Event.KeyEvent.wVirtualKeyCode ) {
1180  default:
1181  // 入力レコード追加無効フラグをクリアする
1182  bInvalid = false;
1183  break;
1184 
1185  case VK_LEFT:
1186  // ウィンドウを左端に表示する
1188  break;
1189 
1190  case VK_UP:
1191  // ウィンドウを上端に表示する
1193  break;
1194 
1195  case VK_RIGHT:
1196  // ウィンドウを右端に表示する
1198  break;
1199 
1200  case VK_DOWN:
1201  // ウィンドウを下端に表示する
1203  break;
1204 
1205  case VK_RETURN:
1206  // ウィンドウをフルサイズ表示する
1208  break;
1209  }
1210  }
1211  // 仮想キーコードを調べる
1212  else switch ( sEvent.Event.KeyEvent.wVirtualKeyCode ) {
1213  default:
1214  // 入力レコード追加無効フラグをクリアする
1215  bInvalid = false;
1216  break;
1217 
1218  case VK_HOME:
1219  // スクリーン表示位置を設定する
1220  SetBufferPosition( 0, 0 );
1221  break;
1222 
1223  case VK_END:
1224  {
1225  // スクリーン表示領域を取得する
1226  int nLeft;
1227  int nTop;
1228  int nWidth;
1229  int nHeight;
1230  if ( GetBufferArea( nLeft, nTop, nWidth, nHeight ) ) {
1231  // スクリーン表示位置を設定する
1232  nTop = ( rpcInstance->m_sMaxCursor.Y - nHeight + 1 );
1233  SetBufferPosition( nLeft, nTop );
1234  }
1235  }
1236  break;
1237 
1238  case VK_RETURN:
1239  // ウィンドウ最大化状態を調べる
1240  if ( ::IsZoomed( GetWindowHandle() ) ) {
1241  // ウィンドウを通常表示する
1242  ::ShowWindow( GetWindowHandle(), SW_SHOWNOACTIVATE );
1243  }
1244  else {
1245  // アクティブウィンドウを取得する
1246  HWND hActive = ::GetActiveWindow();
1247 
1248  // ウィンドウを最大化する
1249  ::ShowWindow( GetWindowHandle(), SW_SHOWMAXIMIZED );
1250 
1251  // アクティブウィンドウを復元する
1252  if ( hActive != ::GetActiveWindow() ) {
1253  ::SetActiveWindow( hActive );
1254  }
1255  }
1256  break;
1257 
1258  case VK_UP:
1259  // 下スクロールする
1260  ScrollWindow( 0, -1 );
1261  break;
1262 
1263  case VK_DOWN:
1264  // 上スクロールする
1265  ScrollWindow( 0, 1 );
1266  break;
1267 
1268  case VK_LEFT:
1269  // 右スクロールする
1270  ScrollWindow( -1, 0 );
1271  break;
1272 
1273  case VK_RIGHT:
1274  // 左スクロールする
1275  ScrollWindow( 1, 0 );
1276  break;
1277 
1278  case VK_PRIOR:
1279  // 下ページスクロールする
1280  ScrollWindow( 0, -20 );
1281  break;
1282 
1283  case VK_NEXT:
1284  // 上ページスクロールする
1285  ScrollWindow( 0, 20 );
1286  break;
1287  }
1288 
1289  // 入力レコード追加無効フラグを調べる
1290  if ( bInvalid ) {
1291  // 継続!
1292  continue;
1293  }
1294  }
1295 
1296  // 同期処理ブロック
1297  do {
1298  CSyncAuto cSyncAuto( *rpcInstance );
1299 
1300  // 入力レコードカウントを調べる
1301  if ( RECORD_SIZE <= rpcInstance->m_nRecordCount ) {
1302  // 入力レコード先頭位置を更新する
1303  rpcInstance->m_nRecordPos = ( ( rpcInstance->m_nRecordPos + 1 ) % RECORD_SIZE );
1304  }
1305 
1306  // 入力レコードリングバッファ更新位置を取得する
1307  int nPos = ( ( rpcInstance->m_nRecordPos + rpcInstance->m_nRecordCount ) % RECORD_SIZE );
1308 
1309  // 入力レコードを設定する
1310  rpcInstance->m_sRecordBuffer[ nPos ] = sRecord;
1311 
1312  // 入力レコードカウントを調べる
1313  if ( RECORD_SIZE > rpcInstance->m_nRecordCount ) {
1314  // 入力レコードカウントをインクリメントする
1315  ++rpcInstance->m_nRecordCount;
1316  }
1317  } while ( false );
1318  }
1319  } while ( false );
1320 
1321  // 実行結果を返す
1322  return result;
1323  }
1324 }
1325 
1326 #pragma managed( pop )
static bool GetBufferPosition(int &rnLeft, int &rnTop) noexcept
出力バッファ表示位置取得関数
Definition: CConsole.cpp:760
virtual HANDLE GetHandle() const noexcept
オブジェクトハンドル取得関数
Definition: CSync.h:68
#define NotifyConstructor()
コンストラクタ実行通知マクロ
Definition: LibUtility.h:24
virtual int HitAnyKey(wchar_t const *pszString=nullptr, DWORD dwTime=INFINITE) noexcept
キー入力待ち関数
Definition: CConsole.cpp:596
COORD m_sMaxCursor
最大カーソル位置
Definition: CConsole.h:587
INPUT_RECORD m_sEvent
入力イベント構造体
Definition: CConsole.h:90
SInputRecord m_sRecordBuffer[RECORD_SIZE]
入力レコードリングバッファ
Definition: CConsole.h:584
static bool KbHitDirect() noexcept
コンソール入力バッファ直接検査関数
Definition: CConsole.cpp:1069
#define NotifyFatalError()
致命的エラー発生通知マクロ
Definition: LibUtility.h:22
bool m_bMenu
オルトキー押下状態フラグ
Definition: CConsole.h:93
wchar_t m_szBuffer[BUFFER_SIZE+1]
文字列バッファ
Definition: CConsole.h:583
static bool InputDirect(wchar_t &rCh) noexcept
コンソール入力バッファ直接入力関数
Definition: CConsole.cpp:1029
#define NotifyDestructor()
デストラクタ実行通知マクロ
Definition: LibUtility.h:25
static HANDLE GetOutputHandle() noexcept
出力ハンドル取得関数
Definition: CConsole.h:315
static bool GetSize(int &rnWidth, int &rnHeight) noexcept
出力バッファサイズ取得関数
Definition: CConsole.cpp:714
CThread m_cThreadSub
サブスレッド
Definition: CConsole.h:588
virtual bool Wait(DWORD dwTime=INFINITE) noexcept override
ウェイト関数
Definition: CTimer.cpp:71
virtual bool InputRecord(SInputRecord &rsRecord, DWORD dwTime) noexcept
入力レコード取得関数
Definition: CConsole.cpp:544
static HWND GetWindowHandle() noexcept
ウィンドウハンドル取得関数
Definition: CConsole.h:326
static bool GetCursorPosition(int &rnX, int &rnY) noexcept
カーソル位置取得関数
Definition: CConsole.cpp:914
#define ConsoleNewLine()
改行出力マクロ
Definition: CConsole.h:29
CConsole() noexcept
コンストラクタ
Definition: CConsole.cpp:31
virtual bool Wait(DWORD dwTime=INFINITE) noexcept
ウェイト関数
Definition: CSync.cpp:59
virtual ~CConsole() noexcept
デストラクタ
Definition: CConsole.cpp:61
static bool GetFontSize(int &rnWidth, int &rnHeight) noexcept
フォントサイズ取得関数
Definition: CConsole.cpp:689
static int const KBHIT_RECORD_SIZE
直接入力検査レコードバッファサイズ
Definition: CConsole.h:578
入力レコード構造体
Definition: CConsole.h:89
static bool GetBufferArea(int &rnLeft, int &rnTop, int &rnWidth, int &rnHeight) noexcept
出力バッファ表示領域取得関数
Definition: CConsole.cpp:817
共通ライブラリ名前空間
Definition: CArray.h:23
static bool SetBufferPosition(int nLeft, int nTop) noexcept
出力バッファ表示位置設定関数
Definition: CConsole.cpp:785
static bool SetBufferSize(int nWidth, int nHeight) noexcept
出力バッファサイズ設定関数
Definition: CConsole.cpp:739
virtual bool Create(wchar_t const *pszObjectName=nullptr) noexcept
作成関数
Definition: CMutex.cpp:143
ミューテックスクラス
Definition: CMutex.h:30
virtual bool OutputChar(wchar_t ch) noexcept
1文字出力関数
Definition: CStreamOut.cpp:45
ストリームクラス
Definition: CStream.h:31
自動同期クラス
Definition: CSyncAuto.h:30
virtual void ClearInputBuffer() noexcept
入力バッファクリア関数
Definition: CConsole.cpp:510
コンソール入出力クラスヘッダコンソール
static bool ScrollWindow(int nX, int nY) noexcept
ウィンドウスクロール関数
Definition: CConsole.cpp:1004
int m_nRecordPos
入力レコード先頭位置
Definition: CConsole.h:585
static bool SetBufferArea(int nLeft, int nTop, int nWidth, int nHeight) noexcept
出力バッファ表示領域設定関数
Definition: CConsole.cpp:844
static bool SetCursorPosition(int nX, int nY) noexcept
カーソル位置設定関数
Definition: CConsole.cpp:939
タイマクラスヘッダファイル
コンソール入出力クラス
Definition: CConsole.h:79
virtual bool OutputString(wchar_t const *pszString) noexcept override
文字列出力関数
Definition: CConsole.cpp:73
#define ConsoleLine(...)
ヘッダインデントなし書式設定文字列行出力マクロ
Definition: CConsole.h:34
int m_nRecordCount
入力レコードカウント
Definition: CConsole.h:586
static int const BUFFER_SIZE
文字列バッファサイズ
Definition: CConsole.h:576
static bool SetCursor(COORD const &rsCursor) noexcept
カーソル位置設定関数
Definition: CConsole.cpp:984
static bool SetWindowArea(int nLeft, int nTop, int nWidth, int nHeight) noexcept
ウィンドウ表示領域設定関数
Definition: CConsole.cpp:896
static bool GetCursor(COORD &rsCursor) noexcept
カーソル位置取得関数
Definition: CConsole.cpp:960
virtual void Close() noexcept override
クローズ関数
Definition: CThread.cpp:46
自動同期クラスヘッダファイル
static DWORD WINAPI SubThreadProc(LPVOID lpParam) noexcept
サブスレッド関数
Definition: CConsole.cpp:1115
タイマクラス
Definition: CTimer.h:30
bool m_bControl
コントロールキー押下状態フラグ
Definition: CConsole.h:92
virtual bool InputChar(wchar_t &rCh) noexcept override
1文字入力関数
Definition: CConsole.h:173
virtual bool YesNoKey(wchar_t const *pszString=nullptr, DWORD dwTime=INFINITE) noexcept
確認入力待ち関数
Definition: CConsole.cpp:626
LIB_COMMON_API bool SetWindowPosition(HWND hWnd, EWindowPosition ePos) noexcept
ウィンドウ表示位置設定関数
Definition: LibUtility.cpp:452
ユーティリティライブラリヘッダファイル
bool m_bShift
シフトキー押下状態フラグ
Definition: CConsole.h:91
static HANDLE GetInputHandle() noexcept
入力ハンドル取得関数
Definition: CConsole.h:304
static int const RECORD_SIZE
入力レコードリングバッファサイズ
Definition: CConsole.h:577
virtual int InputString(wchar_t *pszBuffer, int nSize) noexcept override
文字列入力関数
Definition: CConsole.h:185
bool m_bStopInput
入力中止要求フラグ
Definition: CConsole.h:589
static bool GetWindowArea(int &rnLeft, int &rnTop, int &rnWidth, int &rnHeight) noexcept
ウィンドウ表示領域取得関数
Definition: CConsole.cpp:869