ボンジュール・マドモアゼル

本サイトの情報は自己責任にてご利用下さい。

[VC] Windows コマンドライン引数を解析する必要なし

 
_tWinMain, WinMain は main(int argc, char **argv) と違って、
コマンドラインが一つの文字列として渡されるから、
解析の必要があるかと思われるが __argc, __argv, __targv
などのグローバル変数を使えばよい。
  1. 2012/05/29(火) 08:44:15|
  2. VC|
  3. トラックバック(-)|
  4. コメント:0

[VC] リソースファイル Visual C++独自仕様について

 
※以下、内容が正確かどうかはわかりません。誤りがあった場合には一報頂けると助かります。
■ブロック構成
Visual C++ のリソースファイルは、リソースエディタとリソースコンパイラのふたつのアプリケーションによってアクセスされる。これらアプリケーションに対して、リソース定義のアクセス制御を行うため、リソースファイルはシンボル定義によってブロック化される。ブロックは以下のものがある。

※ブロックの名前は正式なものではない、説明のための便宜的なもの。


(1) APSTUDIO_READONLY_SYMBOLS ブロック
#define APSTUDIO_READONLY_SYMBOLS 〜 #undef APSTUDIO_READONLY_SYMBOLS で括られるブロック。このブロックは、リソースコンパイラ、リソースエディタの両方から参照される領域だが、リソースエディタは、シンボル定義を目的として、#include, #define, #ifdef 等のディレクティブのみを解釈し、それ以外のコードを無視する。
このブロックで定義されるシンボル名および定義値は、リソースエディタで変更することはできない。ただし、例外として、resource.h などの読み書き可能なヘッダーファイルをこのブロックでインクルードしている場合、そのファイルで定義されるシンボルはリソースエディタで変更できる。

(2) APSTUDIO_INVOKED ブロック
リソースエディタでのみ有効なブロック、リソースコンパイラ時には無視される。主にTEXTINCLUDE リソースを定義するためのブロックである。

(2.5) APSTUDIO_HIDDEN_SYMBOLS (図にはない、おまけ)
#define APSTUDIO_HIDDEN_SYMBOLS 〜 #undef APSTUDIO_HIDDEN_SYMBOLS で括られたブロック。このブロック内で定義されたシンボルは、リソースエディタのシンボルブラウザには表示されない。また、リソースエディタ上、このブロックで定義されたリソースIDはシンボル表記の箇所が整数値表記となる。

(3) Non-APSTUDIO_INVOKED ブロック
#ifndef APSTUDIO_INVOKED 〜 #endif で括られるブロック。このブロック内の文字列は、リソースエディタでは無視され、リソースコンパイル時のみ適用される。

(4) リソースコンパイラとリソースエディタの両方でアクセスするブロック
上記以外の領域は、リソースコンパイラとリソースエディタの両方でアクセスされる。


VCリソースファイルの構成



■ TEXTINCLUDE リソース

APSTUDIO_READONLY_SYMBOLS ブロックおよび、Non-APSTUDIO_INVOKED ブロック内で定義したコードは、同一の内容を、APSTUDIO_INVOKED ブロック内に TEXTINCLUDE リソースとして特別な記法で定義する必要がある。なぜ、同じ内容をわざわざ TEXTINCLUDE リソースとして定義する必要があるのか。それは、ブロック内に書かれるべきコードをリソース化し、.apsファイルにロードするためである。
このことを理解するのは、リソースファイルの読込みから保存までのデータの流れを追ってみるのが早い。下図のとおり、リソースファイルのオープン時、APSTUDIO_READONLY_SYMBOLS ブロックで定義されたシンボルが、.aps ファイルに読み込まれ、TEXTINCLUDEリソースは、リソースとして、.aps ファイルに取り込まれる。そして、リソースファイルの保存時には、ロードされた .aps ファイル 内の TEXTINCLUDE リソースが、各ブロックへ保存される。したがって、リソースエディタでリソースファイルを保存したときには、APSTUDIO_READONLY_SYMBOLS ブロックおよび、Non-APSTUDIO_INVOKED ブロック内にもともと記述されたコードは保存後のファイルには直接、引き継がれないのである。

リソースファイルデータフロー



TEXTINCLUDE リソースとは、リソースファイル上の文字列を、apsファイルに引き継ぎぐため、リソース化したものである。TEXTINCLUDE リソースは、1, 2, 3 の各リソースIDによって動作が異なり、各々の動作は以下のとおりとなる。

1 TEXTINCLUDE
新規リソースIDを保存するファイル名を指定する。このファイルには新規リソースに割り振られる次の番号なども保存される。このリソースが未定義の場合、resource.h がそれらの情報を書き込むファイルとなる。通常、このファイルで定義済みのシンボルは、その整数値をリソースエディタ上で変更することができる。リソースエディタでリソースファイルを保存すると、ここで指定したファイル名は、次のようにリソースファイルの先頭に展開される。

#include "ファイル名"

なお、このリソースに無効なファイル名が指定されているリソースファイルは、リソースエディタでは保存することができない。MFCの標準リソースファイルは、この制限を利用して、当該ファイルを書き込み不可としている。

2 TEXTINCLUDE
このリソースで定義された文字列は、リソースエディタでリソースファイルを保存する時、APSTUDIO_READONLY_SYMBOLS ブロック内に保存されるデータ元となる。通常、このリソースでは、読み取り専用シンボル、もしくは、読み取り専用のシンボル定義を含むファイルをインクルードするディレクティブを定義する。

3 TEXTINCLUDE
このリソースで定義された文字列は、リソースエディタでリソースファイルを保存する時、Non-APSTUDIO_INVOKED ブロック内に保存されるデータ元となる。通常、このリソースでは、リソースコンパイル時にインクルードしたいファイルなど、リソースコンパイル時のみ有効にしたいコードを記述する。

テクニカルノート35についての蛇足

話の発端は、リソースは、ひとつのプロジェクトに対して、ひとつの翻訳単位のリソースファイルとして構成する必要性にある。

[VC] Visual Studio が include したリソースファイルをマージすることの検証

 
Visual C++ が読み込む .RC ファイルの中で、コンパイル時ディレクティブを使用せずに #include ディレクティブによってほかの .RC ファイルをインクルードしているときは注意してください。従来のようにテキスト エディタを使用して編集した .RC ファイルを Visual C++ に取り込む場合はこの点が問題となります。Visual C++ はインクルードされている .RC ファイルを読み込み、その中に定義されているリソースをインクルード元の .RC ファイルのリソースにマージします。インクルード元の .RC ファイルを保存すると、ファイルの中の #include ステートメントがインクルードされるリソースに置き換えられます。

MFC ライブラリ リファレンス
テクニカル ノート 35: Visual C++ における複数のリソース ファイルとヘッダー ファイルの使用




要は、リソースファイル内に、単に #include で取り込んだ外部ファイルは、リソースエディタでは、展開されてマージされてしまいますよ、ということ。そこで、Visual Studio 6.0 で実際に検証してみた。

1. 外部ファイルと、それをインクルードしたリソースファイルを用意する


外部ファイル subres.rc2
STRINGTABLE DISCARDABLE

BEGIN
IDS_MYSAMP1 "My Sample String1"
IDS_MYSAMP2 "My Sample String2"
END


リソースファイル(インクルード元)ResTest.rc
...

STRINGTABLE DISCARDABLE
BEGIN
IDS_APP_TITLE "ResTest"
IDS_HELLO "Hello World!"
IDC_RESTEST "RESTEST"
END

#endif // 日本語 resources
/////////////////////////////////////////////////////////////////////////////

#include "subres.rc2"
...


ストリングテーブルをリソースエディタで確認する。
ストリングテーブル確認


2. リソースエディタにてリソースを編集する

あえて、ストリングテーブルとは関係ないダイアログを編集し保存する.
編集前ダイアログ編集前


編集後ダイアログ編集後


3. 保存後、リソースファイルを確認する

リソースファイル(インクルード元)ResTest.rc
...

STRINGTABLE DISCARDABLE
BEGIN
IDS_APP_TITLE "ResTest"
IDS_HELLO "Hello World!"
IDC_RESTEST "RESTEST"
IDS_MYSAMP1 "My Sample String1"
IDS_MYSAMP2 "My Sample String2"
END
...
お、ほんとだ。外部ファイルの内容がマージされている。