ウィンドウ作成クラスの設計について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
atori
記事: 43
登録日時: 13年前

ウィンドウ作成クラスの設計について

#1

投稿記事 by atori » 12年前

C++の概念、知識自体はある程度ついてきたので、使いまわせるクラスを作ろうと思っています。

ウィンドウを作成するクラスを作りたいのですが、少し困っている部分があります。
ウィンドウハンドルを取得するメソッドを作っているのですが、ウィンドウハンドルは色んな所で使うときがあります。

その為に、今まではグローバル領域にインスタンスを定義していました。
しかし、シングルトンというデザインパターンがあるのを知り、こちらのほうがいいなと思ったのですが、
ウィンドウは一つのプログラムで複数作る可能性があります。

ではシングルトンはダメ。となったのですが、なんだかグローバルに作るのも・・・と思い始めています。

やはりグローバルに置くしかないのか、それとも他に方法があるのか・・・ご教授願います。

一応、現在のクラスを貼っておきます。シングルトンは使っていません。

[CreateWindow.h]

コード:

#pragma once

#include <d3dx9.h>

class CCreateWindow
{
private:
	WNDCLASSEX	wc;
	HWND		hWnd;
	MSG			msg;
	LPSTR		wndName;

	int			screenWidth;
	int			screenHeight;

private:
	static		LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	void		SetWindowClass(HINSTANCE *hInstance, LPSTR className);
		

public:
	CCreateWindow(int screenWidth, int screenHeight);
	virtual		~CCreateWindow(void);

	void		Init(HINSTANCE *hInstance, LPSTR wndName, LPSTR className, int nCmdShow);
	void		SetShowWindow(HWND hWnd, int nCmdShow);
	BOOL		DispatchedMessage(void);
	int		    GetMessageWParam(){return (int)msg.wParam;}
	HWND	    GetHWnd(){return hWnd;}
};



[CreateWindow.cpp]

コード:

#include "CreateWindow.h"

CCreateWindow::CCreateWindow(int screenWidth, int screenHeight)
{
	this->screenWidth  = screenWidth;
	this->screenHeight = screenHeight;
}


CCreateWindow::~CCreateWindow(void)
{
}


// 初期化
void CCreateWindow::Init(HINSTANCE *hInstance, LPSTR wndName, LPSTR className, int nCmdShow)
{
	this->SetWindowClass(hInstance, className);

	if(!(RegisterClassEx(&wc)))
	{	// 設計書をWindowsに提出
		MessageBox(NULL, "ウィンドウ初期化エラー", "", MB_OK);
		exit(1);
	}

	hWnd = CreateWindow(wc.lpszClassName,
			wndName,
			WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			screenWidth,
			screenHeight,
			NULL,
			NULL,
			*hInstance,
			NULL
		);

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
}


// ウィンドウクラスの作成
void CCreateWindow::SetWindowClass(HINSTANCE *hInstance, LPSTR className)
{
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.hInstance = *hInstance;
	wc.lpszClassName = className;
	wc.lpfnWndProc = (WNDPROC)WndProc;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.lpszMenuName = NULL;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
}


// ウィンドウの表示設定
void CCreateWindow::SetShowWindow(HWND hWnd, int nCmdShow)
{
	ShowWindow(hWnd, nCmdShow);
}


// メッセージの送出
BOOL CCreateWindow::DispatchedMessage(void)
{
	if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
	{
		if(GetMessage(&msg, NULL, 0, 0) == 0)
		{
			return false;
		}
	    TranslateMessage(&msg);
	    DispatchMessage(&msg);
	}
	return true;
}

// ウィンドウプロシージャ
LRESULT CALLBACK CCreateWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch( message ){

			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;


		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;
}
Done is better than perfect.(Mark Elliot Zuckerberg)

アバター
せんちゃ
記事: 50
登録日時: 14年前
住所: 江別市東野幌町
連絡を取る:

Re: ウィンドウ作成クラスの設計について

#2

投稿記事 by せんちゃ » 12年前

ウィンドウを作成するにあたってまずウィンドウクラスにインスタンスハンドルを指定する必要があります。
このインスタンスハンドルはアプリ内でユニークな存在で、ウィンドウを作成、クラス登録は全てこいつを経由します。

WNDCLASSとHWNDはウィンドウ生成を行う上で必要な最低限のことしかやっていないことと、
ウィンドウプロシージャーは各ウィンドウに一つ割り当てる必要がある(これはクラスメンバ関数とかではダメ)
ので、私は各ウィンドウを作るたびに同じようなコードを書けばいいんじゃないかなと思います。

>ではシングルトンはダメ。となったのですが、なんだかグローバルに作るのも・・・と思い始めています。
ウィンドウがどういう状態であるのかをアプリ層は意識してはいけませんが(容易にアクセスしてもいけない)
クラスにする必要はないかなと思いますしグローバルにしてしまっても問題ないと思います。

ただしグローバルにしてもアクセスの仕方は考えたほうがいいです。
ヽ(*゚д゚)ノ カイバー

usao

Re: ウィンドウ作成クラスの設計について

#3

投稿記事 by usao » 12年前

>私は各ウィンドウを作るたびに同じようなコードを書けばいいんじゃないかなと思います。
えー…
「ウィンドウの作成とかメッセージまわりの処理において,毎回やってる共通的な処理をまとめたクラスを作りたい」んだと思いますが.
MFCのCWndみたいな.

で,インスタンスをどこにおくか,ですが…
そのウィンドウが必要な間,生存できる箇所 であればどこでもいいはずですが,
「プログラム実行中のほとんどの期間必要で,且つ,各所からのアクセスが必要」なのであれば
まぁ一番楽なのは,グローバル的な箇所だと思います.
もちろん,そういったグローバル的な変数の変数名がコード各所にべた書きになっている状況はよくないので,
>ただしグローバルにしてもアクセスの仕方は考えたほうがいいです。
ということになります.
(アクセス側は,それがグローバルにあることを知らなくてよいようにする)

アバター
せんちゃ
記事: 50
登録日時: 14年前
住所: 江別市東野幌町
連絡を取る:

Re: ウィンドウ作成クラスの設計について

#4

投稿記事 by せんちゃ » 12年前

>「ウィンドウの作成とかメッセージまわりの処理において,毎回やってる共通的な処理をまとめたクラスを作りたい」んだと思いますが.
MFCのCWndみたいな.

CWndでもやっていることはHWNDと同じだと考えています。
単にウィンドウの細かい設定をメソッドで渡すようにしているのか構造体でわたしているのか、とか
ウィンドウプロシージャで処理しているのかコールバックでラッピングしているのか~とか。

でもウィンドウプロシージャーはクラスメンバにはできませんし、
そういうクラスを自作しても結局ハンドリングは外部で作った関数を用意する感じになると思うので、そんな面倒な仕組みを作るくらいなら最初から普通に作ったほうが管理も楽だと思う、というのが私の意見です。
ヽ(*゚д゚)ノ カイバー

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: ウィンドウ作成クラスの設計について

#5

投稿記事 by softya(ソフト屋) » 12年前

せんちゃ さんが書きました:>「ウィンドウの作成とかメッセージまわりの処理において,毎回やってる共通的な処理をまとめたクラスを作りたい」んだと思いますが.
MFCのCWndみたいな.

CWndでもやっていることはHWNDと同じだと考えています。
単にウィンドウの細かい設定をメソッドで渡すようにしているのか構造体でわたしているのか、とか
ウィンドウプロシージャで処理しているのかコールバックでラッピングしているのか~とか。

でもウィンドウプロシージャーはクラスメンバにはできませんし、
そういうクラスを自作しても結局ハンドリングは外部で作った関数を用意する感じになると思うので、そんな面倒な仕組みを作るくらいなら最初から普通に作ったほうが管理も楽だと思う、というのが私の意見です。
一応、ウィンドウプロシージャーはこういうメンバ関数化の方法もあります。
「■■Programmer's Studio■■」
http://members3.jcom.home.ne.jp/progstu ... tips2.html

どうウィンドウをクラス化するか次第だとは私は思います。
私は、コントロールとかのクラスを作ることを考えるとパッケージ化したほうが良い気もするんですよね。
MFCばっかりで一から組んでないせいかもしれませんが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
せんちゃ
記事: 50
登録日時: 14年前
住所: 江別市東野幌町
連絡を取る:

Re: ウィンドウ作成クラスの設計について

#6

投稿記事 by せんちゃ » 12年前

softya(ソフト屋) さんが書きました: 一応、ウィンドウプロシージャーはこういうメンバ関数化の方法もあります。
「■■Programmer's Studio■■」
http://members3.jcom.home.ne.jp/progstu ... tips2.html
おお、こんな実装方法があったんですね。
このような方法でしたら設計的にも面倒にはなりませんね、勉強になりました。
ヽ(*゚д゚)ノ カイバー

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: ウィンドウ作成クラスの設計について

#7

投稿記事 by YuO » 12年前

ちなみに,ポインタをウィンドウに結びつけるには,GWL_USERDATAの他に,SetProp, GetPropを使う方法もあります。

私もウィンドウ/クラスをどう使うかで設計が変わると思っていますが,設計のやり方次第で,Viewの範囲外に対してウィンドウ/クラスを見せる必要がないような作りが可能だと思います。
# 必要ならば関数の引数で引き回すことになりますが……。

atori
記事: 43
登録日時: 13年前

Re: ウィンドウ作成クラスの設計について

#8

投稿記事 by atori » 12年前

幾つもの返信ありがとうございます。

グローバルに置いたあとに、どうアクセスさせればよいのかまで考えていませんでした。
良い方法がないか模索してみます。ありがとうございました。
Done is better than perfect.(Mark Elliot Zuckerberg)

閉鎖

“C言語何でも質問掲示板” へ戻る