「Windows API/文字表示の命令」の版間の差分

削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
{{Nav}}, s/命令/関数/
1 行
{{Nav}}
 
== 文字表示の命令関数 ==
=== 基本 ===
「Windows デスクトップアプリケーション」で自動作成されたコードをもとに説明しますので、そのコードを用意してください。(空のテンプレートで作ったコードでもウィンドウに文字や画像を描画することは可能。とりあえず本wikibooksでは、説明の単純化のために、先に「Windows デスクトップアプリケーション」で自動作成されたコードで説明する。)
 
Windows APIの文字表示で、いちばん簡単な命令関数は、 TextOut という命令関数です。
<sourcesyntaxhighlight lang=c>
TextOut(hdc, 10, 30, TEXT("テスト"), 3);
</syntaxhighlight>
</source>
のように使います。「hdc」は対象のウィンドウ名(「ハンドル名」などという)です。初期設定をウィザードで自動作成した場合に標準ではこの名前になってるので、本書では、特に断らない限り、この関数名を使う事とします。
 
16 行
 
 
ただし、このTextOut命令関数など、ウィンドウを描画するための命令関数を書ける位置は限られていて、
<sourcesyntaxhighlight lang=c>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
</syntaxhighlight>
</source>
という関数(120行目あたりにある。)から始まるブロック中にある条件分岐「 case WM_PAINT: 」のブロック中で書きます。
 
26 行
 
すでに、
<sourcesyntaxhighlight lang=c>
case WM_PAINT:
{
35 行
EndPaint(hWnd, &ps);
}
</syntaxhighlight>
</source>
 
とあるので、そこに TextOut 命令関数を挿入し、
 
<sourcesyntaxhighlight lang=c>
case WM_PAINT:
{
50 行
EndPaint(hWnd, &ps);
}
</syntaxhighlight>
</source>
 
のようになります。
87 行
 
そのクラス登録の一連のコード中の70行目あたりに、
<sourcesyntaxhighlight lang=c>
wcex.lpfnWndProc = WndProc;
</syntaxhighlight>
</source>
とあるはずです。これにより、コールバック関数 WndProc が、ウィンドウと関連づけられています。
 
=== 文字表示での変数などの活用 ===
 
<sourcesyntaxhighlight lang=c>
TextOut(hdc, 10, 20, TEXT("Hello"), 5);
</syntaxhighlight>
</source>
 
のように、毎回、字数を入力するのは、面倒である。
 
そこで、「lstrlen()」という、文字列の長さを返す命令関数を使う。これは、C言語のstrlen命令関数のWindows版である。
 
APIプログラミングでは、strlen命令関数ではなく、lstrlen命令関数を使わないといけないだろう。
 
 
また、毎回メッセージごとにTextOut命令関数を書き換えるのは非効率であるので、たとえば変数aisatuをあらかじめ用意して、実用的には<code>TextOut(hdc, 10, 20, aisatu, lstrlen(aisatu)); </code> のように変数(このコードではaisatuが変数)を使うのが効率的である。
 
コード例
<sourcesyntaxhighlight lang=c>
static TCHAR aisatu[60] ;
lstrcpy(aisatu, TEXT("Hello"));
TextOut(hdc, 10, 20, aisatu, lstrlen(aisatu));
</syntaxhighlight>
</source>
 
のように書くのが実用的である。
124 行
 
 
lstrcpyは、C言語でいう文字列のコピー命令関数strcpyのWindows版である。
 
このように、Windows独自の命令関数がいろいろとあるので、とりあえず初心者は、上記のコードをそのままコピーして、自分の使いたいように改造すれば効率的だろう。
 
TextOutする事じたいは難しくないのだが、それを実用的なコードにするためにWindows独自の型などを学ばなければならず、そっちが難しい。
134 行
=== MSDNのシンタックスの読みかた ===
たとえば、マイクロソフトの開発者むけサイト MSDN を見ると、TextOut関数について、
<sourcesyntaxhighlight lang=c>
BOOL TextOutA(
HDC hdc,
142 行
int c
);
</syntaxhighlight>
</source>
 
と、冒頭に、あかたも文法のような何か が書いてある。[https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-textouta MSDN TextOutA function]
164 行
TextOut関数にかぎらず、API関数を実際に使う場合、冒頭の型は宣言しない。つまり、
 
プログラミング中にTextOut関数を実際に呼び出して使用するための命令関数を記述したい場合は、単に
<sourcesyntaxhighlight lang=c>
TextOutA(
HDC hdc,
173 行
int c
);
</syntaxhighlight>
</source>
のような、冒頭のBOOL型を除去した書式で書く必要がある。
 
187 行
 
実際、MSDNのサンプルコードでは、
<sourcesyntaxhighlight lang=c>
TextOut(hdc,r.left,r.top,text, ARRAYSIZE(text));
</syntaxhighlight>
</source>
 
のように、冒頭の型を除去したあとに1行でまとめて宣言している。
206 行
 
 
さて、TextOut 命令関数では、変数の値をそのまま表示することは不可能です。
 
よって、まずC言語の組み込み関数 sprintf という、これは数値型を文字列型に変換できる組み込み関数ですが、これのWindows版で _stprintf_s というのがありますので、Win32 API では _stprintf_s を使って、変数を文字列型に変換します。
223 行
結局、身長の変数 sintyo を画面に表示するには・・・
 
<sourcesyntaxhighlight lang=c>
int sintyo = 153 ; // この 153 を画面に表示したい
static TCHAR henkan[50] ; // 文字列を格納するための変数 henkan を準備
_stprintf_s( henkan, 200, TEXT("%d"), sintyo); // ここで153を文字列に置き換え、文字列変数 henkan に格納してる
TextOut(hdc, 10, 20, henkan, lstrlen(henkan));
</syntaxhighlight>
</source>
 
のように、なります。
237 行
_stprintf_s で代入先になる第一引数になる文字列変数(例では henkan )は TCHAR 型でなければなりません。(もし char型だと コンパイルでエラーになる。)
 
_stprintf_s 命令関数で代入する数値(例では sintyo )は、整数型でなければなりません。もし実数型(たとえば double 型)で数を定義してある場合には、型変換 (int) を使ってから代入します。
 
;実数型の場合のコード例
<sourcesyntaxhighlight lang=c>
double sintyo = 153 ; // double型の場合
static TCHAR henkan[50] ;
_stprintf_s( henkan, 200, TEXT("%d"), (int) sintyo); // (int)は整数型への型変換である。
TextOut(hdc, 10, 20, henkan, lstrlen(henkan));
</syntaxhighlight>
</source>
となります。
 
254 行
 
 
まず、とりあえず100倍して、それを型変換の <code>(int)</code> 命令関数で、整数型として型変換したあとに、他の整数型の変数 bufseisuu に入れます。(バッファ用の整数でbufseisuu のつもり)
 
そのあと、上記の章と同様に sprintf すれば、小数点の上位2ケタの表示がされます。
 
<sourcesyntaxhighlight lang=c>
// 正常に動作するコード例
int hensuu = 0.38 ;
268 行
TextOut(hdc, 450, 415, henkan, lstrlen(henkan));
 
</syntaxhighlight>
</source>
 
===== 駄目なコード =====
282 行
 
 
<sourcesyntaxhighlight lang=c>
// ダメなコード例
int hensuu = 0.38 ;
290 行
TextOut(hdc, 450, 415, henkan, lstrlen(henkan));
 
</syntaxhighlight>
</source>
 
このコードは駄目なのです。
314 行
なお、int整数値を TCHAR 形に変換するには、_itot_s を使います。
 
<sourcesyntaxhighlight lang=c>
_itot_s(sintyo , henkan, 200, 10); // 第4引数の「10」は10進数という意味。
TextOut(hdc, 10, 20, henkan, lstrlen(henkan));
</syntaxhighlight>
</source>
 
のように、なります。
328 行
2つ以上の文字を連結したい場合は、単に、C言語の sprintfs のTCHAR版である <code>_stprintf_s</code> を使えばいいだけです。
 
<sourcesyntaxhighlight lang=c>
_stprintf_s(mojibuf, TEXT("%s %s"), TEXT("私の名は"), person_name);
TextOut(hdc, 10, 20, mojibuf, lstrlen(mojibuf));
</syntaxhighlight>
</source>
 
のようになります。