2017-10-23 11 views
0

winapiとkernel32のクレートを使って、RustでWindowsコンソールの前景色を変更しようとしています。出力ハンドルを取得Windowsコンソールのテキストの色が期待どおりに動作しない

#[repr(u16)] 
pub enum ForegroundColor { 
    RED = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_RED) as u16, 
    CYAN = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, 
    // ... 
} 

機能::前景色を設定します

use winapi; 
use winapi::{CONSOLE_SCREEN_BUFFER_INFO, COORD, HANDLE, SMALL_RECT, WORD}; 
use kernel32; 

static mut CONSOLE_OUTPUT_HANDLE: Option<HANDLE> = None; 
pub fn get_output_handle() -> HANDLE { 
    unsafe { 
     if let Some(handle) = CONSOLE_OUTPUT_HANDLE { 
      handle_check(handle); 
      handle 
     } else { 
      let handle = kernel32::GetStdHandle(winapi::STD_OUTPUT_HANDLE); 
      handle_check(handle); 
      CONSOLE_OUTPUT_HANDLE = Some(handle); 
      handle 
     } 
    } 
} 

fn handle_check(handle: HANDLE) { 
    if handle == winapi::INVALID_HANDLE_VALUE { 
     panic!("NoConsole") 
    } 
} 

機能私は前景色値を格納

[dependencies] 
winapi = "0.2.8" 
kernel32-sys = "0.2.1" 

コード

列挙 を使用rnel32;私main.rs

// ForegroundColor is a struct containing win32 colors 
pub fn set_foreground_color(for_color: ForegroundColor) { 
    // function shown above 
    let output_handle = kernel::get_output_handle(); 
    // cast the enum value to a u16: fn to_u16(&self) -> u16 { *self as u16 } 
    let forground_color = for_color.to_u16(); 

    unsafe { 
     kernel32::SetConsoleTextAttribute(output_handle, forground_color); 
    } 
} 

私はRED色の内側の境界線にCYANの色を与えるとしたいY.に20 X上のブロックと20でボックスを作成しています。何らかの理由で

// for example 1 has to be cyan and 2 red but than on larger scale 
// 1111 
// 1221 
// 1111 
for y in 0..21 { 
    for x in 0..21 { 
     if (x == 0 || y == 0) || (x == 20 || y == 20) { 
      // function shown above 
      set_foreground_color(ForegroundColor::CYAN); 
      // Print a cyan colored ■ 
      print!("■") 
     } else { 
      // function shown above 
      set_foreground_color(ForegroundColor::RED); 
      // Print a red colored ■ 
      print!("■") 
     } 
    } 
    // reset cursor to start of new line 
    println!(); 
} 

、すべてCYAN色を持っていますし、任意の赤いものは存在しません。

print!()を同じコードに置き換えてprintln!()に置き換えると、REDCYANの色付きブロックが期待通りに印刷されます。 はすべて期待どおりの色ですが、今問題はがそれ自身の行にあることです。

println!()を使用すると、テキストの色が期待どおりに変化するのはなぜですか?なぜ私はprint!()と同じ行の色を変えることができないのですか? winapiにコンソールラインの色を保存するバッファがありますか? 1行に複数の色を使用するには、どこかに指定する必要がありますか?

+0

Windowsコンソールは、非ASCII値の悪名高いトリッキーです。 ■より簡単なものを試してみませんか? – Shepmaster

+0

@Shepmaster '■'は、 ' + 254'を押すとASCIIテーブルに置かれます。そして、この問題は通常の数字(試しただけ)でも発生します。 –

+0

私はあなたが戻って、ASCIIが何であるか再読することを強くお勧めします。 128未満の数値のみがASCIIです。 – Shepmaster

答えて

4

ルーストの標準出力はラインバッファです。つまり、テキストは一度に1行ずつコンソールに送信されます。つまり、行全体が同じ色になります。

あなたが使用して各print!後に出力をフラッシュすることができます

use std::io::Write; 

std::io::stdout().flush().expect("Flush stdout failed"); 
+0

Worksパーフェクト!!それはたくさん説明します。 –

関連する問題