ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ゆういちろう

ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#1

投稿記事 by ゆういちろう » 11年前

こんにちは。
現在、VC2008(C言語・SDK、ダイアログベース)でアプリの開発を行っております。

親ウィンドウ内に子ウィンドウ(ボタンやテキストなどのコントロール)があり、
親ウィンドウをリサイズした場合、同様に子ウィンドウの領域もリサイズさせるというの実現させたいです。

しかしながら、以下に載せるソースで動かしてみたところ、
子ウィンドウの端がふにゃふにゃして、きれいにリサイズできません。

ちらつきなどに関してはダブルバッファ等で軽減できるかとは思いますが、
ウィンドウのふにゃつきにはどう対処したらいいものか・・・

どなたかご教授いただければ助かります。
よろしくお願いします。

コード:

#include <windows.h>
#include <stdio.h>
#include <math.h>
#include "resource.h"

BOOL CALLBACK WndProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
	static HWND hText;			//スタティックテキストのハンドル
	static int gap_top, gap_bottom, 
		       gap_left, gap_right;	//スタティックテキストと、親ウィンドウ間のマージンを格納

	switch (msg){
		case WM_INITDIALOG :
			{
				RECT dialog_rc, text_rc;	// 親ウィンドとスタティックテキストの領域を格納

				hText = GetDlgItem(hDlg, IDC_TEXT1);

				// 親ウィンドとスタティックテキストのクライアント領域取得
				GetClientRect(hDlg, &dialog_rc);
				GetWindowRect(hText, &text_rc);
				MapWindowPoints(NULL, hDlg, &text_rc, 2);

				//スタティックテキストと、親ウィンドウ間のマージン計算
				gap_top		= abs(dialog_rc.top - text_rc.top);
				gap_bottom	= abs(dialog_rc.bottom - text_rc.bottom);
				gap_left	= abs(dialog_rc.left - text_rc.left);
				gap_right	= abs(dialog_rc.right - text_rc.right);
			}
			break;

		case WM_SIZING:
			{
				RECT dialog_rc; // 親ウィンドの領域を格納
				
				//現在の親ウィンドウのクライアント領域を取得
				memcpy(&dialog_rc, (RECT*)lp, sizeof(RECT));
				MapWindowPoints(NULL, hDlg, &dialog_rc, 2);
				
				//スタティックテキスト領域を、親ウィンドウの移動と同時に調整させながら移動
				MoveWindow(hText, gap_left, gap_top, dialog_rc.right - (gap_left + gap_right), dialog_rc.bottom - (gap_top + gap_bottom), FALSE);
			}
			break;

		case WM_SIZE:
			{
				InvalidateRect(hDlg, NULL, FALSE);
			}
			break;

		case WM_CLOSE:		//×ボタン
			EndDialog(hDlg, 0);
			return TRUE;

		default:
			break;
	}

	return FALSE;
}


int WINAPI WinMain(HINSTANCE hThisInst,HINSTANCE hPrevInst,LPSTR lpszArgs,int nWinMode)
{
	//ウィンドウ起動
	DialogBox(NULL,MAKEINTRESOURCE(IDD_DIALOG1),NULL,(DLGPROC)WndProc);

	return 0;
}

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

Re: ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#2

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

リソースの情報も頂けたらと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ゆういちろう

Re: ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#3

投稿記事 by ゆういちろう » 11年前

softya様

返信ありがとうございます。
以下に、リソース等のファイル情報を載せます。
よろしくお願いします。

resource.h

コード:

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Wintest20120816.rc
//
#define IDD_DIALOG1                     101
#define IDC_TEXT1                       1001

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1004
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
main.rc

コード:

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// 日本語 resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
#ifdef _WIN32
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
#pragma code_page(932)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DIALOG1 DIALOGEX 0, 0, 455, 279
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_WINDOWEDGE
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    LTEXT           "",IDC_TEXT1,12,8,434,260,WS_BORDER,WS_EX_CLIENTEDGE
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO 
BEGIN
    IDD_DIALOG1, DIALOG
    BEGIN
        LEFTMARGIN, 12
        RIGHTMARGIN, 446
        TOPMARGIN, 8
        BOTTOMMARGIN, 268
    END
END
#endif    // APSTUDIO_INVOKED

#endif    // 日本語 resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

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

Re: ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#4

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

ちょっと遅れてリサイズされるのは仕様かなと思いますが、描画のゴミが残る場合があるようです。
WM_SIZINGでもInvalidateRect()してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#5

投稿記事 by ISLe » 11年前

WM_SIZINGのlParamで受け取るのは、クライアント領域ではなくて(枠を含む)ウィンドウの情報なので、サイズ計算がいろいろ間違っている気がします。

ゆういちろう

Re: ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#6

投稿記事 by ゆういちろう » 11年前

引き続きご返信ありがとうございます。

InvalidateRectについてですが、やはりWM_SIZINGに入れてもうまくいきません。
仕様なんでしょうか・・・。
他の既製ソフトなどは、うまいことリサイズできているので、
なにかしら方法があるかなと思ったんですが・・・。

ゆういちろう

Re: ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#7

投稿記事 by ゆういちろう » 11年前

ISLe様

ご返信ありがとうございます。

LPARAMについてですが、ご指摘ありがとうございます。
確かに、枠の領域等の計算がおかしくなっていますが、枠がふにゃふにゃ動くのとは関連があるのでしょうか?
GetClientRectで領域を取得しても同様にふにゃふにゃになったので、
ウィンドウ領域の取得方法に問題があるわけではないと勝手に思い込んでいたのですが。

ゆういちろう

Re: ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#8

投稿記事 by ゆういちろう » 11年前

自己解決?しましたので、報告します。

以下のように、視点を変えてみたら、うまくいきました。
初期状態からどれだけ動いたかを計算し、大きさを調整するようにしています。

ただ、自分自身では何故これでうまくいっているのかわかりません。

ISLe様のおっしゃるように、LPARAMの使い方を間違っていたのでしょうか・・・

最初のやり方
1.最初にマージンを測っておく
2.サイズ変更ごとに、親ウィンドウの座標からマージンを引く
3.その座標にテキストを移動させる

後のやり方
1.最初に親ウィンドウの座標を取得する
2.サイズ変更ごとに、親ウィンドウの移動幅を取得する
3.テキストを移動幅分、移動させる

根本的に違いが見出せません・・・
一応実現できたので、解決とします。

お騒がせいたしました。
また、返信して頂いたお二方、ありがとうございました。

コード:

#include <windows.h>
#include <stdio.h>
#include <math.h>
#include "resource.h"

BOOL CALLBACK WndProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
	static HWND hText;		//スタティックテキストのハンドル
	static RECT init_dlg_rc;	//親ウィンドウの初期領域を格納
	static RECT cur_dlg_rc;	//親ウィンドウの移動後の領域を格納
	static RECT text_rc;		//スタティックテキストの領域を格納
	static POINT mv_pos;		//親ダイアログの初期状態からの移動幅を格納

	switch (msg){
		case WM_INITDIALOG :
			{
				hText = GetDlgItem(hDlg, IDC_TEXT1);

				// 親ウィンドの初期スクリーン領域取得
				GetWindowRect(hDlg, &init_dlg_rc);

				//スタティックテキストのクライアント領域取得
				GetWindowRect(hText, &text_rc);
				MapWindowPoints(NULL, hDlg, &text_rc, 2);
			}
			break;

		case WM_SIZING:
			{
				//現在の親ウィンドウのスクリーン領域を取得
				memcpy(&cur_dlg_rc, (RECT*)lp, sizeof(RECT));

				//親ウィンドウが初期状態からどれだけ動いた計算
				mv_pos.x = (cur_dlg_rc.right - init_dlg_rc.right) + (init_dlg_rc.left - cur_dlg_rc.left);
				mv_pos.y = (cur_dlg_rc.bottom - init_dlg_rc.bottom) + (init_dlg_rc.top - cur_dlg_rc.top);

				//スタティックテキストを移動
				MoveWindow(hText,	text_rc.left, text_rc.top, text_rc.right - text_rc.left + mv_pos.x,  text_rc.bottom - text_rc.top + mv_pos.y, FALSE);

				//再描画
				InvalidateRect(hDlg, NULL, FALSE);
			}
			break;

		case WM_CLOSE:		//×ボタン
			EndDialog(hDlg, 0);
			return TRUE;

		default:
			break;
	}

	return FALSE;
}


int WINAPI WinMain(HINSTANCE hThisInst,HINSTANCE hPrevInst,LPSTR lpszArgs,int nWinMode)
{
	//ウィンドウ起動
	DialogBox(NULL,MAKEINTRESOURCE(IDD_DIALOG1),NULL,(DLGPROC)WndProc);

	return 0;
}

ゆういちろう

Re: ウィンドウサイズ変更時の、子ウィンドウの振る舞いについて

#9

投稿記事 by ゆういちろう » 11年前

すいません、「解決」し忘れていました。

閉鎖

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