GUI

 

1. 定義

GUI: Graphical User Interface。いわゆるウィンドウプログラミング。

 

2. GUIの使用例

DOS窓 (Windows)、ターミナル (Linux) ではないウィンドウアプリケーション。マウス操作のアプリケーションの作成。

 

3. GUIに関連するライブラリ群

Windows では Win32、X Windows では Xlib が基本であるが、アプリケーションが大きくなればなるほどコードの量が増えてしまうために、それぞれの抽象度を高めた各種ライブラリ群が提供されている。

Windows版:

Win32 Windows 用の GUI 作成ライブラリ。
MFC Win32 を抽象化したウィンドウプログラミングのためのフレームワーク。ファイル入出力用のドキュメントクラス、グラフィック表示用のビュークラスが基本。C++ の知識が必要。

Linux版:  

Xlib X Window 用の GUI 作成ライブラリ。
Tck/Tk Xlib よりも抽象度の高い GUI 作成ライブラリ。
GTk+ Xlib よりも抽象度の高い GUI 作成ライブラリ。
Qt Xlib よりも抽象度の高い GUI 作成ライブラリ。
他、多数...  

 

4. 簡単なGUIプログラム

GUIプログラムは、基本的に

制御部: ウィンドウの初期化と無限ループ (イベント待ちループ)
イベント処理部: 各種イベント毎の処理

の二つから構成される。制御部は、通常の C プログラムの main 関数に相当し、はじめにウィンドウを作成 (初期化) し、無限ループに入る。イベント処理部は、OS から通知される各種イベントに応答して必要な処理 (デフォルト処理、あるいはプログラミングされた処理) を実行する。全体の処理の流れとしては、制御部の無限ループでイベントの発生を待ち続け、イベントが発生するたびにイベント処理部を呼び出すことを繰り返している。

 

Windows版: Win32の利用

WinMain: 制御部 (main 関数に相当)

WndProc: イベント処理部

イベントの例:

WM_CREATE:  ウィンドウ生成
WM_CLOSE: ウィンドウ終了
WM_PAINT: 描画
WM_LBUTTONDOWN: 左マウスボタンダウン
WM_LBUTTONUP: 左マウスボタンアップ
WM_MOUSEMOVE:マウスの移動
WM_KEYDOWN: キーダウン
WM_KEYUP: キーアップ
WM_TIMER: タイマイベント

など。イベント処理部に記述しない場合はデフォルトの動作が実行される。

#include <windows.h>

// HWND:		ウィンドウへのハンドル(識別子)
// HDC:		デバイスコンテキスト[描画属性]へのハンドル(識別子)
// HINSTANCE:	インスタンスへのハンドル(識別子)
// MSG:		イベント

//
// イベント処理
//
LRESULT APIENTRY 
WndProc (HWND hWnd, UINT msg, UINT wParam, LONG lParam)
{
	HDC hdc;
	PAINTSTRUCT paint;

	// イベントに応じて処理を実行
	switch (msg) {
    	case WM_PAINT:
		hdc = BeginPaint(hWnd, &paint);
		TextOut(hdc, 80, 80, "Hello World", 11);
		EndPaint(hWnd, &paint);
        	return 0;
    	case WM_DESTROY:
		PostQuitMessage (0);
		break;
	}
	return DefWindowProc (hWnd, msg, wParam, lParam);
}

//
// 制御部 (main 関数)
//
int PASCAL
WinMain(HINSTANCE hInst, HINSTANCE hDummy, LPSTR lpStr, int nShowCmd)
{
	WNDCLASS 	wc;
	MSG		msg;
	HWND		hWnd;

    	// ウィンドウクラスの定義
	wc.lpfnWndProc = WndProc;
	wc.hInstance = hInst;
	wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor (NULL, IDC_ARROW);
	wc.lpszClassName = "Player";
	wc.hbrBackground = GetStockObject(WHITE_BRUSH);
	wc.style = 0;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.lpszMenuName = 0;
	RegisterClass (&wc);

    	// ウィンドウの生成
    	hWnd = CreateWindow(
           		wc.lpszClassName, 
			"GUIApp Sample", 
			WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, 
			CW_USEDEFAULT,
			256,
			256,
                 	0, 
			0, 
			hInst, 
			0
    	);
	if (hWnd == NULL) ExitThread (1);
	ShowWindow (hWnd, SW_SHOWNOACTIVATE);
	UpdateWindow (hWnd);

	// 無限ループ (イベントが発生するたびに WndProc を呼び出す)
	while (GetMessage (&(msg), NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage (&msg);
	}

	return msg.wParam;
}

 

Linux版: Xlib の場合

main 関数でウィンドウを生成して無限ループに入り、直接イベント処理を行っている。

イベントの例:

ButtonPress: マウスボタンダウン
ButtonRelease: マウスボタンアップ
KeyPress: キーダウン
KeyRelease: キーアップ

など。イベント処理部に記述しない場合はデフォルトの動作が実行される。

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

// Window:	ウィンドウへのハンドル(識別子)
// Display:	ディスプレイへのハンドル(識別子)
// GC:	グラッフィクコンテキスト[描画属性]へのハンドル(識別子)
// Xevent:	イベント

//
// main関数
//
void
main() {
  	Window window;
  	Display *display;
  	int screen;
  	GC gc;
  	XEvent event;

  	// ディスプレイの指定
  	display = XOpenDisplay("");
  	screen = DefaultScreen(display);

  	// ウィンドウの生成・表示・GC作成、イベント指定
  	window = XCreateSimpleWindow (display,
				RootWindow(display, screen),
				100, 100,
				256, 256,
				4,
				BlackPixel(display, screen),
				WhitePixel(display, screen) );
  	XMapWindow(display, window);
  	gc = XCreateGC(display, window, 0, 0);
	XSelectInput(display, window, ExposureMask | ButtonPressMask);

  	// イベント待ち無限ループ
  	while(1) {
		XNextEvent(display, &event);
    		switch( event.type ) {
    		case ButtonPress: 
			printf(“button pressed\n”);
			XDrawString(display, window, gc, 100, 100, "Hello World", 11);
      		break;
    		}
  	}

  	return;
}