C/C++ ( Windows API 実装 ) でやっています。
GUIとCUIって共存できるのでしょうか?
[定義] ここでいう、GUIは Windows API だと EDIT, RADIO, LISTのようなコントロール, VBA とかだと TextBox, ListBox, RadiButton みたいなコントロール, Javaだと コンポーネントを表示できる、ウィンドウ ( ユーザーフォームとも言われたりするが。 ) のことです。 正式名称は Graphical User Interface らしいです。 CUIは Character User Interface らしいです。 別名? コンソール。
Firefoxは微妙ですが、コマンドライン引数を受け取って,
コマンドライン引数 が "/h" みたいに「ヘルプを表示せよ」のようなオプションのとき、
コマンドライン ( コマンドプロンプト, ターミナル etc. ) に出力しますよね。
あれって、どうやっているのでしょうか?
本体は GUI なのに コマンドラインに表示可能...
どういう風にやっているのでしょうか。
調べてみると「EternalWindows」( http://eternalwindows.jp/ ) がヒットしました。
"猫でもできるプログラミング" もヒットしました。
この EternalWindowsさんで説明されている内容を私なりにクラス化してみました。
ですが、思うように動きません。
動くことは動くのですが、
Windows で言えば STARTコマンドでやったような状態になります。
一応のソースコード:
C++
1// CConsole.h 2 3//---------------------------------------------- 4// インクルードガード BEGIN 5//---------------------------------------------- 6#ifndef CCONSOLE_H 7#define CCONSOLE_H 8 9 10 11//---------------------------------------------- 12// インクルードファイル 13//---------------------------------------------- 14#include<string> 15#include<windows.h> 16 17 18 19//---------------------------------------------- 20// プロトタイプ/クラス宣言 21//---------------------------------------------- 22 23class CConsole{ 24 public: 25 CConsole() throw(int); 26 ~CConsole(); 27 28 bool SetColor( COLORREF foreColor, COLORREF bgColor = -1 ); 29 bool GetColor( COLORREF &foreColor, COLORREF &bgColor ); 30 bool Write( const std::string str ); 31 bool Read( std::string &result ); 32 void Wait( void ); 33 private: 34 HANDLE hOutput; 35 HANDLE hInput; 36 CONSOLE_SCREEN_BUFFER_INFO csbi; 37}; 38 39#endif
C++
1// CConsole.cpp 2 3#include"CConsole.h" 4 5//---------------------------------------------- 6// namespace 7//---------------------------------------------- 8using namespace std; 9 10 11/************************************************************** 12* 13* 参 ・ 引: 14* 「EternalWindows」( http://eternalwindows.jp/ ) 15* ->「Windows開発」 16* ->「コンソール」 17* ->「コンソールへの入出力」 18* 19* 「猫でもわかるプログラミング」( http://www.kumei.ne.jp/c_lang/ ) 20* ->「C言語編 第1部」 21* ->「コンソールアプリで文字色を変える」 22* 23**************************************************************/ 24 25CConsole::CConsole() throw(int){ 26 if( AllocConsole() == 0 ) throw -1; 27 28 hOutput = GetStdHandle( STD_OUTPUT_HANDLE ); 29 hInput = GetStdHandle( STD_INPUT_HANDLE ); 30 31 GetConsoleScreenBufferInfo( hOutput, &csbi ); 32} 33 34 35 36/************************************************************** 37* 38* 参 ・ 引: 39* 「EternalWindows」( http://eternalwindows.jp/ ) 40* ->「Windows開発」 41* ->「コンソール」 42* ->「コンソールへの入出力」 43* 44* 「猫でもわかるプログラミング」( http://www.kumei.ne.jp/c_lang/ ) 45* ->「C言語編 第1部」 46* ->「コンソールアプリで文字色を変える」 47* 48**************************************************************/ 49 50CConsole::~CConsole(){ 51 FreeConsole(); 52} 53 54 55 56/************************************************************** 57* 58* 参 ・ 引: 59* 「EternalWindows」( http://eternalwindows.jp/ ) 60* ->「Windows開発」 61* ->「コンソール」 62* ->「コンソールへの入出力」 63* 64* 「猫でもわかるプログラミング」( http://www.kumei.ne.jp/c_lang/ ) 65* ->「C言語編 第1部」 66* ->「コンソールアプリで文字色を変える」 67* 68**************************************************************/ 69 70bool CConsole::SetColor( COLORREF foreColor, COLORREF bgColor ){ 71 DWORD wAtt; 72 bool flag = false; 73 int counter = 0; 74 75 if( foreColor == PINK ){ 76 flag = false; 77 }else if( foreColor == BLACK ){ 78 wAtt = 0; 79 }else if( foreColor == AQUA ){ 80 flag = false; 81 }else if( foreColor == WHITE ){ 82 wAtt = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; 83 flag = true; 84 }else if( foreColor == RED ){ 85 wAtt = FOREGROUND_RED | FOREGROUND_INTENSITY; 86 flag = true; 87 }else if( foreColor == BLUE ){ 88 wAtt = FOREGROUND_BLUE | FOREGROUND_INTENSITY; 89 flag = true; 90 }else if( foreColor == YELLOW ){ 91 wAtt = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; 92 flag = true; 93 }else if( foreColor == GREEN ){ 94 wAtt = FOREGROUND_GREEN | FOREGROUND_INTENSITY; 95 flag = true; 96 }else if( foreColor == GRAY ){ 97 flag = false; 98 }else if( foreColor == -1 ){ 99 flag = false; 100 } 101 102 // 文字色設定 103 if( flag ){ SetConsoleTextAttribute( hOutput, wAtt ); counter++; } 104 105 // 背景色 も同様にする ( 文字数制限のため、省略 ) 106 107 // 背景色 or 文字色 が変更したなら true を返し、変更なしなら false を返す 108 if( counter == 0 ){ 109 return false; 110 }else{ 111 return true; 112 } 113} 114 115 116 117/************************************************************** 118* 119* 参 ・ 引: 120* 「EternalWindows」( http://eternalwindows.jp/ ) 121* ->「Windows開発」 122* ->「コンソール」 123* ->「コンソールへの入出力」 124* 125**************************************************************/ 126 127bool CConsole::GetColor( COLORREF &foreColor, COLORREF &bgColor ){ 128 // 未チェック 129return false; 130} 131 132 133 134/************************************************************** 135* 136* 参 ・ 引: 137* 「EternalWindows」( http://eternalwindows.jp/ ) 138* ->「Windows開発」 139* ->「コンソール」 140* ->「コンソールへの入出力」 141* 142**************************************************************/ 143 144bool CConsole::Write( const string str ){ 145 DWORD dwWrittenByte; 146 147 if( WriteConsole( hOutput, str.c_str(), str.size(), &dwWrittenByte, NULL ) != 0 ){ 148 return true; 149 }else{ 150 return false; 151 } 152} 153 154 155 156/************************************************************** 157* 158* 参 ・ 引: 159* 「EternalWindows」( http://eternalwindows.jp/ ) 160* ->「Windows開発」 161* ->「コンソール」 162* ->「コンソールへの入出力」 163* 164**************************************************************/ 165 166bool CConsole::Read( std::string &result ){ 167 DWORD dwReadByte; 168 char temp[1000]; 169 170 if( ReadConsole( hInput, temp, 1000, &dwReadByte, NULL ) != 0 ){ 171 return true; 172 }else{ 173 return false; 174 } 175} 176 177 178 179/************************************************************** 180* 181* 備 考: 182* Readメンバ関数を流用しただけ。 183* 184* 185**************************************************************/ 186 187void CConsole::Wait( void ){ 188 string temp; 189 190 this->Read( temp ); 191return; 192} 193
という感じです。
SetColorメンバ関数 の引数は RGBを#defineしたものです。( const でもいいですが。とにかく定数化したものです。 )
これを GUIタイプ ( WinMain関数でやる方 ) の WM_CREATE メッセージのところでインスタンス化し、表示。
WM_DESTROYメッセージで オブジェクト破棄する。
としました。
$rem 実行ファイル名が main.exe だとして。 $main
としても コンソール部分が 別ウィンドウ状態で開きます。
できれば CUIのときみたいに 呼び出し側の コンソールウィンドウ? に出力して、
$rem 実行ファイル名が main.exe だとして。 $main > help.txt
とすれば ファイルに書き込む...みたいにできたらいいのですが...
また、オブジェクトを複数作ってみたのですが、最初の一個は成功するのですが、
二個目は例外が投げられます。
複数の コンソールウィンドウを持つことは不可能なのでしょうか?
もしできるなら、たとえば
メインウィンドウ( GUI ) では 画像を表示等,
サブウィンドウ1 ( CUI ) では ファイル名を変更・編集・次の画像へ...みたいなコマンド入出力,
サブウィンドウ2 ( CUI ) では サブウィンドウ1 での結果を表示
みたいに出来そうなのですが...
CreateWindow関数で毎回作るのもいいですが 面倒だったりします。
クラス化, 関数化してもなぜかうまくいかない ( ウィンドウハンドルが無効等? ) でややこしい...
聞きたいことは、
■ GUIソフトに オプション "-h" または "/h" が与えられたときに 呼び出し側のコマンドラインに 直接出力する( ">" や ">>" を使えば ファイルに書き込まれる ) 方法
■ メインウィンドウは GUIタイプだが、サブウィンドウ(複数) は コンソールタイプとして複数のコンソールを持つ方法
です。
[情報]
言語 : C/C++
コンパイラ: MinGW
Window API: あり
OS : Windows 7
宜しくお願い致します。
回答5件
あなたの回答
tips
プレビュー