MFCにて画像サイズとウィンドウサイズがうまく連動しない

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

MFCにて画像サイズとウィンドウサイズがうまく連動しない

#1

投稿記事 by 幸尚 » 1年前

改めましてよろしくお願いします。
今現在、MFCにて簡単な画像ビュワーを作成してます。
問題になっているのは画像を縮小して縮小した画像に合わせてウィンドウサイズを変更するコードを書きましたが
ウィンドウサイズを変更して縮小した画像より画面サイズが小さければウィンドウにスクロールバーを表示する仕様にしてます。
しかし、スクロールバーが表示した状態で新たに画像を読み込むと縮小した画像より少し大きい(スクロールバー分)サイズにウィンドウサイズが変更されます。
水平スクロールバーのみを表示した状態で新たに画像を読み込むと横幅のみスクロールバー分大きいウィンドウサイズになってしまいます。
垂直スクロールバーのみ表示した状態でも同様縦幅のみスクロールバー分大きいウィンドウサイズになっていしまいます。
スクロールバーが表示されない状態で新たに画像を読み込むと縮小した画像とぴったりなサイズにウィンドウを変更してくれます。
画像を新たに読み込むと気にスクロールバーを解除してもスクロールバー分大きいウィンドウサイズになってしまいます。
このような場合どのようにすれば良いか途方にくれています。
以上、なにか良い案があればご提示宜しくお願い致します。

動作環境は
OS: Windows 10 Home 22H2
開発環境: Visual studio 2019
です。

以下にざっくりではありますがソースコードを記載させて頂きます。

コード:

 
// 画像ファイルを読み込む
void xxxxx::OnFileOpen()
{
	// 画像読み込み処理
	...
	...
	...
	if (読み込み成功)
	{
		// スクロールバーの解除
		LONG dwStyle = ::GetWindowLong(this->m_hWnd, GWL_STYLE);
		if ((dwStyle & WS_HSCROLL) == WS_HSCROLL)
		{
			dwStyle &= ~WS_HSCROLL;
		}
		if ((dwStyle & WS_VSCROLL) == WS_VSCROLL)
		{
			dwStyle &= ~WS_VSCROLL;
		}
		::SetWindowLong(this->m_hWnd, GWL_STYLE, dwStyle);
    }
	Invalidate(true);
}

// ウィンドウ再描画メッセージ
void xxxxx::OnPaint()
{
	CPaintDC dc(this);
	
	// 読み込んだ画像を縮小する処理
	// 縮小した画像を描画する処理

	int nWidth = 縮小した画像サイズ(幅);
	int nHeight = 縮小した画像サイズ(高さ);


	// 縮小した画像に合わせてウィンドウサイズを変更
	RECT rect1, rect2;

	GetWindowRect(&rect1);
	GetClientRect(&rect2);

	nWidth += ((rect1.right - rect1.left) - (rect2.right - rect2.left));
	nHeight += ((rect1.bottom - rect1.top) - (rect2.bottom - rect2.top));

	SetWindowPos(
		nullptr,
		0,
		0,
		nWidth,
		nHeight,
		(SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE)
	);
}

// ウィンドウ変更メッセージ
void xxxxx::OnSize(UINT nType, int cx, int cy)
{
	CFrameWnd::OnSize(nType, cx, cy);

	LONG dwStyle = ::GetWindowLong(this->m_hWnd, GWL_STYLE);
	if (cx < 縮小した画像サイズ(幅))
	{
		dwStyle |= WS_HSCROLL;
	}
	else
	{
		dwStyle &= ~WS_HSCROLL;
	}

	if (cy < 縮小した画像サイズ(高さ))
	{
		dwStyle |= WS_VSCROLL;
	}
	else
	{
		dwStyle &= ~WS_VSCROLL;
	}
	::SetWindowLong(this->m_hWnd, GWL_STYLE, dwStyle);


	Invalidate(true);
}
 
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#2

投稿記事 by 幸尚 » 1年前

分かりづらいかもなので画像を送付させて頂きます。

①スクロールバーが表示されている状態画像

②新たに画像ファイルを読み込む画像

新たにファイルを読み込むと②の画像のように上下左右に黒い帯が出ます。
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

アバター
usao
記事: 1889
登録日時: 11年前

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#3

投稿記事 by usao » 1年前

OnPaint() の中でウィンドウサイズを変えてるってのは妥当か…? というのも若干気になりますが,それはそれとして…

ウィンドウのサイズを変える処理を行っている個所のサイズ計算過程を調査して「どうしてそうなるのか」を突き止めれば良いのではないでしょうか.

当てずっぽうですが,

(1) スクロールバーがある状態でサイズ計算すれば,スクロールバー込みでのウィンドウサイズに変更することになる
(2) (1)の後でスクロールバーが要らないという判定になり,スクロールバーが消される.その結果としてスクロールバーがあった箇所が余白になる.

みたいなことになっているのでは?

アバター
usao
記事: 1889
登録日時: 11年前

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#4

投稿記事 by usao » 1年前

ウィンドウのサイズを変えるような処理は,その結果として,スクロールバーの表示有無だけでなくメニューの表示幅が変わったりとかいうことも生じ得るため,
サイズ変更前の状態における「画像表示する領域のサイズ」に基づいて新しいウィンドウサイズを求めても,そのサイズにすれば表示域のサイズが画像ぴったりになるとは限らないです.

私がこれ系の実装をしたときは,上記のような「現領域サイズを基準にして新しいウィンドウサイズを求めてウィンドウリサイズする」という処理を2回以上(ウィンドウサイズを変えずに済む状態になるまで)実施するようにして対処しました.
(経験上では2回で終わる様子.3回以上やることになる場合があり得るのかは不明)

アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#5

投稿記事 by 幸尚 » 1年前

レスありがとうございます。
あれから色々調査したところ自分ではスクロールバーを消しているつもりだったのですが実際スクロールバーが消えてなくてその結果、スクロールバーが表示されている状態でウィンドウサイズを計算していました。

しかしながら、画像を読み込む際に動的にスクロールバーを消す処理をしてもスクロールバーは消えませんでした。

コード:

void xxxxx::OnFileOpen()
{
	// 画像読み込み処理
	...
	...
	...
	if (読み込み成功)
	{
		・・・
	}
	// スクロールバーの解除
	LONG dwStyle = ::GetWindowLong(this->m_hWnd, GWL_STYLE);
	dwStyle &= ~WS_HSCROLL;
	dwStyle &= ~WS_VSCROLL;
	::SetWindowLong(this->m_hWnd, GWL_STYLE, dwStyle);
	Invalidate(true);
}
上記コードでスクロールバーを消しているのですが消えません。
ShowScrollBar()やSetWindowLongPtr()を試しても消えません。
なにかスクロールバーを消す方法がないでしょうか?
お知恵をお貸しくださますようお願い致します。

あと一つ気になったのですが
OnPaint() の中でウィンドウサイズを変えてるってのは妥当か…?
普通はどのようにすれば良いのですか?
OnPaint()内でOnSizs()イベントを投げてOnSize()内でやるべきなのでしょうか?
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

アバター
あたっしゅ
記事: 665
登録日時: 14年前
住所: 東京23区
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#6

投稿記事 by あたっしゅ » 1年前

東上☆海美☆「
『MFC で、画像サイズとウィンドウサイズを、うまく一致させらるのは難しい』ってのは、
MFC が流行っていた頃から言われていたみみ。

Microsoft の MFC を捨てて、C# で書き直す、とか、いっそうの事、Embardero C++ Builder や Delphi (Pascal だけど)に乗り換える、といった方が精神衛生上、いいかも。
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

アバター
あたっしゅ
記事: 665
登録日時: 14年前
住所: 東京23区
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#7

投稿記事 by あたっしゅ » 1年前

東上☆海美☆「
Embardero じゃなくて Embarcadero(エンバカデロ)だ。
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#8

投稿記事 by 幸尚 » 1年前

レスありがとうございます。
『MFC で、画像サイズとウィンドウサイズを、うまく一致させらるのは難しい』ってのは、
MFC が流行っていた頃から言われていたみみ。
そうなのですね。
恥ずかしながらあまりそのようなアプリを作ったのことがないのであまり意識したことがありませんでした。
Microsoft の MFC を捨てて、C# で書き直す、とか、いっそうの事、Embardero C++ Builder や Delphi (Pascal だけど)に乗り換える、といった方が精神衛生上、いいかも。
C#で書き直すことも考えましたがC#はどうも私には肌が合わないようで…
また、現在作っているアプリはSusieのプラグインを読み込んできてそれを使っています。
C#ではC言語で書かれたDLLを読み込む方法が少し面倒くさかったように思います。
もし、.NETで書き直すのであればC++/CLIを勉強して書き直すかもしれません。
Embarcadero C++ Builderは初耳です。
今度、調べてみます。
Delphiに関してもやったことがありません。
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#9

投稿記事 by 幸尚 » 1年前

あれからスクロールバーを消すことを考えたりしましたがなぜ消えないのか未だにわかりません。
試行錯誤を色々試して以下の方法で解決することができましたので報告させて頂きます。
画像を描画した後にウィンドウをリサイズしていましたがその前にウィンドウを隠して一旦ウィンドウをデスクトップサイズにリサイズした後、正常なウィンドウサイズにリサイズしてからまたウィンドウを表示するようにしたところ上手くいきました。
ソースコードとしては以下のように修正しました。

コード:

// ウィンドウ再描画メッセージ
void xxxxx::OnPaint()
{
	CPaintDC dc(this);
	
	// 読み込んだ画像を縮小する処理
	// 縮小した画像を描画する処理

	int nWidth = 縮小した画像サイズ(幅);
	int nHeight = 縮小した画像サイズ(高さ);


	// ウィンドウを非表示
	ShowWindow(SW_HIDE);

	// ウィンドウをデスクトップサイズにリサイズ
	SetWindowPos(
		nullptr,
		0,
		0,
		デクトップの幅,
		デクトップの高さ,
		(SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE)
	);

	// 縮小した画像に合わせてウィンドウサイズを変更
	RECT rect1, rect2;

	GetWindowRect(&rect1);
	GetClientRect(&rect2);

	nWidth += ((rect1.right - rect1.left) - (rect2.right - rect2.left));
	nHeight += ((rect1.bottom - rect1.top) - (rect2.bottom - rect2.top));

	SetWindowPos(
		nullptr,
		0,
		0,
		nWidth,
		nHeight,
		(SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE)
	);
	SetWindowPos(
		nullptr,
		0,
		0,
		nWidth,
		nHeight,
		(SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE)
	);
	// ウィンドウを表示
	ShowWindow(SW_SHOW);
}
力技といえば力技で逃げといえば逃げになりこれが正解かもわかりません。

色々、ご提示、一緒に考えてくださったり本当にありがとうございました。
また何かあればご提示宜しくお願い致します。
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#10

投稿記事 by 幸尚 » 1年前

すいません、よく見たらソースミスってました…

コード:

// ウィンドウ再描画メッセージ
void xxxxx::OnPaint()
{
	CPaintDC dc(this);
	
	// 読み込んだ画像を縮小する処理
	// 縮小した画像を描画する処理

	int nWidth = 縮小した画像サイズ(幅);
	int nHeight = 縮小した画像サイズ(高さ);


	// ウィンドウを非表示
	ShowWindow(SW_HIDE);

	// ウィンドウをデスクトップサイズにリサイズ
	SetWindowPos(
		nullptr,
		0,
		0,
		デクトップの幅,
		デクトップの高さ,
		(SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE)
	);

	// 縮小した画像に合わせてウィンドウサイズを変更
	RECT rect1, rect2;

	GetWindowRect(&rect1);
	GetClientRect(&rect2);

	nWidth += ((rect1.right - rect1.left) - (rect2.right - rect2.left));
	nHeight += ((rect1.bottom - rect1.top) - (rect2.bottom - rect2.top));

	SetWindowPos(
		nullptr,
		0,
		0,
		nWidth,
		nHeight,
		(SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE)
	);

	// ウィンドウを表示
	ShowWindow(SW_SHOW);
}
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

アバター
あたっしゅ
記事: 665
登録日時: 14年前
住所: 東京23区
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#11

投稿記事 by あたっしゅ » 1年前

[雑談][香車]東上☆海美☆「

> Susieのプラグイン

とは、随分、香ばしいみみ。
今は、.jpeg ローダーも .png ローダーも、フリーなソースが、簡単に手に入るだろう。
そもそも、Embardero C++ Builder とか言い始める前に、ここの標準の DxLIb 使えばいいだろ。
え、スクロール・バーがない ? 4K モニタ、買えよ。

> MFC

> OS: Windows 10 Home 22H2
> 開発環境: Visual studio 2019

とか、もしかして 32bit 環境なのか ?
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

アバター
幸尚
記事: 47
登録日時: 2年前
連絡を取る:

Re: MFCにて画像サイズとウィンドウサイズがうまく連動しない

#12

投稿記事 by 幸尚 » 1年前

こんにちは、自己報告になりますが、
画像を描画した後にウィンドウをリサイズしていましたがその前にウィンドウを隠して一旦ウィンドウをデスクトップサイズにリサイズした後、正常なウィンドウサイズにリサイズしてからまたウィンドウを表示するようにしたところ上手くいきました。
上記で対応してましたがやはり何が悪いのか突き止めないと気持ちが悪いので突き止めた結果、前のウィンドウサイズが保持されているのが原因でしたので、画像ファイルを読み込んで成功したら縮小した画像サイズを一旦初期化することによってバグを回避できましたので報告させて頂きます。

また、MFCで組んでましたがC#もやっぱり捨てがたくこれからの言語ということでC#で組み直しております。
> Susieのプラグイン
とは、随分、香ばしいみみ。
今は、.jpeg ローダーも .png ローダーも、フリーなソースが、簡単に手に入るだろう。
そもそも、Embardero C++ Builder とか言い始める前に、ここの標準の DxLIb 使えばいいだろ。
え、スクロール・バーがない ? 4K モニタ、買えよ。
数十年前にSusieを愛用しており、画像のローダ=Susieプラグインしか知らなかったのでSusieプラグインを使用しました。また、4Kモニタに関しては今恥ずかしながら無職なのでそんな予算はありません…
> MFC

> OS: Windows 10 Home 22H2
> 開発環境: Visual studio 2019

とか、もしかして 32bit 環境なのか ?
Windows 11でAndoroid エミュレータ(LD Player)が何故か動かないのでWindows 10 Homeを使用してます。
また、32bitではなく64bitです。

C#のことでこちらに質問するかもしれませんがそのときはどうぞ宜しくお願い致します。
ボールを違うところに投げてたらご指摘して頂けると嬉しいです(o_ _)o

返信

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