クリップボードのCF_TEXTについて

[戻る]
ぴょぴょ 2008/07/04(金) 21:46:57
お世話になります。

最近Unicode文字セットでも正しくコンパイルできるように
前よりも意識するようになりました。
そこでふと疑問があります。

クリップボードのCF_TEXTはマルチバイト文字セットで
コンパイルするとANSIテキスト(シフトJISコード)ですよね。
それではUnicode文字セットでコンパイルするとどうなりますか?

最終的にやりたいことはクリップボード内のテキストを
いろいろと加工するソフトを作成するときに文字列を
LPTSTR(LPCTSTR)という型で今までは宣言してきました。

でも実際はマルチバイト文字セット依存の処理です。
http://wisdom.sakura.ne.jp/system/winapi/win32/win90.html
上のリンクではCF_TEXTは
> テキスト形式のデータです
> 各行は復帰改行 (CR-LF) コードで終わります
> データの終端は NULL 文字です
> この形式は、ANSI テキストに使います 
となっています。

[質問1]
Unicode文字セットでコンパイルしてもANSIテキストとして取り出せるのか?

[質問2]
もしもANSIテキストとして取り出されるのならLPTSTR型ではなく
LPSTR(LPCSTR)という型を使うべきか?

[質問3]
クリップボードのデータ量をバイト数(文字数でない)で計算するとき
LPTSTR lpClipboardData;
DWORD dwSize = lstrlen(lpClipboardData) * sizeof(TCHAR);
で良いのか?

長々と書いてしまいましたが、クリップボードの加工プログラムを書くとき
Unicode文字セットでコンパイルして気をつけるべき点を教えて欲しいです。
よろしくお願い致します。

FUKU 2008/07/04(金) 22:32:06
CF_UNICODETEXT

について調べるとよろしいかと

ぴょぴょ 2008/07/05(土) 15:18:12
FUKUさんレスありがとう。

CF_UNICODETEXTは知っています。
この場合もマルチバイト文字コードでコンパイルすると
クリックボードからUnicode文字として取得可能なのでしょうか?

追加質問です。
マルチバイト文字でもUnocode文字セットでも両方で使える
文字変換、テキスト加工の方法はどのようにしたら良いでしょうか?

今はisspaceなどを使って空白はカットしています。
Unicodeではisspaceを呼び出すと実行時にエラーとなります。
Unicodeは文字検査などはどうすればよろしいでしょうか?

FUKU 2008/07/07(月) 10:13:11
>Unicode文字セットでコンパイルして気をつけるべき点

私の場合は、
・文字列リテラルに _Tマクロを使用する。例えば、_T("あああ")
・ANSIからUNICODEに変換する時は、USES_CONVERSION宣言してA2T、逆ならW2Tマクロを使
う
・バイト数を取得する場合はぴょぴょさんと同じ
・isspace等Cランタイムを使う場合は<tchar.h>を見て、defineされているものを使う 
(_istspaceとか)
・最初に_tsetlocale()を呼んでおき、UNICODEでもTRACE()できるようにしておく
・クリップに文字列を設定する場合は(UNICODEなら) ::SetClipboardData
(CF_UNICODETEXT, hMem);

ってとこでしょうか

シャノン 2008/07/07(月) 10:16:45
> Unicode文字セットでコンパイルしてもANSIテキストとして取り出せるのか?

問題は、Unicode でコンパイルしたかどうかではなく、Unicode で格納したかどうかで
す。
文字セットを Unicode にすると、LP(C)TSTR が LP(C)WSTR になるだけであって、依然と
してプログラム内で明示的にマルチバイト文字列を使いたい場合は LP(C)STR を使うこと
が出来ます。
従って、プログラムの文字セットが何であれ、CF_TEXT、CF_UNICODETEXT 両方とも利用可
能です(データ型が適切であれば)。

> もしもANSIテキストとして取り出されるのならLPTSTR型ではなく
> LPSTR(LPCSTR)という型を使うべきか?

はい。

> クリップボードのデータ量をバイト数(文字数でない)で計算するとき
> LPTSTR lpClipboardData;
> DWORD dwSize = lstrlen(lpClipboardData) * sizeof(TCHAR);
> で良いのか?

はい。

クリップボードデータ型はある程度は自動変換されます。
CF_TEXT で格納したデータを CF_UNICODETEXT で取り出すことも、その逆も(こっちは変
換できない文字が出てくる可能性はありますが)可能です。

> マルチバイト文字でもUnocode文字セットでも両方で使える
> 文字変換、テキスト加工の方法はどのようにしたら良いでしょうか?

このへん参照(ジェネリック テキスト マッピング)
http://msdn.microsoft.com/ja-jp/library/c426s321.aspx
http://msdn.microsoft.com/ja-jp/library/tsbaswba.aspx

どうも面倒なことに、LPTSTR のように、プログラムが Unicode ビルドなら CF_TEXT、そ
うでないなら CF_TEXT に自動的に切り替わってくれるクリップボードフォーマット定義
はないみたいです。
自分で #if defined( UNICODE ) を使用して書く必要があるでしょう。

ぴょぴょ 2008/07/07(月) 16:24:03
[[解決]]
FUKUさん。
シャノンさん。
レスをありがとうございます。

> USES_CONVERSION
これはATLで使うものでしょうか?
調べたら次のページが見つかりました。
http://www.atmark.gr.jp/~s2000/r/rtl/encode.html

> isspace等Cランタイムを使う場合は<tchar.h>を見て…
シャノンさんの紹介ページより。
これからは_istdigit()、isdigit()、_ismbcdigit()、iswdigit()を
よくしらべてから利用しようと思います。
ANSI/Unicode共通ならiswdigit()を使います。

> 自分で #if defined( UNICODE ) を使用して書く必要があるでしょう。
これは
#ifdef UNICODE
hMem = GetClipboardData(CF_UNICODETEXT);
#else
hMem = GetClipboardData(CF_TEXT);
#endif
if ( hMem != NULL ){
 処理
}
とすればANSI/Unicode共通のソースが書けるということですね。
文字判定には_istdigit()のタイプを使って。
紹介ページをよく読み調べてみます。

> クリップボードデータ型はある程度は自動変換されます。
ANSI処理限定ならCF_TEXTでデータを取得してLP(C)STR型を使います。

FUKUさん、シャノンさん。
いろいろとありがとうございました。

シャノン 2008/07/07(月) 17:16:30
> ANSI/Unicode共通ならiswdigit()を使います。

No。
共通なら _istdigit です。iswdigit は Unicode 専用です。

> とすればANSI/Unicode共通のソースが書けるということですね。

そうですね。あるいは、

#if !defined(CF_TTEXT)
#if defined(UNICODE)
#define CF_TTEXT CF_UNICODETEXT
#else
#define CF_TTEXT CF_TEXT
#endif
#endif

hMem = GetClipboardData(CF_TTEXT);

とか。

> ANSI処理限定ならCF_TEXTでデータを取得してLP(C)STR型を使います。

ちなみに、ANSI 限定処理ってどんなのですか?

シャノン 2008/07/07(月) 17:18:18
ちなみに、_istdigit という関数があるわけではありません。
ソースコード中に _istdigit と書いた箇所は、コンパイル前に、#define _UNICODE され
ていれば iswdigit に、#define _MBCS されていれば _ismbcdigit に、いずれも 
#define されていなければ isdigit に書き換えてからコンパイルが行われるのです。

ぴょぴょ 2008/07/07(月) 17:49:28
シャノンさん。
ご指摘ありがとうございます。

> No。
> 共通なら _istdigit です。iswdigit は Unicode 専用です。
これコピペのミスです。
気づかなかったです。

> ちなみに、ANSI 限定処理ってどんなのですか?
マルチバイト文字コード(シフトJISコード)の処理限定です。
つまり漢字は2バイトで処理という意味。

> ちなみに、_istdigit という関数があるわけではありません。
> ソースコード中に _istdigit と書いた箇所は、コンパイル前に、#define _UNICODE 
され
> ていれば iswdigit に、#define _MBCS されていれば _ismbcdigit に、いずれも 
> #define されていなければ isdigit に書き換えてからコンパイルが行われるのです。
このうちの_MBCSは自動的に定義されるのでしょうか?

Unicode文字セットなら_UNICODE定数が定義され、
マルチバイト文字セットなら_UNICODE定数が定義されないだけですよね?
それともマルチバイト文字セットなら_MBCSが勝手に(コンパイラ)が
定義してくれるのでしょうか?

シャノン 2008/07/07(月) 18:47:18
プロジェクトのプロパティ内の文字セットの項目には
・Unicode 文字セットを使用する
・マルチ バイト文字セットを使用する
・設定なし
の3つの選択肢があります。
それぞれ、
・UNICODE および _UNICODE が定義される
・_MBCS が定義される
・いずれも定義されない
に対応します。

> マルチバイト文字コード(シフトJISコード)の処理限定です。

IsMBCSLeadByte とかですかね? 最近全然気にしたことがありませんね。

ぴょぴょ 2008/07/07(月) 21:04:19
[[解決]]
ありがとうございます。
シャノンさんのお陰でUNICODE、_UNICODE、_MBCS定数の対応が良く分かりました。

> IsMBCSLeadByte とかですかね? 最近全然気にしたことがありませんね。
ctype.hヘッダのisleadbyteですね。
名前からして同種の関数かな。

こんど時間があるときに文字判定関数とUnicode関連を調べてみます。
今は次のリンクを読んでいます。
http://www5d.biglobe.ne.jp/~noocyte/Programming/CharCode.html

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

古いスレッドには追加発言できません。