C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]: カラーパレット任意の座標に表示する [1]


(過去ログ 136 を表示中)

[トピック内 22 記事 (21 - 22 表示)]  << 0 | 1 >>

■79957 / inTopicNo.21)  Re[13]: カラーパレット任意の座標に表示する
  
□投稿者/ kazu (13回)-(2016/06/01(Wed) 11:37:00)
No79951 (魔界の仮面弁士 さん) に返信
> ■No79947 (とっちゃん さん) に返信

お世話になっております。
昨日、なぜだかサイトにアクセスできなかったので、お返事が遅くなりました。
こちらで、いろいろと検証をしていった結果をまとめます。

手前の仕様はユーザーコントロールでPictureBoxを継承し、ユーザーコントロールにイベント足していた事を忘れていました。
現在、起こる現象としてピクチャーボックスをクリックまたはマウスムーブし、カラーパレット表示ボタンを押下するとカラーパレットがfromの裏に行き、フリーズしているように見える。というものです。
alt + tabを押せば表に出て来て表示されます。

ユーザーコントロールには4つイベントを加えており、PaintEventHandler,MouseEventHandler(アップ、ダウン、ムーブ)それぞれあります。
最初に4つのメソッドをコメントアウトして、アプリケーションを起動したところ、ピクチャーボックスをクリックした後にカラーパレットを表示するボタンを押下したら正常に期待通り表示されました。
そこで、ひとつづずメソッドをコメントオン、オフして行ったところ、マウスムーブイベントが原因だと判明しました。

以下切り分けした事

1 マウスムーブイベント全てをコメントアウト
ピクチャーボックスをクリックしてカラーボックス表示ボタンを押下
期待の場所にカラーボックスが表示される
ただし、penや消しゴムでの描画ができなくなってしまう。
(本末転倒)

2 マウスムーブイベント左クリック内の座標取得部分をコメントアウト
ピクチャーボックスをクリックしてカラーボックス表示ボタンを押下
カラーパレットがFromの後ろに行く Alt +Tabで表示可能
ペンや消しゴムを使えない上に表示もできない。
3 マウスムーブイベントのrefresh()部分だけをコメントアウト
ピクチャーボックスをクリックしてカラーボックス表示ボタンを押下
期待の場所にカラーボックスが表示される
ただし、penや消しゴムでの描画ができなくなってしまう。
(本末転倒)

切り分け結果
開始点と終了点の間にrefresh()をしているのですが、このrefresh()が原因でカラーパレットが表示されない(Fromの後ろに行く) 事が判明しました。
しかし、refreshしないとpenや消しゴムが使えなくなるので
ためしにApplication.DoEvents(); をstripBtn_Click直後に置いてみましたが、結果はカラーパレット表示ボタンを押下後はすぐに表示されず、一度、PictureBoxをクリックしないとカラーパレットは表示されませんでした。
ステップ実行をすると、カラーパレットボタン押下後にすぐDoEventに入るのですが、そこで処理が止まり、pictureBoxをクリックするとその後の処理が行われるという物でした。



以上が昨日までにやった事でしたが、まだ解決には至りませんでした。。
お忙しいところお手数ですが、なにとぞご教授をよろしくお願いします。



実際のコード
private const float INIT_POINT = 99999.9f;
/// 開始:X座標、Y座標
private PointF _st = new PointF(INIT_POINT, INIT_POINT);
/// 終了:X座標、Y座標
private PointF _ed = new PointF(INIT_POINT, INIT_POINT);
//画像取り込み用ビットマップ
public Bitmap bmp;

ボタン押下処理
private void stripBtn_Click(object sender, EventArgs e) {
Application.DoEvents(); 追加しました
// PictureBox の左上隅にダイアログボックスの座標を合わせて表示する
using(var dlg = new ColorDialogEx())
{
Point p = this.PointToScreen(new Point(PictureBox.Left + 20, PictureBox.Top + 30));
dlg.Position = p;
dlg.AllowFullOpen = false;
if (dlg.ShowDialog(this) == DialogResult.OK)
this.StripSelectColorBtn.BackColor = dlg.Color;
}
}

//マウスムーブイベント
private void MouseMove(object sender, MouseEventArgs e) {
// 左クリック押下中
if (e.Button == MouseButtons.Left) {
// ZOOM率に合わせたサイズを取得
SizeF size = this.getZoomSize();
//// コントロール側の座標値と描画用BITMAP座標値の計算:終点
this._ed.X = e.X - (((float)this.ClientSize.Width - size.Width) / 2);
this._ed.X = this._ed.X * ((float)this.bmp.Width / size.Width);
this._ed.Y = e.Y - (((float)this.ClientSize.Height - size.Height) / 2);
this._ed.Y = this._ed.Y * ((float)this.bmp.Height / size.Height);
//// 再描画
this.Refresh();
//// コントロール側の座標値と描画用BITMAP座標値の計算:始点
this._st.X = e.X - (((float)this.ClientSize.Width - size.Width) / 2);
this._st.X = this._st.X * ((float)this.bmp.Width / size.Width);
this._st.Y = e.Y - (((float)this.ClientSize.Height - size.Height) / 2);
this._st.Y = this._st.Y * ((float)this.bmp.Height / size.Height);
}
}

//画面サイズの取得
public SizeF getZoomSize() {
float img_w = this.bmp.Width;
float img_h = this.bmp.Height;
float pic_w = this.ClientSize.Width;
float pic_h = this.ClientSize.Height;

float mag_w = pic_w / img_w;
float mag_h = pic_h / img_h;
SizeF zoomSize;

if (mag_w < mag_h) {
zoomSize = new SizeF(img_w * mag_w, img_h * mag_w);
}
else {
zoomSize = new SizeF(img_w * mag_h, img_h * mag_h);
}

return zoomSize;
}

別クラス
internal class ColorDialogEx : ColorDialog {
private Point FPosition;
public Point Position { set { FPosition = value; } }

public ColorDialogEx()
: base() {
}

protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) {
if (msg == 0x110) { // WM_INITDIALOG{
RECT r = new RECT();

// ダイアログボックスの位置とサイズを取得する
GetWindowRect(hWnd, ref r);

// ダイアログボックスの位置を変更する
MoveWindow(hWnd, FPosition.X, FPosition.Y, r.right - r.left, r.bottom - r.top, true);

return IntPtr.Zero; // HookProc メソッドでメッセージを処理済みにする
}

// WM_INIDIALOG 以外のメッセージに対しては元のコントロールにまかせる
return base.HookProc(hWnd, msg, wparam, lparam);
}

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool GetWindowRect(IntPtr hWnd, [In, Out] ref RECT lpRect);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool MoveWindow(IntPtr hWnd, int X, int Y,
int nWidth, int nHeight, bool bRepaint);

[StructLayout(LayoutKind.Sequential)]
private struct RECT {
public int left;
public int top;
public int right;
public int bottom;
}
引用返信 編集キー/
■79991 / inTopicNo.22)  Re[14]: カラーパレット任意の座標に表示する
□投稿者/ 魔界の仮面弁士 (740回)-(2016/06/03(Fri) 10:51:54)
No79957 (kazu さん) に返信
> 以下切り分けした事

form → from な誤記はさておき、
かなり条件が絞り込めて来ましたね。


ちなみに下記は .NET でもないですし、OS も CE 系ではありますが、
WM_INITDIALOG が呼び出されなかったケースのようです。
https://teratail.com/questions/10754




> 手前の仕様はユーザーコントロールでPictureBoxを継承し、
これは、どちらの意味でしょうか?

(1) PictureBox を継承したカスタムコントロールを作り、それを利用している。
(2) UserControl に PictureBox を貼ったユーザーコントロールを作り、それを利用している。


また、標準の PictureBox をそのままフォームに貼って
同じような処理を行わせた場合、やはり問題が生じますか?


penや消しゴムというのが何を意味するのかはさておき、とりあえず
継承していない、素の PictureBox で試していているのですが、
今回御提示頂いたコードだけでは、やはり現象を確認できませんでした。


> 実際のコード
これらが、切り分けを行った後の「問題点を再現させるためのコード」に
なっているかどうか、改めて確認してみてください。

すなわち、kazu さん自身で新規にプロジェクトを作成してみて、
そこに掲示板に記載頂いたコードだけを貼ってみた上で、
その状態で現象を再現できるのかどうか調べておいて欲しい、ということです。

もし、掲示板にあるコードを貼るだけでは再現できない場合、
掲示板に記載していない部分のコードに問題があることになりますので、
第三者が問題箇所を特定できなくなってしまいます。



また、繰り返しのお願いになりますが、実行している Windows のバージョン、
Visual Studio のバージョン、.NET Framewrok のバージョンを
それぞれ明らかにしていただけますでしょうか。
環境依存の問題である可能性を切り分けるためにも、情報提供をお願いします。


> //画像取り込み用ビットマップ
> public Bitmap bmp;
このインスタンスはどのタイミングで生成され、
どのタイミングで Dispose されるのでしょうか?


> stripBtn_Click
これは、Form 上に貼られた System.Windows.Forms.Button でしょうか?


> this.StripSelectColorBtn.BackColor = dlg.Color;
これは、上記とは別のボタンのようですね。


> Application.DoEvents(); 追加しました
追加した場合と追加しなかった場合とで、結果はどのように異なりますか?
引用返信 編集キー/

<前の20件
トピック内ページ移動 / << 0 | 1 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -