2017年7月19日水曜日

オーナードローでサブメニューの▶を描画する方法

メニューのオーナードローをした時、どうしても制御できないのがメニューのボーダ部分とサブメニューの▶の部分
いろいろ調べて▶の部分が制御ができるようになった。

オーナードローをしても、枠の灰色の線とSubの隣の▶の色が環境依存で、指定が出来ない。
▶については、通常黒で、選択すると反転して白になる。
左図のような黒背景だと▶が見えない。
DrawItemイベントでは描画しておらず、その後に勝手に描画されるからSetTextColorとか適用されないかな?と思ったけど無視される。

やり方は、ExcludeClipRectでメニュー項目全体をクリップすると、勝手に描画されるのを抑制できるので、あとは自分で描画するだけ。

通常状態でも白で表示出来るようになった。

2017年5月16日火曜日

VS2017のAllocConsoleでUnicode(UTF-16)出力

std::wcout.imbue(std::locale("Japanese")) ;
AllocConsole() ;
FILE * pF = _wfdopen( h, L"w" ) ;
fclose( stdout ) ;
*stdout = *pF;
setvbuf( stdout, NULL, _IONBF, 0 ) ;

VS2010では上記のコードで、wcout、wprintfを使ってコンソール出力が出来た。

VS2017でコンパイルすると、コンパイルは通るが実行すると落ちる。
いろいろ調べてみた結果、_wfreopen(freopen)でstdoutを"CONOUT$"で開き直すとコンソールと紐付けは出来るようだ。

でも、printfすると落ちる。
wprintfすると表示されなかったり、表示されるが16進文字だったり、文字化けしていたり。
wcoutは日本語は表示されるが、"\n"、endlの部分で落ちる。
coutはやってない。
唯一、表示されるのがWriteConsole関数。

試してみたのは下記のキーワード
wcout.imbue
_wsetlocale(setlocale)
setvbuf
_setmode
wcout.rdbuf
SetConsoleOutputCP
sync_with_stdio

どうやってもまともに表示されない。

色々やっているとwcoutで落ちるのは、rdbufが準備できていない?感じで、rdbufを入れ替える方法を見つけたのでwcout以外は全部捨てて対応したコードが下記。

class Out {
private :
class Buf : public std::wstreambuf {
private :
HANDLE h ;
public :
virtual int_type overflow( int_type c = EOF ) override {
if( c == EOF ) return c ;
wchar_t sBuf[] = { c, '\0' } ;
DWORD nW ;
WriteConsole( this->h, sBuf, 1, &nW, NULL ) ;
return c ;
}
Buf( void ) {
this->h = GetStdHandle( STD_OUTPUT_HANDLE ) ;
}
} oBuf ;
std::wstreambuf * pOld ;
public:
Out( void ) { this->pOld = std::wcout.rdbuf( &oBuf ) ; }
~Out( void ) { std::wcout.rdbuf( this->pOld ) ; }
} ;

AllocConsoleした後に、Outクラスのインスタンスを作ると、wcoutのバッファがoverflow関数に1文字ずつ渡ってくるらしい。内部では唯一まともに動くWriteConsoleを呼び出す。