お世話になっております。
再度、質問させてください。
現在、お絵かきソフトの様なプログラムを作成しております。
カラーパレット表示ボタンを押下時にカラーパレットを任意の座標に表示させるという動作はサイトを参考にして実現できたのですが、pictureBoxをクリックした後にカラーパレットの標示させるボタンを押すと画面がフリーズしてしまいます。カラーパレットのボタン部分はToolStripを使用しています。
※追記部分
分かった事。
1、dlg.ShowDialog()の時に引数としてtopmostのFromを入れていない事が原因でした。
2、pictureBoxをクリックした後にカラーパレット表示用ボタン押下時にカラーパレットが表示されない。
手前のプログラムはユーザーコントロールでPictureBoxを継承しており、自作でマウスムーブイベントを作っています。
dlg.ShowDialog(this)にする事によりpictureBoxをクリックしたあとalt + Tabを押下し再度アプリケーションに戻れば、カラーパレットは表示されるようになりました。
しかし、やりたい事はカラーパレットボタンを押下した時にfromの最前に表示される事です。
そこでユーザーコントロール(PictureBox)のイベントを一度すべて消しpictureBoxをクリックまたはムーブ後、カラーパレットボタンを押下したら
期待通りにカラーパレットが表示されました。
切り分けにより、マウスムーブイベントでカラーパレットがFromの後ろに行くということが判明。
以下、マウスムーブイベントの切り分けした結果を記載します。
マウスムーブイベントがしている事
pictureBoxのbitmapのZoomサイズの取得
マウスの開始点の座標を取得
refreshで再描画
マウスの終了点の座標を取得
切り分け
1 マウスムーブイベント全てをコメントアウト
ピクチャーボックスをクリックしてカラーボックス表示ボタンを押下
期待の場所にカラーボックスが表示される
ただし、penや消しゴムでの描画ができなくなってしまう。
(本末転倒)
2 マウスムーブイベント左クリック内の座標取得部分をコメントアウト
ピクチャーボックスをクリックしてカラーボックス表示ボタンを押下
カラーパレットがFromの後ろに行く Alt +Tabで表示可能
ペンや消しゴムを使えない上に表示もできない。
3 マウスムーブイベントのrefresh()部分だけをコメントアウト
ピクチャーボックスをクリックしてカラーボックス表示ボタンを押下
期待の場所にカラーボックスが表示される
ただし、penや消しゴムでの描画ができなくなってしまう。
(本末転倒)
切り分け結果
開始点と終了点の間にrefresh()をしているのですが、このrefresh()が原因でカラーパレットが表示されない(Fromの後ろに行く) 事が判明しました。
聞きたい事
なぜrefreshをすることによりカラーパレットがfromの後ろに行くのか。
ペンや消しゴムを使えた上でカラーパレットも表示できるようにするにはどうすればよいでしょうか?
マウスムーブイベントで取得した開始点と終了点を元にペンモードや消しゴムを描画しているのでなくてはならない機能だと考えております。
お手数ですが、ご教授よろしくお願い足します。
実際のコード
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;
ボタン押下処理
ColorDialogEx dlg = new ColorDialogEx();
private void StripColorBtn_Click(object sender, EventArgs e) {
// OekakiPaint の左上隅にダイアログボックスの座標を合わせて表示する
Point p = this.PointToScreen(new Point(OekakiPaint.Left + 20, OekakiPaint.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; }
