LoginSignup
1
0

More than 1 year has passed since last update.

ウィンドウのサイズ変更に合わせてコントロールのサイズを変更する

Posted at

アカウント統合により過去記事再掲:元の投稿日 2016年03月29日

例えばダイアログのサイズを変更した時

image
↓サイズ変更すると・・・
image

あらあら、まあまあ。

C#なんかは↓こういうアンカーがあって便利なのに。
image

というわけで久々にMFCを触ってて、そういや昔これに対応するクラス作ったなーと。VC++6の時なんだけど。

引っ張りだして使ってみたら、今でも普通に使えたんでQiitaにでも貼り付けとこうというお話。

Doxygenが懐かしい

コメントの**@brief**とかはDoxygenというドキュメンテーションツールで、そういや使ってたなーと懐かしんでおりましたとさ。

stratchControl.hpp
/** @file StretchControl.hpp
	@brief CStretchControl 定義ファイル
*/
#ifndef __STRETCHCONTROL_HPP__
#define __STRETCHCONTROL_HPP__

/**
	@class CStretchControl
	@brief 親ウィンドウ(通常はダイアログ)の伸縮にあわせて、伸縮(または移動)するウィンドウのテンプレートクラス
	@param T 適用するウィンドウ(TはCWndの派生クラスである必要があります)
	@par 概要:
	<BR>
	親ウィンドウ(通常はダイアログ)の伸縮にあわせて、伸縮(または移動)するウィンドウの
	テンプレートクラス

	@par 使い方:
	<BR>
		伸縮(移動)するウィンドウはサブクラス化をサブクラス化します。<BR>
		親ウィンドウが WM_SIZE を受信した時に、このクラスの Resizeメソッドを呼び出し
		て下さい。

	@par 例:
	<BR>
		ダイアログのエディットコントロールを対象とする場合<BR>
<BR>
		1) C***Dlg に CStretchControl<CEdit>型のメンバ変数を追加<BR>
		2) OnInitDialogで SubclassDlgItem を呼び出す<BR>
		3) OnSize を実装し、Resizeを呼び出す<BR>
*/
template<class T>
class CStretchControl : public T
{
	/** @brief 差分を格納する矩形 */
	CRect m_rectDiff;

	/** @brief 伸縮タイプ */
	UINT  m_baseType;

	/** @brief 保持された幅 */
	LONG  m_width;

	/** @brief 保持された高さ */
	LONG  m_height;

public:
	enum {
		normal = 0x00,
		top    = 0x01,
		left   = 0x02,
		bottom = 0x04,
		right  = 0x08,
	};

	/** @brief 標準のコンストラクタ */
	CStretchControl() : T(), m_baseType( 0 ), m_width( 0 ), m_height( 0 ) {
	}

protected:
	/** @brief SubclassWindow を呼び出す前にサブクラス化することを許します */
	virtual void PreSubclassWindow() {
		CRect rect, me;
		GetParent()->GetClientRect( &rect );
		
		GetWindowRect( &me );

		m_width  = me.Width();
		m_height = me.Height();

		GetParent()->ScreenToClient( &me );

		m_rectDiff.top    = me.top    - rect.top;
		m_rectDiff.left   = me.left   - rect.left;
		m_rectDiff.bottom = me.bottom - rect.bottom;
		m_rectDiff.right  = me.right  - rect.right;
	}

public:
	/** @brief 伸縮タイプに従ってサイズ変更を実施します */
	void Resize() {
		if( !m_hWnd ) {
			return;
		}
		CRect rect, me;

		GetParent()->GetClientRect( &rect );

		me.top    = rect.top    + m_rectDiff.top;
		me.left   = rect.left   + m_rectDiff.left;
		me.bottom = rect.bottom + m_rectDiff.bottom;
		me.right  = rect.right  + m_rectDiff.right;

		if( m_baseType & top    ) { me.bottom = me.top    + m_height; }
		if( m_baseType & left   ) { me.right  = me.left   + m_width;  }
		if( m_baseType & bottom ) { me.top    = me.bottom - m_height; }
		if( m_baseType & right  ) { me.left   = me.right  - m_width;  }

		MoveWindow( &me );

		InvalidateRect( NULL );
	}

	/** @brief 伸縮タイプを設定します 
		@param ui IN 伸縮タイプ
		@par 解説
			引数 ui には次の値を連結して指定します<BR>
		<BR>
			normal = 0x00	標準の伸縮をサポートします<BR>
			top    = 0x01	上を基点として上下には移動のみを行います<BR>
			left   = 0x02,	左を基点として左右には移動のみを行います<BR>
			bottom = 0x04,	下を基点として上下には移動のみを行います<BR>
			right  = 0x08,	右を基点として左右には移動のみを行います<BR>
		<BR>
			top, bottom の何れかが指定された場合、ウィンドウは最初の高さを保持します。<BR>
			left, right の何れかが指定された場合、ウィンドウは最初の幅を保持します。<BR>
	*/
	void setBase( UINT ui ) {
		m_baseType = ui;
	}

	/** @brief 伸縮タイプ基点を左下に設定します
	*/
	void setBase_BottomLeft() {
		m_baseType = bottom | left;
	}

	/** @brief 伸縮タイプ基点を下に設定します */
	void setBase_Bottom() {
		m_baseType = bottom;
	}

	/** @brief 伸縮タイプ基点を右下に設定します
	*/
	void setBase_BottomRight() {
		m_baseType = bottom | right;
	}

	/** @brief 伸縮タイプ基点を右に設定します */
	void setBase_Right() {
		m_baseType = right;
	}
};

#endif // __STRETCHCONTROL_HPP__

使い方

コメントに書いてある通りなんだけど、

・C***Dlg に CStretchControl型のメンバ変数を追加
・OnInitDialogで SubclassDlgItem を呼び出す
・OnSizeでResizeを呼び出す

これだけ。
お手軽。
もしクラスウィザードからCEditとかのコントロール変数を追加した場合は、自分でSubclassDlgItemを呼び出す必要はナッシング。
CEdit m_hoge;

CStretchControl<CEdit> m_hoge;
こんな感じにするだけでよろしい。

ほんで、WM_SIZEをハンドリングして、
image

m_hoge.Resize();を呼び出すだけ。
image

びよーん

image

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0