Windows10 & Win32 API

Win32 API のプログラムを Windows10 & VC_2017 の環境で動かします。

前田稔(Maeda Minoru)の超初心者のプログラム入門

Windows10 で動かす

  1. Windows10 がリリースされプログラムの開発環境も大きく変わってきました。
    Win32 API も賞味期限が切れ、残飯寸前の状態でした。
    しかしながら、新しい仕様では対応出来ない(方法が不明?)の場合も多々あり、再び活躍の場が与えられました。
    特にAI(人工知能 artificial insemination)に関係する画像認識の基礎に役立ちそうです。
    そこで 2018-02/20 Windows10 & VC_2017 の環境で、Win32 API のプログラムを動かしてみました。
    古いプロジェクトの文字コードは Shift_JIS が使われていました。
    そのままでも動きますが、なるべく utf-8 に変換した方が良いでしょう。
    VC_2017 で動かすための基本的な変換方法です。
    1. Main.dsp を編集して /ZI を削除して保存します。(文字コードは Shift_JIS のままです)
      /ZI は「コードビューデバッガーのためのシンポル情報の出力」で現在は使われていません。
    2. ソースプログラム(*.cpp, *.h)の文字コードを utf-8 で保存します。
    3. Main.dsp をダブルクリックして VS-2017 を起動します。
      バージョン変換のメッセージが表示されてプロジェクトが開きます。
      (Main.vcproj が格納されているときは、Main.dsp を使わずに Main.vcproj から起動する方法もあります)
    4. ツールバーから「ローカル Windows デバッガー」をクリックしてコンパイル&実行して下さい。
    5. プロジェクトを閉じて Main.sln を保存して下さい。
      次回からは VisualStudio-2017 を Main.sln から起動して下さい。
    開発環境が異なっても、この方法で動く場合があるので試してみて下さい。
    画像描画のプロジェクトを圧縮形式で提供します。
    「プロジェクトのフォルダーから BMP ファイルを入力」を Down Load(02empty.zip)
    「ローカルディスクから BMP ファイルを入力」を Down Load(01wm_paint.zip)
  2. Message Box を表示する を Windows10 で動かします。
    VC++ で Message Box を表示する最も簡単なプログラムです。
    1. このプロジェクトに格納されているファイルは Main.cpp と Main.dsp だけです。
    2. Main.dsp を編集して /ZI を削除して保存します。(文字コードは Shift_JIS)
    3. Main.cpp を utf-8 で保存します。
    4. Main.dsp をダブルクリックして VS-2017 を起動します。
    5. コンパイルをしてプログラムを実行して下さい。
    6. プロジェクトを閉じて Main.sln を保存して下さい。
      次回からは VisualStudio-2017 を起動して Main.sln を入力して下さい。
  3. Ellipse() で円と楕円を描画する を Windows10 で動かします。
    Window に図形を描画するプログラムです。
    1. Draw.dsp を編集して /ZI を削除して保存します。(文字コードは Shift_JIS)
    2. ソースプログラム(*.cpp, *.h)の文字コードを utf-8 で保存します。
    3. Draw.dsp をダブルクリックして VS-2017 を起動します。
    4. コンパイルをしてプログラムを実行して下さい。
    5. プロジェクトを閉じて Draw.sln を保存して下さい。
      次回からは VisualStudio-2017 を起動して Draw.sln を入力して下さい。
  4. ayu.bmp を直接プロジェクトのフォルダーに格納して描画します。
    プロジェクを圧縮形式で提供しています。
    1. このプロジェクトには Main.cpp, Main.dsp, Main.vcproj のファイルが格納されています。
    2. Main.cpp を utf-8 で保存します。
    3. Main.vcproj をダブルクリックして VS-2017 を起動します。
    4. コンパイルをしてプログラムを実行して下さい。
    5. プロジェクトを閉じて Main.sln を保存して下さい。
      次回からは VisualStudio-2017 を起動して *.sln を入力して下さい。
    プログラムの説明は BMP ファイルの表示 を参照して下さい。
  5. ayu.bmp ファイルをローカルディスクから入力して描画します。
    プロジェクを圧縮形式で提供しています。
    1. BmpFile.dsp を編集して /ZI を削除して保存します。(文字コードは Shift_JIS)
    2. ソースプログラム(*.cpp, *.h)の文字コードを utf-8 で保存します。
    3. BmpFile.dsp をダブルクリックして VS-2017 を起動します。
      画像は "c:\\data\\test\\ayu.bmp" から入力します。
    4. プロジェクトを閉じて BmpFile.sln を保存して下さい。
      次回からは VisualStudio-2017 を起動して BmpFile.sln を入力して下さい。
    プログラムの説明は BMP ファイルを表示する関数を定義 を参照して下さい。
  6. 二枚の画像をブレンドしながら切り替える を Windows10 で動かします。
    CPU が「16ビット→32ビット→64ビット」の発展に伴いそのままでは動かなくなってきました。
    1. "c:\data\test\" に次の画像を格納します。
      ffx2s.bmp, GeoS.bmp は 480*240*24 BPP の画像です。
    2. Main.dsp を編集して /ZI のコンパイルオプションを削除して下さい。
    3. *.cpp, *.h の文字コードを utf-8 に変換します。
    4. Image.cpp(.h) から GIF と JPEG 関係のソースコードを削除します。
      // SPI ENTRY
      //typedef int (PASCAL *GetPicture)(LPSTR,long,UINT,HANDLE*,HANDLE*,FARPROC,long);
      //    HRESULT     LoadDLL(LPSTR ImageName, LPSTR SPI);
      //    HRESULT     LoadGif(LPSTR ImageName)    {  return LoadDLL(ImageName,"ifgif.spi");  }
      //    HRESULT     LoadJpeg(LPSTR ImageName)   {  return LoadDLL(ImageName,"ifjpeg.spi"); }
      
      //GetPicture      F_GetPicture;
      //★ 画像ファイルをロード
      HRESULT  IMAGE::LoadFile(LPSTR ImageName)
      {
          strcpy(szFile,ImageName);
          return LoadBmp(ImageName);
      }
      /*
      HRESULT  IMAGE::LoadDLL(LPSTR ImageName, LPSTR SPI)
      {    関数を削除   }
      */
      
    5. Main.cpp の画像を BMP に修正します。
      char            File1[]= "c:\\data\\test\\ffx2s.bmp";
      char            File2[]= "c:\\data\\test\\GeoS.bmp";
      void  AppInit(HWND hwnd)
      {   // 画像のロード
          Img1= new IMAGE(hwnd);
          Img1->LoadFile(File1);
          Img2= new IMAGE(hwnd);
          Img2->LoadFile(File2);
          // Surface を作成
          Surface= new SURFACE(hwnd,Img1->Width,Img1->Height);
          Surface->Mask= RGB(0,0,0);
          Img2->Show(Surface->hWBmpDC,0,0);
      }
      
    6. Main.dsp をダブルクリックして VS-2017 を起動します。
    7. コンパイルをしてプログラムを実行して下さい。
      マウスのクリックで2枚の画像がブレンドしながら切り替わります。
    8. プロジェクトを閉じて Main.sln を保存して下さい。
      次回からは VisualStudio-2017 を起動して *.sln を入力して下さい。
    C# を使えば BMP に限らず、GIF, JPG, TIF, PNG なども描画出来ます。
    C# のページは リソースで取り込んだイメージを描画する を参照して下さい。
  7. Bmp File の入力と、Bmp File の作成(保存)です。
    1. 共通に参照できる領域に画像関係の領域を定義します。
      HBITMAP  hBmp;      // 画像のハンドル
      HDC      hBmpDC;    // デバイスコンテキストのハンドル
      BITMAP   bmp;       // BITMAP 構造体
      
    2. WM_CREATE で Bmp File を入力して描画の準備を整えます。
      "c:\\data\\test\\ffx2s.bmp" が入力する Bmp File です。
          {   case WM_CREATE:
                  hBmp = (HBITMAP)LoadImage(NULL, "c:\\data\\test\\ffx2s.bmp", IMAGE_BITMAP,
                      0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
                  if (hBmp == NULL)
                  {   MessageBox(NULL, "c:\\data\\test\\ffx2s.bmp", "Load BMP Error", MB_OK);
                      return  FALSE;
                  }
                  hdc = GetDC(hWnd);
                  hBmpDC = CreateCompatibleDC(hdc);
                  SelectObject(hBmpDC, hBmp);
                  GetObject(hBmp, sizeof(BITMAP), &bmp);
                  break;
      
    3. WM_PAINT で画像を描画します。
              case WM_PAINT:
                  hdc= BeginPaint (hWnd, &ps);
                  BitBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, hBmpDC, 0, 0, SRCCOPY);
                  EndPaint(hWnd, &ps);
                  break;
      
    4. WM_DESTROY で Bmp File("c:\\tmp\\test.bmp") に画像を書き出して終了します。
      事前に c:\tmp\ のフォルダーを作成しておいて下さい。
              case WM_DESTROY:
                  SaveBmp("c:\\tmp\\test.bmp", hBmpDC, hBmp);
                  if (hBmpDC) DeleteDC(hBmpDC);
                  if (hBmp)   DeleteObject(hBmp);
                  PostQuitMessage(0);
                  return 0L;
      
    5. 画像を24ビット BMP 形式で保存する SaveBmp() 関数です。
      BYTE *imgbuf に画像の RGB データを取得して書き出します。
      // BMP FILE を保存する
      void  SaveBmp(LPSTR fname, HDC hdc, HBITMAP hbm)
      {
          HANDLE  hFile;
          DWORD   dwBytes, len;
          BITMAP  bm;
          int     ret;
          static  BITMAPFILEHEADER    g_Bf = { 0x4d42, 0, 0, 0, 0x36 };
          static  BITMAPINFOHEADER    g_Bi = { 0x28, 0, 0, 1, 24, 0, 0, 0, 0, 0, 0 };
          BYTE    *imgbuf;
      
          if (GetObject(hbm, sizeof(BITMAP), &bm) == 0)
          {   MessageBox(NULL, "GetObject() に失敗しました", "PutBmp", MB_OK);
              return;
          }
          hFile = CreateFile(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
          if (hFile == NULL)    return;
      
          len = (bm.bmWidthBytes + 3) & 0xfffffffc;
          len *= bm.bmHeight;
          g_Bi.biWidth = bm.bmWidth;
          g_Bi.biHeight = bm.bmHeight;
          g_Bf.bfSize = g_Bf.bfOffBits + len;
      
          imgbuf= new BYTE[len];
          ret= GetDIBits(hdc,hbm,0,bm.bmHeight,imgbuf,(LPBITMAPINFO)&g_Bi,DIB_RGB_COLORS);
          if (ret==0)
          {   MessageBox(NULL,"ピクセルデータの取得に失敗しました", "PutBmp", MB_OK);
              CloseHandle(hFile);  return;
          }
          WriteFile(hFile, &g_Bf, sizeof(BITMAPFILEHEADER), &dwBytes, NULL);
          WriteFile(hFile, &g_Bi, sizeof(BITMAPINFOHEADER), &dwBytes, NULL);
          WriteFile(hFile, imgbuf, len, &dwBytes, NULL);
          CloseHandle(hFile);
          if (imgbuf) delete [] imgbuf;
      }
      
  8. αチャンネル付の画像を表示する を Windows10 で動かします。
    元のプロジェクトは my.lib を組み込んでいるのですが、古くなって使えません。
    そこで必要な Class を個々に組み込みます。
    1. "c:\\data\\test\\alph32.bmp"(αチャンネルが設定された BMP 画像)を格納します。
      αチャンネル付きの画像を作成するには専用のソフトが必要で、私は自作のアプリを使いました。
    2. 次のファイルをプロジェクトのフォルダーにコピーして utf-8 に変換します。
      Main.h(cpp), Image.h(cpp), Surface32.h(cpp), BackBuf.h(cpp)
      ソースコードは Object Class Library から提供しています。
    3. Main.cpp を Class に合わせて修正します。(my.lib 関係を削除, Image, Surface32, BackBuf を組み込む)
    4. Main.dsp をダブルクリックして VS-2017 を起動します。
      プロジェクトのフォルダーに格納した Class ファイルをプロジェクトに組み込みます。
    5. マウスのクリックでαチャンネルとブレンドされ、続けてクリックすると透明度が変わります。
  9. 私のダウンロードサイトから提供している「αチャンネル付の画像を作成する」を Windows10 で動かします。
    1. 次のファイルをプロジェクトのフォルダーにコピーして utf-8 に変換します。
      Main.h(cpp), Image.h(cpp), Alpha32.h(cpp)
    2. Image.cpp(.h) から GIF と JPEG 関係のソースコードを削除します。
      (開発環境が変わって GIF や JPEG が使えなくなっている可能性があります)
    3. "afxres.h" でエラーが出るので、次のように修正して下さい。
      //#include "afxres.h"
      #include <windows.h>
      #define IDC_STATIC -1
      
    4. Main.vcproj から VS-2017 を起動します。
    5. kishi.bmp と kishiMSK.bmp をローカルフォルダーから入力するので事前に用意して下さい。
      プログラムを起動して kishi.bmp を入力します。
    6. [ファイル][マスクを入力]から kishiMSK.bmp を入力します。
      [表示][ブレンド画像]でマスクされた画像を表示を選びます。
      (マウスをクリックする毎にブレンドの度合いが変わります)
    7. [ファイル][BMP32で保存]でαチャンネル付の画像(kishi32.bmp)が作成されます。
  10. ストアアプリでは面倒な TEXT FILE の入出力 TEXT ファイルを入力して画面に表示する を動かします。
    入力するファイルは "C:\\DATA\\Test\\shift_jis.txt" でシフトJISでタイプされたファイルです。
    1. *.cpp と *.h を utf-8 に変換して保存します。
    2. Main.cpp を修正して、入力するファイル名を shift_jis.txt にして下さい。
      hFile = CreateFile("C:\\DATA\\Test\\shift_jis.txt",GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
      
    3. Main.vcproj をダブルクリックして VS-2017 を起動します。
      バージョン変換のメッセージが表示されてプロジェクトが開きます。
    4. コンパイルしてから実行すると shift_jis.txt が印字されます。
    5. プロジェクトを閉じて Main.sln を保存して下さい。
  11. EditControl からタイプしたデータをファイルに書き出す を動かします。
    TEXT FILE の入力は自動生成のプロジェクトですが、出力は空のプロジェクトから作成しました。
    その分プロジェクトの構成がシンプルで解り易くなっています。
    1. Main.dsp を編集して /ZI を削除して保存します。(文字コードは Shift_JIS)
    2. *.cpp と *.h を utf-8 に変換して保存します。
    3. Main.dsp をダブルクリックして VS-2017 を起動します。
      バージョン変換のメッセージが表示されてプロジェクトが開きます。
    4. コンパイルしてから実行して下さい。
      EditControl にテキストデータをタイプ入力して OK をクリックします。
      カレントフォルダに test.txt ファイルが作成されます。(文字コードは Shift_JIS です)
    5. プロジェクトを閉じて Main.sln を保存して下さい。
  12. 幾つかのプロジェクトを Windows10 & VC_2017 の環境で動かす方法を説明しましたが、これ以外のプロジェクトも動くはずです。
    実行環境によって違いがあり、動かないプロジェクトが出てくるかも知れません。
    空のプロジェクトから作成した場合はファイルの数が少なくシンプルな構成になっています。
    それに対して、自動生成で作成したプロジェクトはファイルの数が少し多くなっています。
    Windows10 のプロジェクトは、従来とかなり様子が異なり制限も厳しくなって思うようにプログラム出来ない場合があります。
    そのような場合に、従来のプロジェクトが役に立つと思います。
    Windows10(ストアアプリ)のプログラムは「超初心者のプログラム入門(C/C++)」から C++ Windows10(Store App) などを参照して下さい。

超初心者のプログラム入門(Win32API C++)