山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他直線を描画
概要
ウィンドウに直線を描画するサンプルです。
テスト環境
コンパイラ
Visual C++ 2008 Standard 32/64bitVisual C++ 2013 Express 32/64bit
実行環境
Windows 8.1 Enterprise 64bitWindows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit
プログラムソースの概要
_tWinMain関数
Windowsから最初に_tWinMain関数が呼び出されます。 ウィンドウを作成する場合は、RegisterClass APIによりウィンドウクラスを定義してからCreateWindow APIを呼び出しウィンドウを作成します。 Windowsは入力等のイベントが発生するとアプリケーションにメッセージを送付します。 メッセージはキューに保管されます。アプリケーションはメッセージを取り出し、該当ウィンドウにメッセージを配信します。 メッセージの取り出しから配信までループで処理を行いウィンドウから終了メッセージが届くと、ループを抜けるように記述します。 これらの一連の処理は、通常にCreateWindow APIの後に記述しこれをメッセージループと呼んでいます。 詳細は以下を参照してください。メッセージループについて
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)ウィンドウプロシージャー
RegisterClass APIにより登録することによりWindowsから呼び出されます。第2引数にメッセージの種類が格納されていますので、switchステートメントによりメッセージごとの処理を振り分けます。
自分で処理しないメッセージはDefWindowProc APIに渡せばWindowsが標準的な処理を行ってくれます。
case WM_CREATE:
ウィンドウの初期化時に呼び出されます。今回のプログラムでは、DefWindowProc APIにそのままメッセージを渡して処理しています。
case WM_SIZE:
ウィンドウのサイズが変更されたときに呼び出されます。今回のプログラムでは、DefWindowProc APIにそのままメッセージを渡して処理しています。
case WM_DESTROY:
ウィンドウが閉じるときに呼び出されます。PostQuitMessage APIにより終了コードを指定して、ウィンドウプロシージャーを終了させます。
case WM_PAINT:
ウィンドウを再描画する必要があるときに呼び出されます。他のウィンドウに隠れ再びフォアグラウンドになった場合などウィンドウの再描画はWindowsが面倒を見ないのでプログラマの仕事となっています。
BeginPaint APIを呼び出して、描画に必要なデバイスコンテキストのハンドルを取得します。
BeginPaint APIの第2引数のポインタにはPAINTSTRUCT構造体のポインタを渡します。
BeginPaint API終了後、PAINTSTRUCT構造体には再描画が必要な領域の座標等の値が格納されています。
線を使用して描画するには、ペンを作成しなければなりません。
ペンの作成方法の詳細は以下を参照してください。
GDIのペンの作成方法
ペンを作成したらそのペンで描画させるためにSelectObject APIによりペンを選択します。戻り値は、前回のペンのハンドルですので保存しておき、デバイスコンテキストの解放前にペンの設定をもとに戻すときに使用します。
MoveToEx APIで座標50,50にカレントポジションを移動させます。
LineToEx APIでカレントポジションから座標100,100に直線を描画します。カレントポジションは座標100,100となります。
更にLineToEx APIでカレントポジションから座標50,100に直線を描画します。
SelectObject APIでペンを元に戻します。
再描画が終了したことをWindowsに知らせるためにEndPaint APIを使用してます。このAPIを呼び出さないと何度もWM_PAINTメッセージが発生し暴走します。
プログラムソース
line.cpp
// 直線の描画(GDI)
// Visual C++ 2013 32/64bit
#include <windows.h>
#include <tchar.h>
#include <math.h>
// ウィンドウプロシージャー
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
TCHAR szClassName[] = TEXT("line");
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInst,TCHAR* lpszCmdLine, int nCmdShow){
HWND hWnd;
MSG lpMsg;
WNDCLASS myProg;
if (!hPreInst) {
myProg.style =CS_HREDRAW | CS_VREDRAW;
myProg.lpfnWndProc =WndProc;
myProg.cbClsExtra =0;
myProg.cbWndExtra =0;
myProg.hInstance =hInstance;
myProg.hIcon =NULL;
myProg.hCursor =LoadCursor(NULL, IDC_ARROW);
myProg.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);
myProg.lpszMenuName =NULL;
myProg.lpszClassName =szClassName;
if (!RegisterClass(&myProg))
return FALSE;
}
hWnd = CreateWindow(szClassName,
szClassName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
200,
150,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&lpMsg, NULL, 0, 0)) {
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
return int(lpMsg.wParam);
}
// ウィンドウプロシージャー
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
HDC hdc;
PAINTSTRUCT ps;
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:{
hdc = BeginPaint(hWnd, &ps);
HPEN hPen, hOldPen;
hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
hOldPen = (HPEN)SelectObject(hdc, hPen);
MoveToEx(hdc, 50, 50, NULL);
LineTo(hdc, 100, 100);
LineTo(hdc, 50, 100);
SelectObject(hdc, hOldPen);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
break;
}
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
return (0L);
}
ソースファイルと実行ファイルのダウンロード
Copyright (C) 2012 山本ワールド All Rights Reserved.