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

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

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

消えないフォーム

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

■92410 / inTopicNo.1)  消えないフォーム
  
□投稿者/ 犬夜叉 (10回)-(2019/09/24(Tue) 08:53:27)

分類:[.NET 全般] 

環境です。

Windwos10
VisualStudio2017
C#


ボタン1つを装備しtForm1を作ります。
private void button1_Click(object sender, EventArgs e)
{
 From2 frm = new From2();
 frm.Show();
}

Form2を作ります。
public From2()
{
 InitializeComponent();
}

private void From2_Load(object sender, EventArgs e)
{
 this.Capture = true;
}

private void From2_MouseDown(object sender, MouseEventArgs e)
{
 if(!GetWindowContainState(this)) this.Close();
}

private bool GetWindowContainState(Control ctrl)
{
 Rectangle rect = GetWindowRectangle(ctrl);
 Point mouseScreenPos = Control.MousePosition;
 Point mouseClientPos = ctrl.PointToClient(mouseScreenPos);
 return rect.Contains(mouseClientPos);
}

private Rectangle GetWindowRectangle(Control ctrl)
{
 Debug.Assert(ctrl.Bounds.Location == ctrl.Location);
 Debug.Assert(ctrl.Location == new Point(ctrl.Left, ctrl.Top));
 Debug.Assert(ctrl.Bounds.Size == ctrl.Size);
 Debug.Assert(ctrl.Size == new Size(ctrl.Right - ctrl.Left, ctrl.Bottom - ctrl.Top));

 if (ctrl is Form)
 {
  Point winRectLocation = ctrl.PointToClient(ctrl.Bounds.Location);
  Rectangle winRect = new Rectangle(winRectLocation, ctrl.Bounds.Size);
  return winRect;
 }
 else
 {
  Point screenLocation = ctrl.Parent.PointToScreen(ctrl.Bounds.Location);
  Point winRectLocation = ctrl.PointToClient(screenLocation);
  Rectangle winRect = new Rectangle(winRectLocation, ctrl.Bounds.Size);
  return winRect;
 }
}

この状態で実行しForm1を表示し、Form1のボタンを押してForm2を表示させます。
その状態でFomr2以外の場所をクリックするとForm2は消えるのですが、
Form2をクリックすると、消えなくなります。
Form2以外をクリックするとForm2が消えるようにするにはどうすればよいのでしょうか?


引用返信 編集キー/
■92414 / inTopicNo.2)  Re[1]: 消えないフォーム
□投稿者/ 魔界の仮面弁士 (2386回)-(2019/09/24(Tue) 09:54:17)
2019/09/24(Tue) 10:37:43 編集(投稿者)

No92410 (犬夜叉 さん) に返信
> Form2を作ります。
> public From2()

ありがちなミスですね。
From / Form とか Namae / Name とか Expect / Except とか Drag / Drug とか…。


> その状態でFomr2以外の場所をクリックすると

こっちのスペルミスは珍しいかも。(^^;


> private void From2_Load(object sender, EventArgs e)
> {
>  this.Capture = true;
> }

こんなことをしたら、Form2 上に TextBox があっても、
その上にマウスを重ねても「I カーソル」になりませんよね。

Form2 上のコントロールを選択する場合も、
1 回目のクリックが捨てられてしまい、2 回目のクリックで
ようやくアクティブになる状態となり、操作性が悪くなりそうですが…。


> Form2をクリックすると、消えなくなります。

最初のクリックで消えないのは、
 GetWindowContainState(this)
で領域内かどうかを判定しているからですね。
常に消したいなら、領域判定せずに Close(); すれば消えます。

領域内であれ領域外であれ、一度クリックすれば、キャプチャーは終了するので、
それ以降はもう、領域外操作では MouseDown イベントは発生しません。
再 Capture するなどしない限りは。


> Form2以外をクリックするとForm2が消えるようにするにはどうすればよいのでしょうか?

RawInput を捉えるとか。

// Install-Package SharpDX.RawInput

あるいはマウスクリックに拘らないなら、Deactivate イベントで。

public partial class Form2 : Form
{
 public Form2()
 {
  InitializeComponent();
 }
 private void Form2_Load(object sender, EventArgs e)
 {
  Deactivate += delegate { Close(); };
 }
}
引用返信 編集キー/
■92415 / inTopicNo.3)  Re[2]: 消えないフォーム
□投稿者/ 犬夜叉 (13回)-(2019/09/24(Tue) 10:32:59)
No92414 (魔界の仮面弁士 さん) に返信

> RawInput を捉えるとか。

RawInput ってなんですか?
どうやって使うのでしょうか?
引用返信 編集キー/
■92418 / inTopicNo.4)  Re[3]: 消えないフォーム
□投稿者/ 魔界の仮面弁士 (2389回)-(2019/09/24(Tue) 12:16:32)
No92415 (犬夜叉 さん) に返信
>> RawInput を捉えるとか。
> RawInput ってなんですか?

DirectX の機能で、入力デバイスから得られる情報を直接受け取るものです。
自アプリがアクティブではない状態で、キーボードやマウス等の入力を受け取る場合にも使えます。


> どうやって使うのでしょうか?
メニューに [ツール]-[NuGet パッケージ マネージャー] がありませんか?

もしあれば、[ソリューションの NuGet パッケージの管理] ダイアログで
[参照] タブで「SharpDX.RawInput」と検索して、自プロジェクトにインストールすれば
参照設定が行われます。

もしくは、パッケージ マネージャ コンソールにて
 Install-Package SharpDX.RawInput
のコマンドを入力する方法でも OK です。

https://www.nuget.org/packages/SharpDX.RawInput/


たとえばこんな感じ。


using SharpDX.RawInput;
using SharpDX.Multimedia;
public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
  }

  private void Form1_Load(object sender, EventArgs e)
  {
    // 自フォーム外のマウス操作も捉える
    Device.RegisterDevice(UsagePage.Generic, UsageId.GenericMouse, DeviceFlags.InputSink, Handle);
    Device.MouseInput += Device_MouseInput;
  }

  private void Device_MouseInput(object sender, MouseInputEventArgs e)
  {
    // こちらはカーソルの絶対座標
    label1.Text = Cursor.Position.ToString();

    // こちらはマウスの相対的な動作
    // (1px 未満の微細な動きも捉えられるが、絶対座標は得られない)
    var sb = new StringBuilder();
    sb.AppendFormat("OffsetXY=({0}, {1})", e.X, e.Y);
    if(e.WheelDelta !=0)
    {
      sb.AppendFormat(", Wheel={0}", e.WheelDelta);
    }
    if (e.ButtonFlags != MouseButtonFlags.None)
    {
      sb.AppendFormat(", Button={0}", e.ButtonFlags);
    }
    listBox1.Items.Insert(0, sb.ToString());

    // 左ボタンが押された時に、フォーム外の座標だったらフォームを閉じる
    if (e.ButtonFlags == MouseButtonFlags.LeftButtonDown)
    {
      if(!IsDisposed && !GetWindowContainState(this))
      {
        Close();
      }
    }
  }
}
引用返信 編集キー/
■92419 / inTopicNo.5)  Re[4]: 消えないフォーム
□投稿者/ 犬夜叉 (14回)-(2019/09/24(Tue) 13:11:03)
No92418 (魔界の仮面弁士 さん) に返信

.Net4.0 環境下では使えないようなのですが。
引用返信 編集キー/
■92420 / inTopicNo.6)  Re[5]: 消えないフォーム
□投稿者/ 魔界の仮面弁士 (2390回)-(2019/09/24(Tue) 13:33:20)
No92419 (犬夜叉 さん) に返信
> .Net4.0 環境下では使えないようなのですが。

.NET Framework 4 で開発されているとは、どこにも書かれていなかったような…?

とりあえず当方では、ターゲット フレームワークを「.NET Framework 4」にした上で、
先の「非アクティブ時に閉じる」手法と、「SharpDX.RawInput で判定して閉じる手法」の
いずれの手法も動作することを確認できました。


そちらの環境では、どちらの方法とも駄目だったのでしょうか?
それとも RawInput の方だけが NG だったのでしょうか?


ちなみに SharpDX.RawInput バージョン 4.2.0 には、
 \net40\SharpDX.dll
 \net45\SharpDX.dll
の 2 種類が存在しますので、参照先のパスが正しいかも確認してみてください。
(その依存関係にある SharpDX バージョン 4.2.0 にも、フレームワーク別にアセンブリがあります)
引用返信 編集キー/
■92421 / inTopicNo.7)  Re[4]: 消えないフォーム
□投稿者/ 魔界の仮面弁士 (2391回)-(2019/09/24(Tue) 14:44:27)
No92418 (魔界の仮面弁士) に追記
> if(!IsDisposed && !GetWindowContainState(this))
> {
>   Close();
> }

上記の GetWindowContainState は、犬夜叉さんが書かれたものを
そのまま利用していますが、座標判定部分は自作メソッドを呼ばずに、
 if (!IsDisposed && !DesktopBounds.Contains(Cursor.Position))
だけでも良さそうです。


ところで、Form2 の座標に重なるように、別のウィンドウが(TopMost 状態などで)存在していた場合、
その別ウィンドウをクリックした時に、Form2 は Close されるべきなのでしょうか?


(1) クリック座標が Form2 の領域内だったのであれば、別ウィンドウをクリックしても、Form2 を Close させたくない。
(2) 別ウィンドウをクリックしたのなら、現在座標は無関係で、常に Form2 を Close したい。


もしも (1) を求めるのなら、RawInput の座標判定の方が良いでしょうし、
(2) を求めるなら、非アクティブ時(Deactivate イベントまたは OnDeactivate メソッド)に
Close させる方が良いと思います。要件によっては、両者併用というパターンもあるかも知れません。
引用返信 編集キー/
■92422 / inTopicNo.8)  Re[5]: 消えないフォーム
□投稿者/ 犬夜叉 (15回)-(2019/09/24(Tue) 15:40:19)
2019/09/24(Tue) 15:42:04 編集(投稿者)

No92421 (魔界の仮面弁士 さん) に返信

開発環境では .Net 4.5.2 を使用しています。
properties の設定は以下の通り変更しています。

@ターゲットフレームワーク 4
Aプラットフォームターゲット x86

これをリビルドしたのですが
以下の警告が表示され実行されませんでした。
RawInputを4.0用にすることができるのでしょうか?


警告 プライマリ参照 "SharpDX.RawInput, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL" は、".NETFramework,Version=v4.5" フレームワークに対して作成されたアセンブリ "SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1" に間接的に依存するため、解決できませんでした。これは現在ターゲットされているフレームワーク ".NETFramework,Version=v4.0" よりも新しいバージョンです。 WindowsFormsApp2

引用返信 編集キー/
■92423 / inTopicNo.9)  Re[6]: 消えないフォーム
□投稿者/ 魔界の仮面弁士 (2392回)-(2019/09/24(Tue) 15:56:16)
No92422 (犬夜叉 さん) に返信
> これをリビルドしたのですが
> 以下の警告が表示され実行されませんでした。
> RawInputを4.0用にすることができるのでしょうか?

NuGet 後に、ターゲット フレームワーク を変更したのではないでしょうか。
だとしたら、リビルドしただけでは依存関係が解決されません。

NuGet 管理画面から該当するライブラリを一度アンインストールし、
[ビルド]-[クリーン] 作業を行ってから、もう一度 NuGet をやりなおしてみてください。
引用返信 編集キー/
■92424 / inTopicNo.10)  Re[7]: 消えないフォーム
□投稿者/ 犬夜叉 (16回)-(2019/09/24(Tue) 16:07:06)
No92423 (魔界の仮面弁士 さん) に返信
アンインストール
ビルドクリーン
インストール
ビルド

しましたが、実行されませんでした。
表示されるのは以下の警告だけです。
でもフォームが表示されません。

警告 プライマリ参照 "SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL" は、".NETFramework,Version=v4.5" フレームワークに対して作成されているため、解決できませんでした。これは現在ターゲットされているフレームワーク ".NETFramework,Version=v4.0" よりも新しいバージョンです。

警告 プライマリ参照 "SharpDX.RawInput, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL" は、".NETFramework,Version=v4.5" フレームワークに対して作成されたアセンブリ "SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1" に間接的に依存するため、解決できませんでした。これは現在ターゲットされているフレームワーク ".NETFramework,Version=v4.0" よりも新しいバージョンです。

警告 一部の NuGet パッケージが現在のターゲット フレームワークとは異なるターゲット フレームワークを使用してインストールされていて、再インストールが必要になる可能性があります。詳細については、http://docs.nuget.org/docs/workflows/reinstalling-packages を参照してください。影響を受けるパッケージ: SharpDX
引用返信 編集キー/
■92425 / inTopicNo.11)  Re[8]: 消えないフォーム
□投稿者/ 犬夜叉 (17回)-(2019/09/24(Tue) 16:17:01)
No92423 (魔界の仮面弁士 さん) に返信

すみませんでした。
SharpDX.RawInput だけでなく
SharpDx もアンインストールしないといけなかったようです。

2つアンインストールして、
SharpDX.RawInput をインストールすると自動的に
SharpDx もインストールされ
ビルドできるようになりました。


引用返信 編集キー/
■92426 / inTopicNo.12)  Re[8]: 消えないフォーム
□投稿者/ 魔界の仮面弁士 (2393回)-(2019/09/24(Tue) 16:22:26)
No92424 (犬夜叉 さん) に返信
> 表示されるのは以下の警告だけです。
> でもフォームが表示されません。

(1) SharpDX.RawInput をアンインストールします。

(2) 続いて、SharpDX をアンインストールします。

(3) ソリューション エクスプローラーで、[WindowsFormsApp2] の
 プロジェクト(≠ソリューションではなく)を右クリックし、
 [クリーン]を選択します。

(4) [WindowsFormsApp2] - [参照] の配下に、SharpDX と SharpDX.RawInput が
 存在していないことを確認します。

(5) [WindowsFormsApp2] - [Properties] をダブルクリックし、
 [アプリケーション] タブの ターゲット フレームワークが
 「.NET Framework 4」になっていることを確認します。

(6) 念のため、ソリューションを一度閉じてから、再度開きなおします。(多分不要だけど)

(7) NuGet パッケージ マネージャーから、SharpDX.RawInput 4.2.0 をインストールします。
 このとき、出力ウィンドウの 出力元: [パッケージマネージャー] には、
 このようなメッセージが出力されるはずです。


'.NETFramework,Version=v4.0' を対象とするプロジェクト 'WindowsFormsApp2' に関して、パッケージ 'SharpDX.RawInput.4.2.0' の依存関係情報の収集を試行しています
〜〜〜中略〜〜〜
パッケージ 'SharpDX.RawInput.4.2.0' を 'packages.config' に追加しました
'SharpDX.RawInput 4.2.0' が WindowsFormsApp2に正常にインストールされました


(8) [WindowsFormsApp2] の下にある packages.config は、下記の内容になっているはずです。

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SharpDX" version="4.2.0" targetFramework="net40" />
<package id="SharpDX.RawInput" version="4.2.0" targetFramework="net40" />
</packages>


(9) [WindowsFormsApp2] - [参照] にある、SharpDX.RawInput を選択してプロパティを見ると、
「パス」欄にあるファイル名は、下記のように net40 フォルダー内のものを指しているはずです。


C:\〜〜〜\WindowsFormsApp2\packages\SharpDX.RawInput.4.2.0\lib\net40\SharpDX.RawInput.dll


(10) 同様に、SharpDX も net40 側が参照されていることを確認し、
プロジェクトをビルド・実行します。これで当方では問題なく動作しています。
引用返信 編集キー/
■92429 / inTopicNo.13)  Re[9]: 消えないフォーム
□投稿者/ 犬夜叉 (19回)-(2019/09/25(Wed) 16:34:46)
No92425 (犬夜叉 さん) に返信

できました。
ありがとうございました。



解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ