meideru blog

家電メーカーで働いているmeideruのブログです。主に技術系・ガジェット系の話を書いています。

今更だけど、脱Windows APIしようと思う(;´・ω・)

 

最近、Macに関する記事ばかりで飽きてしまっている読者の方々、朗報ですw

久しぶりにプログラミングのネタに関する記事を書きますよ(*’▽’)

プログラミング

今日はWindowsプログラミングに関する話を書きたいと思います。

目次

Windows API(Win32API)とは

私は今でもWindowsのアプリケーションを作るときは、Windows API(Win32API)使用しています。

Windows APIとは、マイクロソフトがWindows自身が持つ機能群をプログラマのために公開したAPIのことです。
これを直接操作すればアプリケーションを作ることが可能です

Windows APIを用いてアプリケーションを開発する方法は、Windows 95の時代からある方法です。

C言語とC++で開発可能です。

ところで、このWindows APIを用いてアプリケーションを作るというやり方は、今では古典的でめんどくさいやり方です(;´∀`)

ちょっとしたウィンドウを表示するだけでも何十行とコードを書かなければならないのです(;´・ω・)

なので、今どきこんな方法で開発している会社は、ほとんど存在しないです。

Windows APIを用いないで開発する方法

Windows APIを用いないでアプリケーションを開発するには以下のような方法があります。

  • MFC
  • Windowsフォームアプリケーション(.NET)

(他にもQtを使ってクロスプラットフォームで開発とかいう方法もありますが、純粋なWindowsプログラミングの意味から外れるので、ここでは紹介しません。)

MFCとは

上で言った通り、Windows APIだと、ちょっとしたウィンドウを表示するのにも何十行もコードを書かなければならないのです。

そこで、Windows APIをラップして(覆い隠して)、もっと簡単にアプリケーションを開発できるようにしたのがMFCというフレームワークです。

言語はC言語とC++で開発可能です。

今でもMFCは少なからず使われています。
しかし、主流なやり方ではありません。
なぜならば、他にもっと良い方法があるからです。

因みに、以前、私がバイトしていたベンチャー起業では、MFCを使ってアプリケーションを開発していました。

大学生がIT系の会社のバイトの初出勤で思ったこと
前に記事に書いた通り、今はIT系の会社でバイトしています。業種はアンチウイルスソフトなどを作成するセキュリティ系の会社です。【関連記事】・大学生だけどプログラマのバイトをやろうと思う ・【朗報】大学生俺氏、IT系の会社でバイトする模様 実は、昨日が初出勤でした。この記事では初出勤で思ったことを書きます。バイトの初出勤冒頭にも書いた通り、昨日が初出勤でした。勤務場所は都心とだけ言っておきます。。。特定が怖いのでそれ以上は言いません。。。業種これも冒頭に書いた通り、業種はアンチウイルスソフトなどを開発...

Windowsフォームアプリケーション(.NET)とは

マイクロソフトはインターネットの技術を取り込むのが遅れたので、率先して開発環境にその技術を取り込むことにしました。
その技術の総称を.NETと呼びます。

アプリケーションの開発方法も根本から作り直しました。
そして生まれたのが、Windowsフォームアプリケーションです。

開発は、C++/CLIとC#で可能です。

これが今、もっともメジャーな開発方法です。

私が今バイトしている会社では、C++/CLIで開発しています。

Windowsフォームアプリケーションを使うと、どれくらい楽になるのか

Windows APIとWindowsフォームアプリケーションのコードを比較してみます。

手っ取り早く、ウィンドウを各手法でウィンドウを表示するコードを比較してみます。

Windows API でウィンドウを表示するためのコード

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);	// ウィンドウプロシージャ
ATOM InitApp(HINSTANCE);								// ウィンドウクラスの登録
BOOL InitInstance(HINSTANCE, int);						// ウィンドウの生成

// Windows プログラムのエントリーポイント
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
	LPSTR lpsCmdLine, int nCmdShow)
{
	MSG msg;
	BOOL bRet;

	// ウィンドウクラスの登録
	if (!InitApp(hCurInst))
		return FALSE;
	// ウィンドウの生成
	if (!InitInstance(hCurInst, nCmdShow))
		return FALSE;

	// メッセージを取得
	while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
	{
		if (bRet == -1) {
			break;
		}else{
			TranslateMessage(&msg);		// メッセージを変換
			DispatchMessage(&msg);		// メッセージを送出
		}
	}
	return (int)msg.wParam;
}

// ウィンドウクラスの登録
ATOM InitApp(HINSTANCE hInst)
{
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX);			// 構造体のサイズ
	wc.style = CS_HREDRAW | CS_VREDRAW;		// クラスのスタイル
	wc.lpfnWndProc = WndProc;				// プロシージャ名
	wc.cbClsExtra = 0;						// 補助メモリ
	wc.cbWndExtra = 0;						// 補助メモリ
	wc.hInstance = hInst;					// インスタンス
	wc.hIcon = (HICON)LoadImage(			// アイコン
		NULL, MAKEINTRESOURCE(IDI_APPLICATION),
		IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
	wc.hCursor = (HCURSOR)LoadImage(		// カーソル
		NULL, MAKEINTRESOURCE(IDC_ARROW),
		IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
	wc.hbrBackground =						// 背景ブラシ
		(HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = NULL;					// メニュー名
	wc.lpszClassName = TEXT("Class Name");	// クラス名
	wc.hIconSm = (HICON)LoadImage(			// 小さいアイコン
		NULL, MAKEINTRESOURCE(IDI_APPLICATION),
		IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);

	return(RegisterClassEx(&wc));
}

// ウィンドウの生成
BOOL InitInstance(HINSTANCE hInst, int nCmdShow)
{
	HWND hWnd;
	
	hWnd = CreateWindow(
		TEXT("Class Name"),		// クラス名
		TEXT("ウィンドウ名"),		// ウィンドウ名
		WS_OVERLAPPEDWINDOW,	// ウィンドウスタイル
		CW_USEDEFAULT,			// x位置
		CW_USEDEFAULT,			// y位置
		CW_USEDEFAULT,			// ウィンドウ幅
		CW_USEDEFAULT,			// ウィンドウ高さ
		NULL,		// 親ウィンドウのハンドル、親を作るときは NULL
		NULL,		// メニューハンドル、クラスメニューを使うときは NULL
		hInst,		// インスタンスハンドル
		NULL		// ウィンドウ作成データ
	);

	if (!hWnd)
		return FALSE;

	ShowWindow(hWnd, nCmdShow);		// ウィンドウの表示状態を設定
	UpdateWindow(hWnd);				// ウィンドウを更新
	
	return TRUE;
}

// ウィンドウプロシージャ(コールバック関数)
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
	switch (msg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return(DefWindowProc(hWnd, msg, wp, lp));
	}
	return 0;
}

 

100行前後という長いコードです(;´・ω・)

WinMain関数がエントリーポイントとなっています。

Windows APIだと、メッセージをプロシージャで処理することによって、アプリケーション動いています。

Windowsフォームアプリケーション(C++/CLI)

#include "MyForm.h"

using namespace FirstProject;

[STAThreadAttribute]
int main()
{
	Application::Run(gcnew MyForm());
	return 0;
}

 

Visual C++です。

これだけです。少なっ!!たった10行程度でウィンドウの表示ができてしまいます。

語弊がないように言っておきますが、正確にはこれだけでは動きません。フォームのヘッダーファイルがないと動きません。

しかし、そのファイルはVisual Studioが自動的に書いてくれて、必要な部分だけ付け加えるだけで良いので、かなり楽です。

Windowsフォームアプリケーション(C#)

using System;
using System.Drawing;
using System.Windows.Forms;

class Form01
{
  public static void Main()
  {
      Form f = new Form();
      Application.Run(f);
  }
}

 

Visual C#です。

こちらもとても簡単に書けてしまいます。

Windows APIのときに書いたコードが嘘みたいです(*’▽’)

Windowsフォームアプリケーションを勉強しようと思います

今からMFCを勉強するのは論外でしょう。
今ではあまり使われない技術です(;´・ω・)

やはり、Windowsフォームアプリケーションを勉強するのが良いと思われます。

なので、勉強します。

というか、実はもう既に勉強のために2冊本を購入して読み始めていますw

一応、C++/CLIとC#の両方で開発するやり方を勉強しようと思います。

C++/CLIとC#のどちらが良いのか

私の感覚だと、ベテランはC++/CLIで開発、ビギナーはC#で開発というようなイメージです。

C#だとメモリ管理などコンパイラがやってくれて便利な反面、自由な書き方ができなくなってしまいます。

バイト先の上司はベテランプログラマが多いので、ほぼ全員がC++/CLIで開発していますね。

まぁ、両方できるに越したことはないのだと思いますw

 - 技術系