前提・実現したいこと
WindowsAPIの基本的なDrawTextEx
のレンダリングについて型が合わないとエラーが出ます。
発生している問題・エラーメッセージ
'int DrawTextExA(HDC,LPSTR,int,LPRECT,UINT,LPDRAWTEXTPARAMS)': 引数 2 を 'LPCTSTR' から 'LPSTR' へ変換できません。
該当のソースコード
LPCTSTR Lender3 = TEXT("Hello World\nWindows API Programming");
DrawTextEx( hdc, Lender3, -1, &rc, DT_WORDBREAK|DT_EXPANDTABS|DT_TABSTOP, &dtp );
試したこと
DrawTextEx
は調べてもLPTSTRと定義されているのにエラーメッセージではLPSTRと出てきます。LPSTRをLPTSTRにするとTEXTマクロが使えなかったり文字コードの仕組みがよくわかりません。
どうすれば以上の関数を使用できるでしょうか。ほかの関数で代用できることはわかりますがこの関数の使い方を知りたいです。
そして文字コードは基本的にUNICODEで統一していったほうがいいんでしょうか。
補足情報(FW/ツールのバージョンなど)
VisualStudio2017 Community
Windows10 Pro
C++
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答3件
0
ドキュメントによると、食わせる文字列は変更される(最大4文字長くなる)可能性があるとのこと。
長メのTCHAR配列を用意し、文字列をコピーしてDrawTextEx()に食わすことになろうかと。
C
1TCHAR Lender3[256] = TEXT("Hello World\nWindows API Programming"); 2DrawTextEx( 3 hdc, 4 Lender3, 5 -1, 6 &rc, 7 DT_WORDBREAK|DT_EXPANDTABS|DT_TABSTOP, 8 &dtp 9 );
※ 変更される恐れがないならconst_cast<LPSTR>(Lender3)
でもよさげ。
[追記] ↑違うポ。 gazette2さんのフォロー回答を参照されたし。
投稿2018/02/26 20:14
編集2018/02/27 02:12総合スコア16612
0
ベストアンサー
一般的な文字列コードに関するエラーを避ける方法は次のようになります。
- Tのあるマクロを使用する。
LPCWSTR, LPCSTR → LPCTSTR
LPWSTR, LPSTR → LPTSTR
WCHAR, CHAR → TCHAR
- 文字列は_T()で囲む
LPCSTR x = "...";
LPCWSTR x = L"...";
LPCWSTR x = TEXT("...");
→ LPCTSTR x = _T("...");
- strlenなどの標準C関数使用時に注意
strlen : Ansi用
wcslen : Unicode用
tcslen : strlenの T version.
0. なるべくUnicode設定を使用する
そして、epistemeさんの答えに捕捉です。
追加説明したい部分は
変更される恐れがないならconst_cast<LPSTR>(Lender3) でもよさげ
ですが、これは正しい情報ではありません。
一応
TSTR WCHAR LPTSTR LPCSTR LPCTSTRなどいろいろありまして複雑に思われますが要すると次のようになります。
- Cは const(コードの説明ではあまり重要ではありません)
- Wは Unicode
- WもTもないものは Ansi(Multi-byteコードもansiの一種)
- Tはマジック文字(ワイルドカード)
例えば
LPWSTR, WCHAR, LPCWSTRなどはすべてUnicodeです。
LPSTR, CHAR, LPCSTRなどはAnsiコードです。
そして、4番のTは設定によって変わります。
設定がUnicodeになっている場合Tの部分がWに変わり、そうでない場合Tの部分が無くなります。
例えばLPTSTRは
Unicode設定下 ⇒ LPWSTR
Ansi設定下 ⇒ LPSTR
なので、変更される恐れがなくてもconst_cast<LPSTR>を使用すると設定によって次のコードは
LPCTSTR Lender3 = _T("....."); DrawTextEx(..., const_cast<LPSTR>(Lender3), ...);
Unicode設定の場合
LPCWSTR Lender3 = TEXT("....."); DrawTextEx(..., const_cast<LPSTR>(Lender3), ...); // ERROR! :DrawTextExの2番目の因数はLPWSTRに翻訳される。LPWSTRが必要な部分にLPSTRを入れるのはエラー。
なので単にconst_cast<LPSTR>(Lender3)を使用するとUnicode設定下には使えないコードになってしまいます。そしてAnsiコードよりUnicodeを使用するのをお勧めします。
追加
C言語の基礎に戻って考えてみますと""で囲まれた文字列ってすべてConstですね。
const char *p1 = "..."; // OK char *p2 = "..." // Error(昔の本やコンパイラーの場合許可される場合もあるがこれはエラーです) p1[0] = 'd'; // Error. 文字列はconst.
ここまでは分かっていると思います。
マクロの中のCは文字コードとは関係ありませんがそれなりに重要な意味があります。
マクロの中のCの観点からみるとWinAPIやMFC関数の中で文字列を因数にするものは大体二つの種類があります。
- LPCTSTR, LPCWSTR, LPCSTRなど、Cがついたものを因数に取る関数(例:CreateWindowEx)
- そうでないもの(LPTSTR, LPWSTR, LPSTRなど)(例:DrawTextEx)
がそれです。
1の場合は因数の中身が変更されない
2の場合は因数の中身が変更される可能性がある。
っていうことです。
詳しく説明すると関数の因数でCがついたものたち(1類)は
p1[0] = 'd';
みたいな行動を関数の中で絶対しないっていういわゆる保障的なものです。
しかし、2類関数たちはそんな保証をしません。
なので因数の中身が変更される可能性がいつでもあります。
最初に戻ってDrawTextExを見ますと
int DrawTextEx( _In_ HDC hdc, _Inout_ LPTSTR lpchText, _In_ int cchText, _Inout_ LPRECT lprc, _In_ UINT dwDTFormat, _In_ LPDRAWTEXTPARAMS lpDTParams );
2番目の因数がLPTSTRですね。
なのでこの関数の中でlpchTextが指している内容が変更される(もしくは可能性がある)っていうことで、
LPCTSTR p1 = _T("..."); LPTSTR p2 = new TCHAR[1024]; TCHAR arr[1024] = _T("..."); DrawTextEx(..., p1, ...); // Error: p1[0] = 'd';と全く同じコードになります。 DrawTextEx(..., p2, ...); // OK: newで作られたメモリーは書き込むことができます。 DrawTextEx(..., arr, ...); // OK: 配列は書き込むことができます。
なんか長くなりましたが要すると
1類関数には p1, p2, arrどちらでもいい。
2類関数には p1はできない。p2, arrはオッケー。
LPTSTR変数 -> LPCTSTR因数 : OK
LPCTSTR変数 -> LPTSTR因数 : Error
って言うことです。
投稿2018/02/27 02:00
編集2018/02/27 10:29総合スコア179
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/27 07:57

0
'int DrawTextExA(HDC,LPSTR,int,LPRECT,UINT,LPDRAWTEXTPARAMS)': 引数 2 を 'LPCTSTR' から 'LPSTR' へ変換できません。
このエラーは非constポインタの引数にconstポインタを渡そうとしたことを示しています。解決策としてはepistemeさんの回答を参考にしてください。
そして文字コードは基本的にUNICODEで統一していったほうがいいんでしょうか。
Windowsのネイティブ文字コードはUnicode(UTF-16)なのでWindows APIとの親和性においてはUnicodeを使うべきです(プロジェクトの設定も既定でUnicode文字セットになっているはずです)。プロジェクトの設定を「Unicode文字セットを使用する」として、文字コードはwchar_t
(あるいはWCHAR
)を使うのが一番トラブルが少ないです。
ちなみに、TEXT
マクロやTCHAR
,LPTSTR
といった、コンパイルオプションによってcharとwchar_tを切り替える仕組みはWindows 9x系との互換性のために存在しています。今さら(よほど特殊な事情がない限り)9x向けにコンパイルすることはないでしょうから、今となっては利用価値はないでしょう。
投稿2018/02/27 00:56
総合スコア5944
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。