10代と話して驚いたこと

C++でDOS窓を使ったプログラムを作っています。
コンソールAPIで色設定(青)をして出力を行ったところ、一定の行から別の色(白)に変わってしまいます。
この問題を解決したいと念じ、かれこれニ昼夜考えあぐねております。目はうさぎのやうに真っ赤になってしまいました。是非ともお力添えを頂きたく恐縮ながらお願い申し上げる次第です。
なお、<conio.h>による色設定は代替策として考慮済みです。

環境:
OS    windows98
コンパイラ C++Builder6

ソース:

#include <iostream.h>
#include <conio.h>
#include <windows.h>

void main()
{
// 出力コンソールのハンドル
HANDLE m_hConsoleStdOut;
// 出力コンソールのハンドルを取得
m_hConsoleStdOut = ::GetStdHandle
(STD_OUTPUT_HANDLE);
// 前景色・背景色属性を設定
::SetConsoleTextAttribute
(m_hConsoleStdOut, 1 + (0 << 4));

for(int i=0;i<30;i++)
printf("\t%2d hello world・・\n",i);
getch();
}

A 回答 (3件)

 環境がまったく異なるので参考情報でしかありませんが…。



 WindowsXP pro SP2, VisualC++ 6.0 という環境で実験してみました。なおソースはそのままではコンパイルを通らず、<iostream.h> を <stdio.h> に直しました。

 結果は、printf を使っていても何の問題も無く、すべての行が青で表示されました。.exe を dumpbin で調べ見ると printf の呼び出しは解決されていて、WriteConsole が呼ばれていました。
 printf はコンパイラ付属のライブラリ(LIBC.LIB)に実装されているようなので、C++Builderとは実装が異なるかもしれません。
 不具合の原因として考えられるのは、
(1) C++Builder の printf の不具合
(2) Windows98 の WriteConsole の不具合
(3) Windows98 の command.com の不具合
(4) Windows98 の ansi.sys の不具合
と言ったとこでしょうか…。
 問題の切り分けのために .exe を Windows 2000 か XP の PC で実行してみてはいかがでしょう? もし正常動作すれば、原因は (2)-(4) のどれかということになります。色指定は (4) の機能なので、(4) が一番怪しい気がしますが…。

 私のほうは逆に家にも会社に 98 の PC が無くて試せていません。もし見つかったら、試してみて続報を入れます。

蛇足:
 for(....) {
   SetConsoleTextAttribute(...);
   printf(...);
 }
という具合に一行ごとに色設定するとどうでしょう?
    • good
    • 0
この回答へのお礼

実験までして頂き、本当にありがとうございます。
oldroot2005様の環境(WindowsXP pro SP2, VisualC++ 6.0)では正常に走るのですね。
コンパイラやOSの不具合の可能性までは思い至りませんでした。お陰様で新たな着眼点を得ることができました。
さっそく、会社のXPのPCで試してみることにいたします。

お礼日時:2005/09/25 19:20

すみません実際に試したりはしてません。

思いついたままです。

えーとですね Windows API を使うなら

The SetConsoleTextAttribute function sets the foreground (text) and background color attributes of characters written to the screen buffer by the WriteFile or WriteConsole function

と言う事ですので

WriteConsole
The WriteConsole function writes a character string to a console screen buffer beginning at the current cursor location.

BOOL WriteConsole(
HANDLE hConsoleOutput, // handle to a console screen buffer
CONST VOID *lpBuffer, // pointer to buffer to write from
DWORD nNumberOfCharsToWrite,
// number of characters to write
LPDWORD lpNumberOfCharsWritten,
// pointer to number of characters written
LPVOID lpReserved // reserved
);

を使って Windows API であくまでも突き進むと言う事になるのではないでしょうか。

printf が WriteConsole を呼び出しているのなら良いけども handle の指定はどうなっているのだろうと思ってしまいますね。基本的に違うんじゃないですか。

98 の DOS窓なら基本的に16bitの世界ですから printf とか使うなら

やはり

conio.h の

void textcolor(int newcolor);
void textbackground(int newcolor);

とかを使ったらいいのではないでしょうか。何かなつかしいですね。

もっと DOS らしく行くなら エスケープシーケンス を使うとか・・・
    • good
    • 0
この回答へのお礼

Rohypnol様、貴重なお時間を割いていただきありがとうございます。APIについての基礎も分からず勉強不足を恥じ入るばかりです。事前にコンソールテキストの属性を設定しておかなければならないということですね。またAPIとprintfが相容れないものかもしれないとのご指摘も参考になりました。APIについてもっと理解を深めるよう努力いたします。

お礼日時:2005/09/12 22:19

未確認ですが、確かコンソールの場合って、


一度画面をクリア(cls)してやらないとリセット
されるんじゃなかったっけ?

この回答への補足

作成中のテキスト・ゲームはスクロールで画面を下に流していく構成になっている為、途中でCLSを使わないでプログラムしたいのです。

補足日時:2005/09/12 21:30
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。画面(25行)からはみ出た分がリセット(デフォルト=白)されてしまうという考え方ですね。

お礼日時:2005/09/12 21:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報