ホームに戻る
 マルチスレッドの使用
 
#include <windows.h>
#include <stdio.h>

#define ID_B1 1000
#define ID_B2 1100

// スレッド用構造体
typedef struct{
    HWND hwnd;
    BOOL thread_end;
} DATA, *PDATA;

// 2つのスレッド Thread1 Thread2
DWORD WINAPI Thread1(LPVOID);
DWORD WINAPI Thread2(LPVOID);

// ウィンドウプロシージャの宣言(ウィンドウの動作を規定)
LRESULT CALLBACK WndProc(
  HWND hwnd,    //ウィンドウハンドル(void型ポインタ)
  UINT message,    //メッセージ識別番号(unsigned int)
  WPARAM wParam,    //(32ビットlong)
  LPARAM lParam);    //(32ビットlong)

//メイン関数
int APIENTRY WinMain(
  HINSTANCE hInstance,  //インスタンスのハンドル
  HINSTANCE hPreInstance, //以前のインスタンスハンドル
  LPSTR cmdLine,  //コマンド行の文字列
  int cmdShow)    //ウィンドウの表示状態
{
  //ウィンドウクラスの宣言
  WNDCLASS wd;

  //ウィンドウクラス名
  char *wdName = "window00";

  //ウィンドウ登録のためのループ
  if (!hPreInstance) {
    //ウィンドウスタイル
    wd.style = CS_HREDRAW | CS_VREDRAW;  //幅、高さの変化に対し再描画する
    //ウィンドウプロシージャ
    wd.lpfnWndProc = (WNDPROC)WndProc;
    //クラスの予備のメモリ領域
    wd.cbClsExtra = 0;
    //ウィンドウの予備のメモリ領域
    wd.cbWndExtra = 0;
    //プログラムのインスタンスハンドル
    wd.hInstance = hInstance;
    //アイコンのハンドル
    wd.hIcon = NULL;
    //カーソルのハンドル
    wd.hCursor = LoadCursor(NULL, IDC_ARROW);
    //バックグラウンドのブラシのハンドル
    wd.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    //メニュー名
    wd.lpszMenuName = NULL;
    //クラス名
    wd.lpszClassName = wdName;

    //ウィンドウの登録(成功 非0、失敗 0)
    if (!RegisterClass(&wd))
      return FALSE;
  }

  //ウィンドウの生成(ハンドルを form00 とする)
  HWND form00 = CreateWindowEx(
    NULL,      //拡張スタイル(なし)
    wdName,      //ウィンドウクラス名
    "window",    //ウィンドウの名前
    WS_OVERLAPPEDWINDOW,  //ウィンドウスタイル(オーバーラップ型)
    CW_USEDEFAULT,    //ウィンドウのX座標(ディフォルト)
    CW_USEDEFAULT,    //ウィンドウのY座標(ディフォルト)
    200,      //ウィンドウの幅(80に設定)
    100,      //ウィンドウの高さ(50に設定)
    NULL,      //親ウィンドウ(この場合自身が親)
    NULL,      //メニュー(なし)
    hInstance,    //プログラムのハンドル
    NULL);      //予備パラメータ

  //ウィンドウの表示
  ShowWindow(form00, cmdShow);

  //ウィンドウの更新
  UpdateWindow(form00);

  //イベントのループ
  MSG msg;
  while (GetMessage(&msg, NULL, NULL, NULL))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

// ウィンドウプロシージャ(ウィンドウの動作を規定)
LRESULT CALLBACK WndProc(
  HWND hwnd,
  UINT message,
  WPARAM wParam,
  LPARAM lParam)
  {
  //ボタンを2個宣言
  HWND hButton1, hButton2;

  //インスタンスハンドルを得る
  HINSTANCE hInst;
  hInst = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);

  //スレッド用
  static DATA data1, data2;
  static HANDLE hThread1, hThread2;
  DWORD thId1, thId2;

  switch (message) {
  //ウィンドウを表示するとき処理
    case WM_CREATE:
    //ボタン1の表示
      hButton1 = CreateWindow(
        "BUTTON",
        "Button1",
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        10,
        10,
        80,
        20,
        hwnd,
        (HMENU)ID_B1,
        hInst
        ,NULL);
    //ボタン2の表示
      hButton2 = CreateWindow(
        "BUTTON",
        "Button2",
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        100,
        10,
        80,
        20,
        hwnd,
        (HMENU)ID_B2,
        hInst
        ,NULL);
      break;
  //ボタンを押したときの処理
    case WM_COMMAND:
      switch(LOWORD(wParam)){
      //ボタン1を押したとき
        case ID_B1:
          data1.hwnd = hwnd;
          data1.thread_end = FALSE;
          hThread1 = CreateThread(NULL,
          0,
          (LPTHREAD_START_ROUTINE)Thread1,
          (LPVOID)&data1,
          0,
          &thId1);
          break;
      //ボタン2を押したとき
        case ID_B2:
          data2.hwnd = hwnd;
          data2.thread_end = FALSE;
          hThread2 = CreateThread(NULL,
          0,
          (LPTHREAD_START_ROUTINE)Thread2,
          (LPVOID)&data2,
          0,
          &thId2);
                    break;
        default:
          return(DefWindowProc(hwnd, message, wParam, lParam));
      }
      break;
  //ウィンドウを破壊する時の処理
    case WM_DESTROY:
      //スレッドを閉じる
      CloseHandle(hThread1);
      CloseHandle(hThread2);
      //1秒待つ
      Sleep(1000);
      //メイン関数のループを終了
      PostQuitMessage(0);
      break;

  //デフォルトの処理に対してデフォルトの処理を返す
    default:
      return DefWindowProc(hwnd, message, wParam, lParam);
  }
  return NULL;
}

// Thread1
DWORD WINAPI Thread1(LPVOID data)
{
  PDATA pData;
  pData = (PDATA)data;
  SYSTEMTIME st;
  HDC hdc;

  char s[256];
  char *nokoribyou = "残り%2d秒 ";

  static BOOL th_flag = FALSE;
  int count = 10;

  hdc = GetDC(pData->hwnd);

  if(!th_flag){
    th_flag = TRUE;
    while (!pData->thread_end){
      Sleep(1000);
      sprintf(s, nokoribyou, count);
      count--;
      //再描画
      RECT r = {110,40,50,20};
      InvalidateRect(pData->hwnd,   //ウィンドウハンドル
        &r,   //再描画領域の指定(Rect)NULL 全体
        TRUE);   //背景消去フラグ
      PAINTSTRUCT ps;
      BeginPaint(pData->hwnd, &ps);
      //文字列の描画
      TextOut(hdc, 20, 40, s, strlen(s));
      //描画の終了
      EndPaint(pData->hwnd, &ps);
      if(count < 0){
        pData->thread_end = TRUE;
        MessageBox(pData->hwnd, 
          (LPCSTR)"Thread1が終了しました", 
          (LPCSTR)"Thread1", 
          MB_OK);
        th_flag = FALSE;
      }
    }
      }
  return (DWORD)0;
}

// Thread2
DWORD WINAPI Thread2(LPVOID data)
{
  PDATA pData;
  pData = (PDATA)data;
  SYSTEMTIME st;
  HDC hdc;

  char s[256];
  char *nokoribyou = "残り%2d秒 ";

  static BOOL th_flag = FALSE;
  int count = 10;

  hdc = GetDC(pData->hwnd);

  if(!th_flag){
    th_flag = TRUE;
    while (!pData->thread_end) {
      Sleep(1000);
      sprintf(s, nokoribyou, count);
      count--;
      //再描画
      RECT r = {110,40,50,20};
      InvalidateRect(pData->hwnd,   //ウィンドウハンドル
        &r,   //再描画領域の指定(Rect)NULL 全体
        TRUE);   //背景消去フラグ
      PAINTSTRUCT ps;
      BeginPaint(pData->hwnd, &ps);
      //文字列の描画
      TextOut(hdc, 110, 40, s, strlen(s));
      //描画の終了
      EndPaint(pData->hwnd, &ps);
      if(count < 0){
        pData->thread_end = TRUE;
        MessageBox(pData->hwnd, 
          (LPCSTR)"Thread2が終了しました", 
          (LPCSTR)"Thread2", 
          MB_OK);
        th_flag = FALSE;
      }
    }
    }
    return (DWORD)0;
}

inserted by FC2 system