質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

7850閲覧

C#WPFでウインドウを追従させたい

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2016/05/01 07:29

現在デスクトップマスコットを制作しているのですが、ウィンドウAの上にウインドウBを表示し、それらを追従させる方法はないのでしょうか?
イメージ説明

mercurian-teto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

以下のような処理を一定間隔(20ミリ秒程度)で繰り返し実行することで追従できます。
一定間隔の繰り返し処理は、DispatcherTimerクラス(System.Windows.Threading)でできます。

  1. 追従したいウィンドウAのウィンドウハンドルを取得する

私も昔似たようなものを作ったことがありまして、フォアグラウンドウィンドウに追従するようにしていました。Windows APIのGetForegroundWindow関数で、呼び出し時点でフォアグラウンド(操作対象)になっているウィンドウのハンドルを取得できます。
あらかじめ決まったウィンドウに追従させたい場合は、その仕様によって方法が変わりますが、とにかくウィンドウハンドルさえ取得すれば2の処理ができます。

  1. 1で取得したウィンドウハンドルを使って、ウィンドウAの位置情報を取得する

Windows APIのGetWindowRect関数で取得できます。

  1. ウィンドウBの座標をウィンドウAの上になるように設定する

MainWindowのLeftプロパティとTopプロパティがウィンドウのX座標とY座標になります。移動させたい座標を計算してそれを設定すればウィンドウの位置を変更できます。

サンプルコード

C#

1using System.Windows.Threading; 2using System.Runtime.InteropServices; 3using System.Windows.Interop; 4 : 5 : 6 7// MainWindowの中 8 9private DispatcherTimer dispatcherTimer = new DispatcherTimer(); 10private IntPtr hwndThis; 11 12private void Window_Loaded(object sender, RoutedEventArgs e) 13{ 14 dispatcherTimer.Interval = new TimeSpan(200000); // 100ナノ秒単位で指定 15 dispatcherTimer.Tick += dispatcherTimer_Tick; 16 dispatcherTimer.Start(); 17 18 // Windowクラスのプロパティにウィンドウハンドルがないので取得して覚えておく 19 var hwndSource = HwndSource.FromVisual(this) as HwndSource; 20 hwndThis = hwndSource.Handle; 21} 22 23private void dispatcherTimer_Tick(object sender, EventArgs e) 24{ 25 IntPtr hwnd = GetForegroundWindow(); 26 if(hwnd == hwndThis) // 自分自身への追従はしない 27 return; 28 29 RECT rect = new RECT(); 30 GetWindowRect(hwnd, ref rect); 31 this.Left = rect.left; 32 this.Top = rect.top - this.Height; 33} 34 35[DllImport("user32.dll")] 36private static extern IntPtr GetForegroundWindow(); 37 38struct RECT 39{ 40 public int left; 41 public int top; 42 public int right; 43 public int bottom; 44} 45 46[DllImport("user32.dll")] 47[return: MarshalAs(UnmanagedType.Bool)] 48private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

補足
位置だけ変えても別のウィンドウに隠れる可能性があるため、Windowの共通でTopmostにチェックを入れると(Topmost="True")常に見えるようになります。


追記
自身がフォアグラウンドしたときにどこかに行ってしまわないようにサンプルコードを修正しました。参照するアセンブリにSystem.Windowsを追加してください。

投稿2016/05/01 14:09

編集2016/05/02 06:45
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/05/02 06:00

ありがとうございます。ですがこれthis.Close();で閉じようとすると閉じれずにどこかに行ってしまうんですが…
catsforepaw

2016/05/02 06:42

ウィンドウBをクリックするとかしてフォアグラウンドにすると、自分自身に追従しようとしてどこかに行ってしまいますね。サンプルコードは原理を説明するためのものなので、除外判定とか一切考慮していませんでした。 取得したウィンドウハンドルが自分自身だった場合は追従しないようにすれば良いかと思います。サンプルコードを修正版に差し替えておきます。
退会済みユーザー

退会済みユーザー

2016/05/02 08:13

おおお!できました!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問