【C++】ウィンドウスタイルを維持しながらタイトルバーを消す方法

C++
この記事は約3分で読めます。

最近だと非公開のAPIでタイトルバーの色は黒に変更できるようですが、C++/Win32でタイトルバーを自作したい人向けです。

おすすめコンポーネント

C++でやるならこのウィンドウ一択かと思いますね。私が調べて実装した内容がほぼすべて網羅されているように思います。対象OSもWindows7/8/8.1/10なので十分ですね。

BorderlessWindow の課題

基本的に非クライアント領域を変更するとウィンドウのスタイルがクラシックな感じに変更されます。そして、ウィンドウの影なども消えてしまいます。これが嫌な人は多いように思いました。私もその一人です。


OS のウィンドウスタイルは残してタイトルバーだけを消したいですよね?ほんとは API でタイトルバーをカスタムドローできるようにしてくれると一番いいんですけどね。なかなか変更させてくれませんよね。


そんでもってこの BorderlessWindow はウィンドウのスタイルを維持しながらタイトルバーを削除するのですが、1点問題があります。ウィンドウの色を標準の白のままで使う場合はいいのですが、黒にするとウィンドウの1pxの枠線が目立ちます。

これが凄く目立つんですよね。この枠線の色を変更する方法をずっと探していました。ちなみにこの枠線はウィンドウのタイトルバーやウィンドウの枠(非クライアント領域)です。


これは WM_NCCALCSIZE メッセージでタイトルバーや枠を無くした後に DwmExtendFrameIntoClientArea で上下左右に 1px 付けられています。


別に上でも下でも 1px つけていればウィンドウのスタイルは保持されます。ただ、全部を 0 px にするとウィンドウの影が失われます。これがほんと困りもんなんですよね。


影が無くなってもウィンドウスタイルに CS_DROPSHADOW を付ければそれっぽい影が付きます。これで我慢できればいいんですが、できないんですよね。ウィンドウの影は付けたいけど枠は消したくてめちゃくちゃ悩んでました。

回避策

WM_PAINT や WM_NCPAINT なんかで 黒で上書きしようとしたのですが、これがまたうまくいきませんでした。以前にC#で同じようにタイトルバーを削除したのですがこの時は、白の枠線はあるのですが、ToolStripを配置すると何故か消えたんですよね。


正確には枠線の上にコントロールがのって見えない感じです。今日までなんで C# は消えて C++ は表示されるのか?これも謎でした。完全に諦めかけていたのですが、ダメ元で.net のソースを見てみるとコントロールの背景色の描画にGDI+を利用していること確認しました。


もしかしてと思い GDI+ で枠線を上書きしてみると普通に上書きできました。あれっ?って感じですよね。GDIでどー頑張っても上手くいかなかったんですが、なぜか GDI+ だと上書きできるって…。ちなみに Direct2D でも上書きできました。上書きしたイメージはこんな感じ。青色で上書きしています。

なぜ上書きできるのかは不明ですが、DwmExtendFrameIntoClientArea の仕様なんですかね?それとも GDI+ の仕様?それともそんなもんなんでしょうか?


ただ、リサイズした時に若干、下の白線が見えたりしますが許容範囲かなと思います。調べたアプリの中では MusicBee なんかも同じ挙動でした。VB.netで作成されているようなので、この方法で上書きしてるんじゃないかと思いますね。

おわりに

もし、タイトルバーを独自に実装してこの白線を消したい方は裏技っぽいですが、GDI+ か Direct2D で上書きすることを検討してみるのはどうでしょうか?

コメント

タイトルとURLをコピーしました