ページ 11

ReadConsoleOutput()の挙動について

Posted: 2014年5月05日(月) 18:23
by usao
環境 : Win7 Home(64bit) , VS2012 Express

Win32APIの ReadConsoleOutput() についてです.
MSDNによると,この関数は,
情報を取得したい領域矩形をコンソールスクリーンバッファからはみ出す形に指定した場合でも
よろしくやってくれる(はみ出さない部分についてのみの情報をくれる)ことになっているのですが,
プロジェクトが「Unicode文字セットを使用する」設定になっているとうまくいかないようで困っております.

以下のコードを
「マルチバイト文字セットを使用する」設定でビルド→実行した場合だと
ただしく はみ出さない部分についての情報を取得できています.
(結果スクリーンショット添付します.これが所望の動作です)

しかし,前述のように設定を「Unicode~」に変えると正しく取得できません.
なぜか結果の一部に 0 が入れられてしまうのです.
(結果とデバッガで受取バッファ内を見たところのスクリーンショット添付します)

原因や対応策(Unicode設定で所望の結果を得る方法)についてご教授いただきたく,お願い申し上げます.
► スポイラーを表示

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月05日(月) 18:36
by h2so5
僕のマシンだと実行結果が異なります。
環境 : Win8.1 , VS2010

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月05日(月) 21:44
by usao
>僕のマシンだと実行結果が異なります。

ご確認いただきありがとうございます.

MBCSならOKというわけでもないのですね.
「はみ出さないように指定する」しかないのでしょうか…

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月06日(火) 10:33
by へにっくす
MBCS/Unicodeの違いは文字コードなのはわかりますよね?
なのに何でコンソールの文字コードは変えてないのですか。
GetStdHandleする前に、以下のコードを追加して文字コードを切り替えてください。
※VS2012 Win7の環境で確認。

コード:

#ifdef _UNICODE
	::SetConsoleOutputCP(65001); // UTF-8
#else
	::SetConsoleOutputCP(932); // Shift-JIS
#endif
SetConsoleOutputCP関数 - MSDN

※Win8.1 VS2013でやったらこれでもダメでした(ただしMBCS/Unicodeの切り替えでは同じ結果です。なぜか3行目を取得できないので、別の問題?バグかしら・・・)。

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月06日(火) 11:18
by usao
>GetStdHandleする前に、文字コードを切り替えてください。

ありがとうございます.
SetConsoleOutputCP()を使うと とりあえず私の環境では
前述のコードが「所望の動作」になることを確認いたしました.
(GetConsoleOutputCP()で調べてみたところ,
 プロジェクトの文字コードの設定に関わらずデフォルト状態だと 932 が返されていました.)

SetConsoleOutputCP()に渡す引数の値は何ぞや?という点については,
MSDNのSetConsoleOutputCP()の英語版の方
http://msdn.microsoft.com/en-us/library/ms686036
には,Code Page Identifiers というページ
http://msdn.microsoft.com/en-us/library/dd317756
へのリンクがあり,そこに書かれていました.

#何やらフォントの具合も変わる?(65001にしたら文字が太い)ようです


>※Win8.1 VS2013でやったらこれでもダメでした
おっと,この場合,[解決]とは行かないのかな.

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月06日(火) 11:54
by へにっくす
usao さんが書きました:#何やらフォントの具合も変わる?(65001にしたら文字が太い)ようです
それは太いのではなく、UTF-8対応のフォントに自動的に切り替わるからですね。
usao さんが書きました:>※Win8.1 VS2013でやったらこれでもダメでした
おっと,この場合,[解決]とは行かないのかな.
Win8.1での現象は、質問の趣旨とはまた別の問題かと思いますよ。
MBCS/Unicodeの切り替えでも変わらないし。
MSDN forumに投稿した方がいいかも。
(・・・ってusaoさんに言っても仕方がないか ^^;)

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月06日(火) 12:14
by usao
>それは太いのではなく、UTF-8対応のフォントに自動的に切り替わるからですね。

その関係なのか,65001にしたら
WriteConsole()で日本語を含む文字列を出力できなくなってしまいました T_T
フォントの設定とかがいるのかも…
(しかしWriteConsoleOutputCharacter()のほうは元気に日本語出力してます.なぜか.)
オフトピック
関係あるのか無いのかわかりませんが,ググっていたらこんなのがあり,
http://stackoverflow.com/questions/1088 ... ws-console
ここでは SetConsoleOutputCP()ではなく _setmode() とかいうのを使う話がされているようで…?

うーん,MBCSの世界に引きこもりたい……

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月06日(火) 13:02
by へにっくす
これ参考になるかな。
XPだと隠しAPIを使わないとフォントを変更できないらしい。Vista以降なら公開されているAPIがあるが
Win32APIでコンソールをゴリゴリと

・・・ってーか趣旨と変わってないかw
オフトピック
Unicode使わなければならない理由でもあるの?

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月06日(火) 13:16
by usao
>・・・ってーか趣旨と変わってないかw

SetConsoleOutputCP()を使う方法で 他の事に副作用(?)が出てしまったので
このまま解決でいいのかなぁ,とか思ったので…

まぁ 最初のコードについては こちらの環境では動作結果が改善したということで
[解決]をつけておきます.


とりあえず直近ではMBCSの世界に逃げておいて,
コンソール+Unicode の色々な問題については 今後,時間があるときにでも調べてみようかと思います.

ありがとうございました.

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月06日(火) 17:33
by Mana
こちらではコマンドプロンプトのコードページは932のままでUnicodeでもMBCSでもちゃんと表示できたけども。
環境 : Win7 Ultimate(64bit) , VS Express 2013 for Desktop

ただし画面に表示されているのではなく画面バッファから取得するらしく
No.1のコードの最初に
::system("cls");
を加えることで安定した。
こちらの環境はバッファ大きくしてるから。

Re: ReadConsoleOutput()の挙動について

Posted: 2014年5月07日(水) 19:12
by Mana
IDEやエクスプローラーから起動するなら::system("cls")関係ありませんね。

こちらでは常に正常なので検証不可ですがロケールが関係するのかもしれないと思い付いたので投稿。