VSCode + MinGW-w64 via MSYS2 で WIN32API の Unicode ビルド

VSCode + MinGW-w64 via MSYS2 で WIN32API の Unicode ビルド
本記事は C++ Advent Calendar 2023 の6日目の記事だ。

5日目は @uyamae 氏の C++ をclang で解析するときに情報をvcxproj から取得する方法 だった。


Windows 上でサクッと C++ ビルド環境を用意したい

さて、Win32API のコードをビルドしたいけど Visual Studio を入れるまでもない場合、 MinGW の GCC C++ コンパイラ (g++) と Visual Studio Code (VSCode) の組み合わせでも割と快適にビルドできる。

しかし、 VSCode のドキュメントの手順 そのままでは マルチバイト・Unicode周りでハマったので、非ASCII 圏で問題ないように設定する方法を紹介する。

先に解決方法だけ示しておくと、

  1. tasks.json の g++ ビルド時の引数を書き加えてやりつつ

                 "command": "C:\\msys64\\ucrt64\\bin\\g++.exe",
                 "args": [
                     "-fdiagnostics-color=always",
    +                "-DUNICODE",
    +                "-D_UNICODE",
    +                "-municode",
    +                "-std=c++23",
                     "-g",
                     "${file}",
                     "-o",
                     "${fileDirname}\\${fileBasenameNoExtension}.exe"
                 ],
  2. C/C++ extension for VS Code の設定から、 以下の IntelliSense 設定も変えればよい

    • 定義:

      _DEBUG
      UNICODE
      _UNICODE
    • C 標準: c23

    • C++ 標準: C++23

VSCode + MSYS2 上の MinGW-w64 の組み合わせでの設定

続きを読む

エディットコントロールの高さを、文字列や横幅にあわせて自動的に変更する

横幅がぐりぐり変わり、複数行表示可能なエディットコントロールを、文字列にあわせて、高さを調節したい。

DrawText 関数に、 DT_CALCRECT フラグを設定することで、指定した幅に収まる文字列を表示するのに必要な矩形の取得だけをすることができる(描画されない)。
コレを使ってコントロールの高さを計算し直せば実現できる。

上のエディットコントロールを書き換えると、その文字列が下のエディットコントロールに反映され、サイズが変更されるようなサンプルを作った。

ばりばり ATL/WTL 使ったコードだが、基本的に普通にWin32API呼んでも同じようにできる。

続きを読む

継承するなら、基本・派生どちらにもデストラクタを書かないとしても、仮想デストラクタが必要!?

継承されるクラスに仮想デストラクタを書かなくてはならない理由として、
よく、ポリモーフィズムを使った場合に、派生クラスのデストラクタが実行されない理由が挙げられる。
"継承 仮想デストラクタ" でググった結果

そうすると、「派生クラスにデストラクタ書かなければ当然仮想デストラクタでなくてもいい」と思いがちだが、
実はそんなことは全然無い。

続きを読む

WM_SIZEをハンドルしないCDialogResizeを作る

前回突然オーバーライドと隠ぺいの話をしたのは、
今回の話につなげるため。

CDialogResizeは便利だが、
チェインを使ってコレを処理してしまうと、
その後にWM_SIZEの処理をすることができなくなってしまう。
(チェインする前に捕まえて、 bHadled=FALSE することは可能)

じゃあCDialogResizeを継承して、処理した後にreturnしないようにすればよいのだが、
OnSize関数は仮想関数ではないので、書き換えることができない。

ところが、そのOnSizeを呼んでいるメッセージマップの実態である、
ProcessWindowMessage関数は、(BEGIN_MSG_MAPマクロの中身)
チェインからのみで、CDialogResize内部からは呼ばれていないので、
これを隠ぺいしてしまえば、CDialogResizeのProcessWindowMessageは呼ばれない。

つまり、WM_SIZEを捕まえてもreturnしないProcessWindowMessageを書けばいいのだ。

続きを読む

[C++] 継承クラスでの、仮想関数による再定義(オーバーライド)と、普通の関数の再定義(隠ぺい)の違い

よくある仮想関数を使ったポリモーフィズム(多様性)の例とは少し違うけど
(複数の種類の派生クラスのアドレスを、親クラスのポインタに代入するやつ)、
メソッドをオーバーライドした場合と、隠ぺいした場合の動作の違いを例示すると、
こんな感じのソースになる。 続きを読む

WM_SIZEを処理するとCDialogResizeが動かない?

最近、簡潔さとヘッダだけで動く手軽さ、動作の速さに出力バイナリの小ささから、
ATL/WTLに若干ハマっている。

WM_SIZEを処理するとCDialogResizeが動かないという
初歩的すぎるミスを犯したのでメモメモ。

続きを読む