それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

PHP'erがWindowsプログラミングを体当たりしてみる

Windowsプログラミングってあれじゃないですか、VisualStudioで要素を貼り付けて終り。書籍も細かいWindowのスタイルとか解説しているだけで、仕組みがよく解らない。気持ち悪い。mainが無い。とかよく解らないことが多いので、体当たりで学習することにしました。

VisutalStdioは使わない。

VCは使いません。

あえて使わないところがミソです。VC使うと、ドラッグ&ドロップでプログラミングじゃない。仕組みが見えない。しかもブログにしても絵本になる。VCの使い方を覚えるだけで、Windowsプログラミングの勉強にならない。

GNU/GCCを使います

やっぱオープンな仕様っていいよね。なのでGNU!!!

参考にしたのは次のサイト

http://wisdom.sakura.ne.jp/system/winapi/win32/index.html

現在調べて分かってること。

  • WindowsのGUIは windows.hを使う
  • main関数はない
    • WinMain関数を使う
  • メッセージループがある。
    • メッセージループはMSG構造体の値を監視する。
    • ループ内部でMSGを取得して、対応する関数を呼ぶ。
    • WM_QUITが来るとメインループは終了する。
    • WM_DESTROYをトリガにして、WM_QUITを送る。
  • MSGキューが存在する。
    • MSGキューの値は、順番に取り出される
  • Windowの管理はWindowsが行なう
    • WindowにはZ-indexがある。
  • コンパイル環境にもいろいろある。
    • 別言語だとC++との型変換がある。
    • Win32APIが返すC++の型を言語の型にキャストする
  • 開発言語、およびコンパイラ

現在の基礎知識はココまで、メインループとかイベントドリブンも一応知ってるけど、全て一端忘れて白紙から勉強し直し。

実行環境を整える。

C++コンパイラはいろいろある。VisutalStdioだと何度も面倒で挫折しているので、あえてVCには触らない。そして、GNUにこだわる。

mingwとは

Wikipediaによると

MinGWGNU ツールチェーンのWindows移植版である。MinGWはWindows APIのためのヘッダファイルを含んでおり、フリーのコンパイラであるGCCを、Windowsアプリケーションの開発のために利用できる。

これはGNU!いいね。他にも昔からのLSIC試食版とか BorlandC++とか VC付属のC++コンパイラとかいろいろある。

インストール

mingwを入れる

  1. ダウンロード
    1. http://www.mingw.org/
  2. パスを通す
  3. とりあえずコンパイルしてみる。

最初の一歩

sample01.cpp
#include <windows.h>
int main()
{
	MessageBox(NULL , TEXT("無限インターネット") ,
			 TEXT("無限インターネット") , MB_OK);
        return 0;
}

なぜかWinMainじゃなくてMainを使ってるけど、なんでか通るのです。そのうち調べる。

コンパイルして実行
C:\users\takuya>gcc sample01.cpp           #コンソールアプリ
C:\users\takuya>a.exe
C:\users\takuya>gcc -mwindows sample01.cpp #Winアプリ
C:\users\takuya>a.exe

おおおおお順調。なんかWindowsの世界がやっと分かって気がするよ。VisutalStdioだと隠蔽されて、生APIが分からないものね。

最初のウインドウ

sample02.cpp
#include <windows.h>
int WINAPI WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  PSTR lpCmdLine,
  int nCmdShow
)
{
  /*
   * ウィンドウを作る。
   */
  HWND hwnd = CreateWindow(
      TEXT("STATIC") , TEXT("SOS!") ,
      WS_CAPTION ,
      100 , 100 , 200 , 200 , NULL , NULL ,
      hInstance , NULL
  );

  if (hwnd == NULL) return 0;

  ShowWindow(hwnd , SW_SHOW);
  MessageBox(NULL, TEXT("入部するのよ"),TEXT("メッセージボックス"), MB_OK);
  return 0;
}
コンパイルと実行
C:\users\takuya>gcc sample02.cpp           #コンソールアプリ
C:\users\takuya>a.exe
C:\users\takuya>gcc -mwindows sample02.cpp #Winアプリ
C:\users\takuya>a.exe
ダイアログボックス

ダイアログボックスで一端実行を止めている。JSのAlertデバッグみたいモノです。
もしダイアログボックスがないと、Windowは表示されるけど、速攻で回収されてしまいますね。

メインループを使う。

ダイアログボックスで止めるのではなく、Windowsではメッセージループ(メインループ)を使う。メインループの中で、MSGをディスパッチしていく。メインループでグルグル回すのは、GUIアプリに共通のことなので、これは知識として知っていた。でも実際にそのコードを書くのは初めてだ。

sample03.cpp
#include <windows.h>

int WINAPI WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  PSTR lpCmdLine,
  int nCmdShow
)
{
  /*
   * メッセージループをする。
   */
   HWND hwnd;
   MSG msg;
   
   hwnd = CreateWindow(
        TEXT("BUTTON"),TEXT("Foooooo"),
        WS_CAPTION | WS_VISIBLE,
        100, 100, 200, 200, NULL, NULL,
        hInstance, NULL
      );
   if( hwnd == NULL) return 0;
   while(TRUE){
      GetMessage(&msg, NULL, 0, 0);
      if( msg.message == WM_LBUTTONUP)break;
      DispatchMessage(&msg);
   }
  return 0;
}
コンパイルと実行
C:\users\takuya>gcc sample03.cpp           #コンソールアプリ
C:\users\takuya>a.exe
C:\users\takuya>gcc -mwindows sample03.cpp #Winアプリ
C:\users\takuya>a.exe

細かい解説。

今度かく。でもGNUだけで手軽にWinアプリのメインのメッセージループを体験できた。次はメッセージループからイベントへのディスパッチを勉強してこうと思う。