スレッドを生成するには CreateThread 関数を使用します。
それぞれの実行スレッドはプロセス内部のスレッド関数の呼び出しで始動します。
スレッドの実行はスレッド関数から戻るまで続きます。
スレッド関数のプロトタイプは以下のようになります。
DWORD WINAPI ThreadFunc(LPVOID lpParameter);
引数はCreateThreadで指定されたパラメータです。
C言語のランタイムライブラリを使う場合は _beginthreadex 関数を使用してください。
ウインドウ上にマウスカーソルのスクリーン座標を表示します。
サンプルではカーソル位置の取得と描画は0.1秒ごとに行っています。
#include <windows.h>
#include <tchar.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
DWORD WINAPI MyThread(LPVOID);
HINSTANCE hInst;
LPCTSTR lpszAppName = TEXT("MyApp");
LPCTSTR lpszAppTitle = TEXT("MyApp");
POINT pt;
volatile BOOL bTerminate = FALSE;
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg = {0};
HWND hWnd;
WNDCLASSEX wc = {0};
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
//メインウィンドウクラス登録
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(NULL_BRUSH));
wc.lpszMenuName = NULL;
wc.lpszClassName = lpszAppName;
wc.hIconSm = NULL;
if(RegisterClassEx(&wc) == 0) {
return 0;
}
hInst = hInstance;
//メインウインドウ作成
hWnd = CreateWindow(lpszAppName, lpszAppTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL
);
if(hWnd == NULL) {
return 0;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//メイン メッセージ ループ
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HANDLE m_hThread = NULL;
switch(uMsg) {
case WM_CREATE:
{
DWORD dwid;
//スレッドを作成します
ZeroMemory(&pt, sizeof(POINT));
m_hThread = CreateThread(NULL, 0, MyThread, (LPVOID)hWnd, 0, &dwid);
if(m_hThread == NULL) {
return -1;
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
TCHAR szText[20];
RECT rc;
GetClientRect(hWnd, &rc);
HDC hMemDC = CreateCompatibleDC(hDC);
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, rc.right, rc.bottom);
hBitmap = static_cast<HBITMAP>(SelectObject(hMemDC, hBitmap));
FillRect(hMemDC, &rc, reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1));
wsprintf(szText, TEXT("%d : %d"), pt.x, pt.y);
DrawText(hMemDC, szText, lstrlen(szText), &rc, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
BitBlt(hDC, 0, 0, rc.right, rc.bottom, hMemDC, 0, 0, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
DeleteObject(hBitmap);
DeleteDC(hDC);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
{
//スレッドを終了します
bTerminate = TRUE;
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//スレッド関数
DWORD WINAPI MyThread(LPVOID lpParameter)
{
HWND hwnd = static_cast<HWND>(lpParameter);
while(!bTerminate) {
//マウスカーソルのスクリーン座標を取得します
GetCursorPos(&pt);
//メインウインドウの再描画
InvalidateRect(hwnd , NULL, FALSE);
Sleep(100);
}
return 0;
}