且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

WPF - 从模态窗口中删除系统菜单图标,但不是主应用程序窗口

更新时间:2021-10-18 15:25:41

WS_EX_DLGMODALFRAME 仅在WPF窗口的本机Win32窗口没有与之关联的图标时删除图标。 WPF(方便地)使用应用程序的图标作为所有窗口的默认图标,而没有明确设置的图标。通常情况下,这不会导致任何问题,并且可以省去在每个窗口上手动设置应用程序图标的麻烦。但是,当我们尝试删除图标时,它会给我们带来问题。

I had this same problem. It appears that WS_EX_DLGMODALFRAME only removes the icon when the WPF window's native Win32 window does not have an icon associated with it. WPF (conveniently) uses the application's icon as the default icon for all windows without an explicitly set icon. Normally, that doesn't cause any problems and saves us the trouble of manually setting the application's icon on each window; however, it causes a problem for us when we try to remove the icon.

由于问题是WPF自动为我们设置了窗口的图标,我们可以发送 WM_SETICON 到Win32窗口重置它的图标我们是应用 WS_EX_DLGMODALFRAME

Since the problem is that WPF automatically sets the window's icon for us, we can send WM_SETICON to the Win32 window to reset its icon when we are applying WS_EX_DLGMODALFRAME.

const int WM_SETICON = 0x0080;
const int ICON_SMALL = 0;
const int ICON_BIG = 1;

[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr SendMessage(
    IntPtr hWnd, 
    int msg,
    IntPtr wParam, 
    IntPtr lParam);

删除图标的代码:

IntPtr hWnd = new WindowInteropHelper(window).Handle;
int currentStyle = NativeMethods.GetWindowLongPtr(hWnd, GWL_EXSTYLE);

SetWindowLongPtr(
    hWnd,
    GWL_EXSTYLE,
    currentStyle | WS_EX_DLGMODALFRAME);

// reset the icon, both calls important
SendMessage(hWnd, WM_SETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
SendMessage(hWnd, WM_SETICON, (IntPtr)ICON_BIG, IntPtr.Zero);

SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, 
    SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);

编辑:哦,看起来这只适用于app在Visual Studio中运行外部

Oh, and it looks like this works only when the app is run outside of Visual Studio.