回答編集履歴

2 リンク修正

sheephuman

sheephuman score 46

2017/06/18 22:53  投稿

冒頭のコードを改造しようとして、
```C#
       [DllImport("USER32.DLL", EntryPoint = "FindWindowEx")]
       private static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);
       [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
       static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
       [System.Runtime.InteropServices.DllImport("user32.dll")]
       static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
     
       private void button1_Click_1(object sender, EventArgs e)
       {
           IntPtr WinHandle = FindWindow("SHELLDLL", "Program Manager");
           if (WinHandle != null)
           {
               SetParent(this.Handle, WinHandle);
           }
       }
       private void button2_Click(object sender, EventArgs e)
       {
           IntPtr hWnd;
        hWnd = FindWindow("SHELLDELL_DefView", "Program Manager");
           hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SHELLDLL_DefView", null);
        //  hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SysListView32", null);
           if (hWnd != null && hWnd != IntPtr.Zero)
           {
               SetParent(this.Handle, hWnd);
           }
           // hDt = FindWindowEx(hDt, IntPtr.Zero, "SHELLDLL_DefView", null);
           ////↑この"SHELLDLL_DefView"がキモ。このクラス名が入っていな //いと、Program Managerだろうと何だろうとデスクトップウィンドウを取得できない。
           //if (hDt != null && hDt != IntPtr.Zero)
           //{
           //   SetParent(this.Handle, hDt);
           //}
       }
   }
}
```
などとしてみましたが、一向に動作せず諦めました。
確実なやり方はShellDLL_DefViewを持っているProgram Managerを、Win32APIを利用して列挙させるという方法になるようです。こんなややこしい方法をとらずに直接setParent出来たらと思ったのですが・・・・。
解決方法
```C#
 public delegate bool EnumWindowCallBack(IntPtr hwnd, IntPtr lParam);
       [DllImport("USER32.DLL", EntryPoint = "FindWindowEx")]
       private static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);
       // SetParent 関数
       [DllImport("USER32.DLL", CharSet = CharSet.Auto)]
       private static extern System.IntPtr SetParent(
           System.IntPtr hWndChild,
           System.IntPtr hWndNewParent
       );
       [DllImport("USER32.Dll")]
       static extern int EnumWindows(EnumWindowCallBack x, IntPtr y);
       [DllImport("User32.Dll", CharSet = CharSet.Unicode)]
       public static extern int GetClassName(IntPtr hWnd, StringBuilder s, int nMaxCount);
    // ウィンドウを列挙するためのコールバックメソッド
       private bool EnumerateWindow(IntPtr hWnd, IntPtr lParam)
       {
           StringBuilder sbClassName = new StringBuilder(256);
           int result = GetClassName(hWnd, sbClassName, 256);
           string className = sbClassName.ToString();
           if (className.Equals("WorkerW") || className.Equals("Progman"))
           {
               IntPtr hDt = FindWindowEx(hWnd, IntPtr.Zero, "SHELLDLL_DefView", null);
              //↑この"SHELLDLL_DefView"がキモ。このクラス名が入っていな //いと、Program Managerだろうと何だろうとデスクトップウィンドウを取得できない。
               if (hDt != null && hDt != IntPtr.Zero)
               {
                   SetParent(this.Handle, hDt);
               }
           }
           return true;
       }
private void button1_Click_1(object sender, EventArgs e)
       {
           EnumWindows(EnumerateWindow, IntPtr.Zero);
       }
```
まとめ記事。[
http://mojakouinfotaker.blog.fc2.com/blog-entry-867.html]( http://mojakouinfotaker.blog.fc2.com/blog-entry-867.html)
[まとめ記事]( http://mojakouinfotaker.blog.fc2.com/blog-entry-867.html)
1 解決方法を追記

sheephuman

sheephuman score 46

2016/11/08 23:15  投稿

冒頭のコードを改造しようとして、
```C#
       [DllImport("USER32.DLL", EntryPoint = "FindWindowEx")]
       private static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);
       [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
       static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
       [System.Runtime.InteropServices.DllImport("user32.dll")]
       static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
     
       private void button1_Click_1(object sender, EventArgs e)
       {
           IntPtr WinHandle = FindWindow("SHELLDLL", "Program Manager");
           if (WinHandle != null)
           {
               SetParent(this.Handle, WinHandle);
           }
       }
       private void button2_Click(object sender, EventArgs e)
       {
           IntPtr hWnd;
        hWnd = FindWindow("SHELLDELL_DefView", "Program Manager");
           hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SHELLDLL_DefView", null);
        //  hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SysListView32", null);
           if (hWnd != null && hWnd != IntPtr.Zero)
           {
               SetParent(this.Handle, hWnd);
           }
           // hDt = FindWindowEx(hDt, IntPtr.Zero, "SHELLDLL_DefView", null);
           ////↑この"SHELLDLL_DefView"がキモ。このクラス名が入っていな //いと、Program Managerだろうと何だろうとデスクトップウィンドウを取得できない。
           //if (hDt != null && hDt != IntPtr.Zero)
           //{
           //   SetParent(this.Handle, hDt);
           //}
       }
   }
}
```
などとしてみましたが、一向に動作せず諦めました。
確実なやり方はShellDLL_DefViewを持っているProgram Managerを、Win32APIを利用して列挙させるという方法になるようです。こんなややこしい方法をとらずに直接setParent出来たらと思ったのですが・・・・。
解決方法  
 
```C#  
 public delegate bool EnumWindowCallBack(IntPtr hwnd, IntPtr lParam);  
 
       [DllImport("USER32.DLL", EntryPoint = "FindWindowEx")]  
       private static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);  
 
       // SetParent 関数  
       [DllImport("USER32.DLL", CharSet = CharSet.Auto)]  
       private static extern System.IntPtr SetParent(  
           System.IntPtr hWndChild,  
           System.IntPtr hWndNewParent  
       );  
 
       [DllImport("USER32.Dll")]  
       static extern int EnumWindows(EnumWindowCallBack x, IntPtr y);  
 
       [DllImport("User32.Dll", CharSet = CharSet.Unicode)]  
       public static extern int GetClassName(IntPtr hWnd, StringBuilder s, int nMaxCount);  
 
 
 
    // ウィンドウを列挙するためのコールバックメソッド  
       private bool EnumerateWindow(IntPtr hWnd, IntPtr lParam)  
       {  
           StringBuilder sbClassName = new StringBuilder(256);  
           int result = GetClassName(hWnd, sbClassName, 256);  
           string className = sbClassName.ToString();  
           if (className.Equals("WorkerW") || className.Equals("Progman"))  
           {  
               IntPtr hDt = FindWindowEx(hWnd, IntPtr.Zero, "SHELLDLL_DefView", null);  
              //↑この"SHELLDLL_DefView"がキモ。このクラス名が入っていな //いと、Program Managerだろうと何だろうとデスクトップウィンドウを取得できない。  
               if (hDt != null && hDt != IntPtr.Zero)  
               {  
                   SetParent(this.Handle, hDt);  
               }  
           }  
           return true;  
       }  
 
 
private void button1_Click_1(object sender, EventArgs e)  
       {  
           EnumWindows(EnumerateWindow, IntPtr.Zero);  
       }  
 
 
```  
 
 
 
まとめ記事。[
http://mojakouinfotaker.blog.fc2.com/blog-entry-867.html]( http://mojakouinfotaker.blog.fc2.com/blog-entry-867.html)

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る