如何在WPF HwndHost中更改窗口的背景?

时间:2014-07-18 15:14:42

标签: wpf interop hwndhost

我在WPF应用程序中创建了一个从HwndHost派生的控件。 HwndHost派生控件位于UserControl内。

我希望能够设置在HwndHost内创建的窗口的背景颜色(默认情况下它是白色的,我希望它是黑色的)。最简单的方法是什么?

1 个答案:

答案 0 :(得分:1)

我在更改HwndHost的背景颜色时遇到了同样的问题,我在StackOverflow上发现了这个问题:

Registering a custom win32 window class from c#

我已修改它将背景颜色更改为黑色,它看起来像这样:

public class CustomWindow : IDisposable
{
   #region Constants

   private const int ERROR_CLASS_ALREADY_EXISTS = 1410;

   #endregion

   #region Fields

   private bool m_disposed;

   private IntPtr m_hwnd;

   private WndProc m_wnd_proc_delegate;

   #endregion

   #region Constructors and Destructors

   /// <summary>
   /// Initializes a new instance of the <see cref="CustomWindow"/> class.
   /// </summary>
   /// <param name="class_name">The class_name.</param>
   /// <exception cref="System.Exception">
   /// class_name is null
   /// or
   /// class_name is empty
   /// or
   /// Could not register window class
   /// </exception>
   public CustomWindow(string class_name)
   {
      if (class_name == null)
      {
         throw new Exception("class_name is null");
      }
      if (class_name == String.Empty)
      {
         throw new Exception("class_name is empty");
      }

      this.m_wnd_proc_delegate = CustomWndProc;

      // Create WNDCLASS
      var wind_class = new WNDCLASS();
      wind_class.lpszClassName = class_name;
      wind_class.lpfnWndProc =  
          Marshal.GetFunctionPointerForDelegate(this.m_wnd_proc_delegate);
      wind_class.hbrBackground = CreateSolidBrush(0);

      var class_atom = RegisterClassW(ref wind_class);

      var last_error = Marshal.GetLastWin32Error();

      if (class_atom == 0 && last_error != ERROR_CLASS_ALREADY_EXISTS)
      {
         throw new Exception("Could not register window class");
      }

      // Create window
      this.m_hwnd = CreateWindowExW(
        0,
        class_name,
        String.Empty,
        0,
        0,
        0,
        0,
        0,
        IntPtr.Zero,
        IntPtr.Zero,
        IntPtr.Zero,
        IntPtr.Zero);
  }

  #endregion

  /// <summary>
  /// Creates the solid brush.
  /// </summary>
  /// <param name="theColor">The color.</param>
  /// <returns>IntPtr.</returns>
  [DllImport("gdi32.dll", EntryPoint = "CreateSolidBrush", CharSet =   CharSet.Unicode)]
  internal static extern IntPtr CreateSolidBrush(uint theColor);

  /// <summary>
  /// Gets the black window.
  /// </summary>
  /// <value>The black window.</value>
  public IntPtr BlackWindow 
  { 
      get
      {
         return this.m_hwnd;
      }
  }

  #region Delegates

  private delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

  #endregion

  #region Public Methods and Operators

  /// <summary>
  /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  /// </summary>
  public void Dispose()
  {
     this.Dispose(true);
     GC.SuppressFinalize(this);
  }

  #endregion

  #region Methods

  [DllImport("user32.dll", SetLastError = true)]
  private static extern IntPtr CreateWindowExW(
    UInt32 dwExStyle,
    [MarshalAs(UnmanagedType.LPWStr)] string lpClassName,
    [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName,
    UInt32 dwStyle,
    Int32 x,
    Int32 y,
    Int32 nWidth,
    Int32 nHeight,
    IntPtr hWndParent,
    IntPtr hMenu,
    IntPtr hInstance,
    IntPtr lpParam);

  private static IntPtr CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
  {
     return DefWindowProcW(hWnd, msg, wParam, lParam);
  }

  [DllImport("user32.dll", SetLastError = true)]
  private static extern IntPtr DefWindowProcW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

  [DllImport("user32.dll", SetLastError = true)]
  private static extern bool DestroyWindow(IntPtr hWnd);

  [DllImport("user32.dll", SetLastError = true)]
  private static extern UInt16 RegisterClassW([In] ref WNDCLASS lpWndClass);

  /// <summary>
  /// Releases unmanaged and - optionally - managed resources.
  /// </summary>
  /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
  private void Dispose(bool disposing)
  {
      if (!this.m_disposed)
      {
         if (disposing)
         {
            // Dispose managed resources
         }

         // Dispose unmanaged resources
         if (this.m_hwnd != IntPtr.Zero)
         {
            DestroyWindow(this.m_hwnd);
            this.m_hwnd = IntPtr.Zero;
         }
         this.m_disposed = true;
      }
  }

  #endregion

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  private struct WNDCLASS
  {
     public readonly uint style;

     public IntPtr lpfnWndProc;

     public readonly int cbClsExtra;

     public readonly int cbWndExtra;

     public readonly IntPtr hInstance;

     public readonly IntPtr hIcon;

     public readonly IntPtr hCursor;

     public IntPtr hbrBackground;

     [MarshalAs(UnmanagedType.LPWStr)]
     public readonly string lpszMenuName;

     [MarshalAs(UnmanagedType.LPWStr)]
     public string lpszClassName;
  }
}

然后我使用了CustomWindow创建的窗口和HwndHost中的父窗口。