- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用以下代码将窗口挂接到面板:
SetParent(win, pnlApp.Handle);
SetWindowLong(win, GWL_STYLE, WS_VISIBLE);
MoveWindow(win, 0, 0, pnlApp.Width, pnlApp.Height, true);
其中 win
是窗口句柄,作为 IntPtr
。这里想想记事本,它会很好地挂接到一个面板上。
但是,当我尝试使用以下代码释放(解除 Hook )时:
SetParent(win, (IntPtr)0);
显示时没有窗口框架!我的意思是它会再次释放到桌面,但它没有任何窗口框架。
如何解决这个问题?
最佳答案
关于问题中的代码:
SetWindowLong()应替换为 SetWindowLongPtr() - 查看文档中的警告。后者在调用代码需要时调用前者。
您需要调用GetWindowLongPtr()获取当前窗口样式,然后根据需要添加或删除样式;存储原始值:它将用于恢复以前的状态。
► 在示例中,删除了 WS_SYSMENU
样式,因此窗口不会显示系统菜单和通常位于标题中的所有按钮。这只是一个例子,看看它是如何工作的(它可能不是对所有 Windows 都有效)。
SetParent()返回前一个父级的句柄。存储这个值,无论它是什么,都需要将窗口恢复到它以前的所有者。如果 Window 是顶级 Window,则之前的 Parent 似乎 是 Desktop,因此您期望 IntPtr.Zero
。也可能不是,你可以获得一个不是IntPtr.Zero
的Handle。只需存储返回值,看看那是什么,如果你有兴趣:)
你应该检查 GetWindowLongPtr()
和 SetWindowLongPtr()
的返回值:如果它是 0
,那么有一个错误。您可以使用 Marshal.GetLastWin32Error()获取错误代码。请注意 SetWindowLongPtr()
不会清除错误代码,因此您必须自己清除它,调用 SetLastError(0) .
您可以使用 MoveWindow()将 Windows 重新定位在新父级的边界内;我建议打电话SetWindowPos()相反,您有更多选择。请参阅此处的代码。
免责声明:请记住 Raymond Chen 的博文中的内容:
Is it legal to have a cross-process parent/child or owner/owned window relationship
换句话说,这是一个只是因为你问的事情:)
设置这些字段(或任何合适的字段):
windowdHwnd
是要重新父级oldParent
为上一个Parent的Handle,由SetParent()
oldStyles
将存储以前的窗口样式,由 GetWWindowLongPtr()
IntPtr windowdHwnd = IntPtr.Zero;
IntPtr oldParent = (IntPtr)(-1);
int oldStyles = 0;
// [...]
当您拥有您关心的窗口的句柄时,将 windowdHwnd
设置为此值。之后调用此代码(它可以是一个方法,传递窗口句柄和将成为新父级的容器控件 - 此处是一个名为 somePanel
的控件)。
// Already parented, resets the previous styles, clean up and return
if (windowdHwnd != IntPtr.Zero && oldParent != (IntPtr)(-1)) {
NativeMethods.SetParent(windowdHwnd, oldParent);
NativeMethods.SetWindowLongPtr(windowdHwnd, NativeMethods.GWL_Flags.GWL_STYLE, new IntPtr(oldStyles));
windowdHwnd = IntPtr.Zero;
oldParent = (IntPtr)(-1);
return;
}
// Store the existing Styles, to restore when the Window is dismissed
oldStyles = NativeMethods.GetWindowLongPtr(windowdHwnd, NativeMethods.GWL_Flags.GWL_STYLE);
if (oldStyles == IntPtr.Zero) {
int error = Marshal.GetLastWin32Error(); // Show the error code or throw an exception
return;
}
// Removes the System Menu from the Window: it will also remove the Buttons from the Caption
int newStyle = oldStyles.ToInt32()^ (int)NativeMethods.WinStyles.WS_SYSMENU;
NativeMethods.SetLastError(0);
// Sets the new Styles
IntPtr result = NativeMethods.SetWindowLongPtr(windowdHwnd, NativeMethods.GWL_Flags.GWL_STYLE, (IntPtr)newStyle);
if (result == IntPtr.Zero) {
int error = Marshal.GetLastWin32Error(); // Show the error code or throw an exception
return;
}
oldParent = NativeMethods.SetParent(windowdHwnd, somePanel.Handle);
// Repositions the Window and shows it, if needed
var flags = NativeMethods.SWP_Flags.SWP_ASYNCWINDOWPOS | NativeMethods.SWP_Flags.SWP_SHOWWINDOW;
NativeMethods.SetWindowPos(windowdHwnd, IntPtr.Zero, 0, 0, somePanel.Width, somePanel.Height, flags);
你可以写(这只是删除):
int newStyle = oldStyles &~(int)NativeMethods.WinStyles.WS_SYSMENU;
而不是(这会打开/关闭):
int newStyle = oldStyles ^ (int)NativeMethods.WinStyles.WS_SYSMENU;
NativeMethods
类:
using System.Runtime.InteropServices;
public class NativeMethods
{
[Flags]
public enum SWP_Flags : uint
{
/// <summary>Retains the current size (ignores the cx and cy parameters).</summary>
SWP_NOSIZE = 0x0001,
/// <summary>Retains the current position (ignores X and Y parameters).</summary>
SWP_NOMOVE = 0x0002,
/// <summary>Retains the current Z order (ignores the hWndInsertAfter parameter).</summary>
SWP_NOZORDER = 0x0004,
/// <summary>Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to
/// the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent
/// window uncovered as a result of the window being moved. When this flag is set, the application must
/// explicitly invalidate or redraw any parts of the window and parent window that need redrawing.</summary>
SWP_NOREDRAW = 0x0008,
/// <summary>Does not activate the window. If this flag is not set, the window is activated and moved to the
/// top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter
/// parameter).</summary>
SWP_NOACTIVATE = 0x0010,
/// <summary>Draws a frame (defined in the window's class description) around the window.</summary>
SWP_DRAWFRAME = 0x0020,
/// <summary>Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to
/// the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE
/// is sent only when the window's size is being changed.</summary>
SWP_FRAMECHANGED = 0x0020,
/// <summary>Displays the window.</summary>
SWP_SHOWWINDOW = 0x0040,
/// <summary>Hides the window.</summary>
SWP_HIDEWINDOW = 0x0080,
/// <summary>Discards the entire contents of the client area. If this flag is not specified, the valid
/// contents of the client area are saved and copied back into the client area after the window is sized or
/// repositioned.</summary>
SWP_NOCOPYBITS = 0x0100,
/// <summary>Does not change the owner window's position in the Z order.</summary>
SWP_NOOWNERZORDER = 0x0200,
/// <summary>Same as the SWP_NOOWNERZORDER flag.</summary>
SWP_NOREPOSITION = 0x0200,
/// <summary>Prevents the window from receiving the WM_WINDOWPOSCHANGING message.</summary>
SWP_NOSENDCHANGING = 0x0400,
/// <summary>Internal use.</summary>
SWP_NOCLIENTSIZE = 0x0800,
/// <summary>Internal use.</summary>
SWP_NOCLIENTMOVE = 0x1000,
/// <summary>Prevents generation of the WM_SYNCPAINT message.</summary>
SWP_DEFERERASE = 0x2000,
/// <summary>If the calling thread and the thread that owns the window are attached to different input queues,
/// the system posts the request to the thread that owns the window. This prevents the calling thread from
/// blocking its execution while other threads process the request.</summary>
SWP_ASYNCWINDOWPOS = 0x4000
}
[Flags]
public enum WinStyles : uint
{
WS_BORDER = 0x00800000, //The window has a thin-line border.
WS_CAPTION = 0x00C00000, //The window has a title bar (includes the WS_BORDER style).
WS_CHILD = 0x40000000, //The window is a child window. A window with this style cannot have a menu bar. This style cannot be used with the WS_POPUP style.
WS_CHILDWINDOW = 0x40000000, //Same as the WS_CHILD style.
WS_CLIPCHILDREN = 0x02000000, //Excludes the area occupied by child windows when drawing occurs within the parent window. This style is used when creating the parent window.
WS_CLIPSIBLINGS = 0x04000000, //Clips child windows relative to each other; that is, when a particular child window receives a WM_PAINT message, the WS_CLIPSIBLINGS style clips all other overlapping child windows out of the region of the child window to be updated. If WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible, when drawing within the client area of a child window, to draw within the client area of a neighboring child window.
WS_DISABLED = 0x08000000, //The window is initially disabled. A disabled window cannot receive input from the user. To change this after a window has been created, use the EnableWindow function.
WS_DLGFRAME = 0x00400000, //The window has a border of a style typically used with dialog boxes. A window with this style cannot have a title bar.
WS_GROUP = 0x00020000, //The window is the first control of a group of controls. The group consists of this first control and all controls defined after it, up to the next control with the WS_GROUP style. The first control in each group usually has the WS_TABSTOP style so that the user can move from group to group. The user can subsequently change the keyboard focus from one control in the group to the next control in the group by using the direction keys.
//You can turn this style on and off to change dialog box navigation. To change this style after a window has been created, use the SetWindowLong function.
WS_HSCROLL = 0x00100000, //The window has a horizontal scroll bar.
WS_ICONIC = 0x20000000, //The window is initially minimized. Same as the WS_MINIMIZE style.
WS_MAXIMIZE = 0x01000000, //The window is initially maximized.
WS_MAXIMIZEBOX = 0x00010000, //The window has a maximize button. Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified.
WS_MINIMIZE = 0x20000000, //The window is initially minimized. Same as the WS_ICONIC style.
WS_MINIMIZEBOX = 0x00020000, //The window has a minimize button. Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified.
WS_OVERLAPPED = 0x00000000, //The window is an overlapped window. An overlapped window has a title bar and a border. Same as the WS_TILED style.
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | //The window is an overlapped window. Same as the WS_TILEDWINDOW style.
WS_CAPTION |
WS_SYSMENU |
WS_THICKFRAME |
WS_MINIMIZEBOX |
WS_MAXIMIZEBOX,
WS_POPUP = 0x80000000, //The windows is a pop-up window. This style cannot be used with the WS_CHILD style.
WS_POPUPWINDOW = WS_POPUP | //The window is a pop-up window. The WS_CAPTION and WS_POPUPWINDOW styles must be combined to make the window menu visible.
WS_BORDER |
WS_SYSMENU,
WS_SIZEBOX = 0x00040000, //The window has a sizing border. Same as the WS_THICKFRAME style.
WS_SYSMENU = 0x00080000, //The window has a window menu on its title bar. The WS_CAPTION style must also be specified.
WS_TABSTOP = 0x00010000, //The window is a control that can receive the keyboard focus when the user presses the TAB key. Pressing the TAB key changes the keyboard focus to the next control with the WS_TABSTOP style.
//You can turn this style on and off to change dialog box navigation. To change this style after a window has been created, use the SetWindowLong function. For user-created windows and modeless dialogs to work with tab stops, alter the message loop to call the IsDialogMessage function.
WS_THICKFRAME = 0x00040000, //The window has a sizing border. Same as the WS_SIZEBOX style.
WS_TILED = 0x00000000, //The window is an overlapped window. An overlapped window has a title bar and a border. Same as the WS_OVERLAPPED style.
WS_TILEDWINDOW = WS_OVERLAPPED | //The window is an overlapped window. Same as the WS_OVERLAPPEDWINDOW style.
WS_CAPTION |
WS_SYSMENU |
WS_THICKFRAME |
WS_MINIMIZEBOX |
WS_MAXIMIZEBOX,
WS_VISIBLE = 0x10000000, //The window is initially visible. This style can be turned on and off by using the ShowWindow or SetWindowPos function.
WS_VSCROLL = 0x00200000, //The window has a vertical scroll bar.
}
public enum GWL_Flags : int
{
GWL_USERDATA = -21,
GWL_EXSTYLE = -20,
GWL_STYLE = -16,
GWL_ID = -12,
GWLP_HWNDPARENT = -8,
GWLP_HINSTANCE = -6,
GWL_WNDPROC = -4,
DWLP_MSGRESULT = 0x0,
DWLP_DLGPROC = 0x4,
DWLP_USER = 0x8
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr GetWindowLongPtr(IntPtr hWnd, GWL_Flags nIndex);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr SetWindowLongPtr(IntPtr hWnd, GWL_Flags nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SWP_Flags uFlags);
[DllImport("kernel32.dll")]
internal static extern void SetLastError(uint dwErrCode);
}
关于c# - 将窗口解除 Hook 到其原始状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65842979/
https://github.com/mattdiamond/Recorderjs/blob/master/recorder.js中的代码 我不明白 JavaScript 语法,比如 (functio
在 iOS 7 及更早版本中,如果我们想在应用程序中找到 topMostWindow,我们通常使用以下代码行 [[[UIApplication sharedApplication] windows]
我已经尝试解决这个问题很长一段时间了:我无法访问窗口的 url,因为它位于另一个域上..有一些解决方案吗? function login() { var cb = window.ope
是否可以将 FFMPEG 视频流传递到 C# 窗口?现在它在新窗口中作为新进程打开,我只是想将它传递给我自己的 SessionWindow。 此时我像这样执行ffplay: public void E
我有一个名为 x 的矩阵看起来像这样: pTime Close 1 1275087600 1.2268 2 1275264000 1.2264 3 1275264300 1.2
在编译时,发生搜索,grep搜索等,Emacs会在单独的窗口中创建一个新的缓冲区来显示结果,有没有自动跳转到那个窗口的方法?这很有用,因为我可以使用 n 和 p 而不是 M-g n 和 M-g p 移
我有一个启动 PowerShell 脚本的批处理文件。 批处理文件: START Powershell -executionpolicy RemoteSigned -noexit -file "MyS
我有一个基于菜单栏的应用程序,单击图标时会显示一个窗口。在 Mac OS X Lion 上一切正常,但由于某种原因,在 Snow Leopard 和早期版本的 Mac OS X 上会出现错误。任何时候
在 macOS 中,如何在 Xcode 和/或 Interface Builder 中创建带有“集成标题栏和工具栏”的窗口? 这是“宽标题栏”类型的窗口,已添加到 OS X 10.10 Yosemit
在浏览器 (Chrome) 中 JavaScript: var DataModler = { Data: { Something: 'value' }, Process: functi
我有 3 个 html 页面。第 1 页链接到第 2 页,第 2 页链接到第 3 页(为了简单起见)。 我希望页面 2 中的链接打开页面 3 并关闭页面 1(选项卡 1)。 据我了解,您无法使用 Ja
当点击“创建节点”按钮时,如何打开一个新的框架或窗口?我希望新框架包含一个文本字段和下拉菜单,以便用户可以选择一个选项。 Create node Search node
我有一个用户控件,用于编辑应用程序中的某些对象。 我最近遇到一个实例,我想弹出一个新的对话框(窗口)来托管此用户控件。 如何实例化新窗口并将需要设置的任何属性从窗口传递到用户控件? 感谢您的宝贵时间。
我有一个Observable,它发出许多对象,我想使用window或buffer操作对这些对象进行分组。但是,我不想指定count参数来确定窗口中应包含多少个对象,而是希望能够使用自定义条件。 例如,
我有以下代码,它打开一个新的 JavaFX 阶段(我们称之为窗口)。 openAlertBox.setOnAction(e -> { AlertBox alert = AlertBox
我要添加一个“在新窗口中打开”上下文菜单项,该菜单项将以新的UIScene打开我的应用程序文档之一。当然,我只想在实际上支持多个场景的设备上显示该菜单项。 目前,我只是在检查设备是否是使用旧设备的iP
我正在尝试创建一个 AIR 应用程序来记录应用程序的使用情况,使用 AIR 从系统获取信息的唯一简单方法是使用命令行工具和抓取 标准输出 . 我知道像 这样的工具顶部 和 ps 对于 OS X,但它们
所以我有这个简单的 turtle 螺旋制作器,我想知道是否有一种方法可以打印出由该程序创建的我的设计副本。 代码: import turtle x= float(input("Angle: ")) y
我正在编写一个 C# WPF 程序,它将文本消息发送到另一个程序的窗口。我有一个宏程序作为我的键盘驱动程序 (Logitech g15) 的一部分,它已经这样做了,尽管它不会将击键直接发送到进程,而是
我尝试使用以下代码通过 UDP 发送,但得到了奇怪的结果。 if((sendto(newSocket, sendBuf, totalLength, 0, (SOCKADDR *)&sendAd
我是一名优秀的程序员,十分优秀!