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

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

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

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

Q&A

1回答

5376閲覧

C#でウィンドウを最背面にして移動したい

cancat

総合スコア313

C#

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

0グッド

0クリップ

投稿2017/09/30 00:25

編集2022/01/12 10:55

こんにちは。
Windows10でWindows Formのアプリケーションを開発しています。
Visual Studio 2017 Communityを使っています。

###前提・実現したいこと
いつも見る必要のないウィンドウをサブのディスプレイに移動したいです。表示はしておきたいけれど、いつも見る必要はないので、ウィンドウを最背面にしたいです。
セカンダリディスプレイは、DisplayLinkを使って、USBから出力しています。

###試したこと
下記コードを実行すると、
・WindowBack()を実行すると、ウィンドウ位置がメインウィンドウに移動します。ウィンドウは最背面になります。最背面なのはいいけれどウィンドウ位置がいまいち。
・WindowBack()をコメントアウトして実行しないと、ウィンドウ位置はセカンダリウィンドウに配置できます。ウィンドウは最背面にできません。ウィンドウ位置はいいけど最背面でないので邪魔なことがあります。

ここからは推測です。
WindowBack()を実行したときにウィンドウ位置がメインウィンドウに移動する理由は、ウィンドウの親としてProgram Managerをさがしているためです。
とすると、DisplayLinkで表示しているウィンドウのウィンドウハンドルは、Program Managerではないのかもしれません。そうだとすれば、DisplayLinkのウィンドウのハンドルを探して、それを親にすれば、サブウィンドウに最背面で表示できることになります。
そこで質問。

DisplayLinkで表示しているウィンドウのウィンドウハンドルの名前を知りたいです。
あるいは、もしこの推測が違っているのであれば、違っているところをご指摘いただけるとうれしいです。さらに、

いつも見る必要のないウィンドウをサブのディスプレイに移動したいです。表示はしておきたいけれど、いつも見る必要はないので、ウィンドウを最背面にしたいです。

という目的を達成できるコードを教えていただけるとうれしいです。

###発生している問題・エラーメッセージ
DisplayLinkを使ったサブウィンドウに、ウィンドウを最背面にして移動できない。

###該当のソースコード

C#

1private void Form1_Load(object sender, EventArgs e) { 2 var windowgoback = new windowBack.WindowBack(); 3 windowgoback.windowBack(this.Handle); 4 5 this.Location = new Point(4000, 100); 6}

C#

1using System; 2using System.Runtime.InteropServices; 3 4namespace windowBack { 5 public class WindowBack { 6 [DllImport("USER32.DLL", CharSet = CharSet.Auto)] 7 private static extern System.IntPtr FindWindow( 8 string lpClassName, 9 string lpWindowName 10 ); 11 12 [DllImport("USER32.DLL", CharSet = CharSet.Auto)] 13 private static extern System.IntPtr SetParent( 14 System.IntPtr hWndChild, 15 System.IntPtr hWndNewParent 16 ); 17 18 public void windowBack(IntPtr Handle) { 19 System.IntPtr hProgramManagerHandle = FindWindow(null, "Program Manager"); 20 21 if (!hProgramManagerHandle.Equals(System.IntPtr.Zero)) 22 SetParent(Handle, hProgramManagerHandle); 23 } 24 } 25}

###補足情報(言語/FW/ツール等のバージョンなど)
Microsoft Visual Studio Community 2017
Version 15.0.26228.9 D15RTWSVC
Microsoft .NET Framework
Version 4.6.01586

です。
よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ウィンドウを最背面に持っていくには、SetParentを使うのでなく、SetWindowPosを使ってください。
SetWindowPos

サブのディスプレイにウィンドを移動するには、以下を参照してください。
指定したモニターにフォームを表示する

この二つを組み合わせれば、お望みの動作が実現できると思います。


追記

SetWindowPosのHWND_BOTTOMの値は、1です。

uFlagsは、SWP_NOSIZE(値としては1)とSWP_NOMOVE(値としては2)のOR、すなわち3を渡してください。

以下を参考にしてください。

SetWindowPos (user32)


追記2

常に最背面にしたいということであれば、以下のコードで実現できます。

C#

1 public partial class Form1 : Form 2 { 3 private const int WM_WINDOWPOSCHANGING = 0x0046; 4 private IntPtr HWND_BOTTOM = (IntPtr)1; 5 6 [StructLayout(LayoutKind.Sequential)] 7 public struct WINDOWPOS 8 { 9 public IntPtr hwnd; 10 public IntPtr hwndInsertAfter; 11 public int x; 12 public int y; 13 public int cx; 14 public int cy; 15 public uint flags; 16 } 17 18 public Form1() 19 { 20 InitializeComponent(); 21 } 22 23 protected override void WndProc(ref Message m) 24 { 25 switch (m.Msg) 26 { 27 case WM_WINDOWPOSCHANGING: 28 WINDOWPOS wp = (WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(WINDOWPOS)); 29 wp.hwndInsertAfter = HWND_BOTTOM; 30 Marshal.StructureToPtr(wp, m.LParam, true); 31 break; 32 } 33 base.WndProc(ref m); 34 } 35 } 36

投稿2017/10/03 04:22

編集2017/10/11 06:18
Harahira

総合スコア243

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

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

cancat

2017/10/03 06:46

ありがとうございます。夜に試します!
cancat

2017/10/03 11:44

すみません。C#だとHWND_BOTTOMはどう指定すればよいですか? [DllImport("USER32.DLL", CharSet = CharSet.Auto)] private static extern bool SetWindowPos( System.IntPtr hWnd, // ウィンドウのハンドル System.IntPtr hWndInsertAfter, // 配置順序のハンドル int X, // 横方向の位置 int Y, // 縦方向の位置 int cx, // 幅 int cy, // 高さ uint uFlags // ウィンドウ位置のオプション ); public void SetWindowBack(IntPtr Handle, int X, int Y, int width, int height) { SetWindowPos(Handle, HWND_BOTTOM, X, Y, width, height, 0); }
cancat

2017/10/03 13:43

ありがとうございます。 下記の通りですが、残念ながら、最背面にはなりませんでした。 windowgoback.SetWindowBack(this.Handle, this.Location.X, this.Location.Y, this.Width, this.Height); public void SetWindowBack(IntPtr Handle, int X, int Y, int width, int height) { SetWindowPos(Handle, (System.IntPtr)1, X, Y, width, height, 3); }
Harahira

2017/10/04 02:05

以下のコードで、最背面に移動することは確認してます。 public partial class Form1 : Form { [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { SetWindowPos(this.Handle, (IntPtr)1, 0, 0, 0, 0, 3); } } なにか、それ以外に原因があるのでは?
YAmaGNZ

2017/10/04 09:16

質問者さんが求めているのは、一時的なZオーダーの移動ではなく 常に最背面(TOPMOSTの逆)なのでは? Program Managerの子にするというのも検索で出てきますしね 当方には質問者さんの環境が作れないので分かりませんが、もし質問者さんの 推測していることが原因なのであれば、SPY++等で調べてみてはいいのでは?
cancat

2017/10/10 07:43

コメントありがとうございます。 そうです。常に最背面にしたいです。TOPMOSTの逆です。 SPY++だと何を探せばよさそうでしょうね?
cancat

2017/10/11 06:24

ありがとうございます。また夜に試します!!
cancat

2017/10/11 11:28

残念。最背面にはなりませんでした。背面にもなりませんでした。別のウィンドウの上に表示しています。
Harahira

2017/10/11 11:57

私の環境では、提示したコードで最背面に固定されることを確認しています。おかしいですね。なにが違うのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問