2017-10-23 12 views
0

winapi 및 kernel32 상자를 사용하여 Rust로 Windows 콘솔 전경 텍스트 색을 변경하려고합니다.Windows 콘솔의 텍스트 색 설정이 예상대로 작동하지 않습니다.

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

코드 내가 전경 색상 값을 저장

열거 :

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") 
    } 
} 

기능 전경 색상을 설정 : 출력 핸들을 얻을 수

#[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, 
    // ... 
} 

기능 사용 rnel32; 나는 20 X에 블록 및 Y.에 20 상자를 만드는 오전 내 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의 색상과주고 싶어.

// 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에 있습니까? 한 줄에 여러 색상을 사용할 수 있기 전에 어딘가에 지정해야합니까?

+0

윈도우 콘솔이 아닌 ASCII 값으로 악명이 까다 롭습니다; ■보다 간단한 것을 시도해보십시오. – Shepmaster

+0

@Shepmaster'이 (가)' + 254를 누르면 ASCII 테이블에 저장됩니다. 그리고이 문제는 정상적인 번호에서도 발생합니다 (방금 시도했습니다). –

+0

ASCII로 돌아가서 다시 읽으시기 바랍니다. 128보다 작은 숫자 값만 ASCII입니다. – Shepmaster

답변

4

녹의 표준 출력은 라인 버퍼입니다. 따라서 텍스트는 한 번에 한 줄씩 콘솔로 보내 지므로 전체 줄의 색상이 동일합니다.

당신은 사용하여 각 print! 후 출력을 세척 할 수 있습니다

use std::io::Write; 

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

Works 완벽하게 !! 그것은 많은 것을 설명합니다. –