- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
在 Windows Explorer 和 Internet Explorer 等应用程序中,您可以捕获标题栏下方的扩展框架区域并将窗口四处拖动。
对于 WinForms 应用程序,表单和控件尽可能接近 native Win32 API;一个人会简单地覆盖他们表单中的 WndProc()
处理程序,处理 WM_NCHITTEST
窗口消息并通过返回 来欺骗系统认为在框架区域上的点击实际上是在标题栏上的点击HTCAPTION
。我已经在我自己的 WinForms 应用程序中做到了这一点,并取得了令人愉快的效果。
在 WPF 中,我还可以实现一个类似的 WndProc()
方法,并将它挂接到我的 WPF 窗口句柄,同时将窗口框架扩展到客户区,如下所示:
// In MainWindow
// For use with window frame extensions
private IntPtr hwnd;
private HwndSource hsource;
private void Window_SourceInitialized(object sender, EventArgs e)
{
try
{
if ((hwnd = new WindowInteropHelper(this).Handle) == IntPtr.Zero)
{
throw new InvalidOperationException("Could not get window handle for the main window.");
}
hsource = HwndSource.FromHwnd(hwnd);
hsource.AddHook(WndProc);
AdjustWindowFrame();
}
catch (InvalidOperationException)
{
FallbackPaint();
}
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case DwmApiInterop.WM_NCHITTEST:
handled = true;
return new IntPtr(DwmApiInterop.HTCAPTION);
default:
return IntPtr.Zero;
}
}
问题是,由于我盲目地设置 handled = true
并返回 HTCAPTION
,点击任何地方但窗口图标或控制按钮导致窗口被拖动。也就是说,下面以红色突出显示的所有内容都会导致拖动。这甚至包括窗口两侧(非客户区)的调整大小 handle 。我的 WPF 控件(即文本框和选项卡控件)也因此停止接收点击:
我想要的只是为了
可拖动。也就是说,我只希望这些红色区域是可拖动的(客户区+标题栏):
我如何修改我的 WndProc()
方法和我窗口的 XAML/代码隐藏的其余部分,以确定哪些区域应该返回 HTCAPTION
哪些区域不应该?我正在考虑使用 Point
来检查我的控件位置的点击位置,但我不确定如何在 WPF 土地上进行。
编辑 [4/24]: 一种简单的方法是让一个不可见的控件,甚至是窗口本身,通过调用 来响应
(参见 Ross's answer)。问题是由于某些原因 MouseLeftButtonDown
窗口上的 DragMove()DragMove()
在窗口最大化时不起作用,因此它不能很好地与 Windows 7 Aero Snap 配合使用。由于我要进行 Windows 7 集成,因此在我的情况下这不是一个可接受的解决方案。
最佳答案
感谢我今天早上收到的一封电子邮件,提示我制作一个工作示例应用程序来演示这一功能。我现在已经这样做了;您可以在 GitHub (或在 now-archived CodePlex )中找到它。只需克隆存储库或下载并提取存档,然后在 Visual Studio 中打开它,然后构建并运行它。
完整的应用程序整体上是 MIT 许可的,但您可能会将其拆开并将其代码的一部分放在您自己的周围,而不是完整地使用应用程序代码——并不是许可阻止您这样做任何一个。此外,虽然我知道应用程序主窗口的设计与上面的线框并不相似,但这个想法与问题中提出的是一样的。
希望这对某些人有帮助!
我终于解决了。感谢 Jeffrey L Whitledge 为我指明了正确的方向! 他的回答被接受了,因为如果不是这样我就无法找到解决方案。 编辑 [9/8]: 这个回答现在被接受了,因为它更完全的;我给了 Jeffrey 一笔可观的赏金,以感谢他的帮助。
为了后代,我是这样做的(引用 Jeffrey 的相关回答):
Get the location of the mouse click (from the wParam, lParam maybe?), and use it to create a
Point
(possibly with some kind of coordinate transformation?).
此信息可以从WM_NCHITTEST
消息的lParam
中获取。光标的x坐标是它的低位词,光标的y坐标是它的高位词,如MSDN describes。
由于坐标是相对于整个屏幕的,我需要在我的窗口上调用 Visual.PointFromScreen()
以将坐标转换为相对于窗口空间。
Then call the static method
VisualTreeHelper.HitTest(Visual,Point)
passing itthis
and thePoint
that you just made. The return value will indicate the control with the highest Z-Order.
我必须传入顶级 Grid
控件而不是 this
作为视觉对象来测试该点。同样,我必须检查结果是否为空,而不是检查它是否是窗口。如果它为空,则光标没有击中网格的任何子控件——换句话说,它击中了未占用的窗口框架区域。无论如何,关键是使用 VisualTreeHelper.HitTest()
方法。
现在,话虽如此,如果您按照我的步骤进行操作,则有两个注意事项可能适用于您:
如果您不覆盖整个窗口,而只是部分扩展窗口框架,则必须在未被窗口框架填充的矩形上放置一个控件作为客户区填充物。
在我的例子中,我的选项卡控件的内容区域正好适合该矩形区域,如图所示。在您的应用程序中,您可能需要放置一个 Rectangle
形状或一个 Panel
控件并为其涂上适当的颜色。这样控件就会被命中。
这个关于客户区填充物的问题会导致下一个问题:
如果您的网格或其他顶级控件在扩展窗口框架上有背景纹理或渐变,整个网格区域将响应点击,即使在任何完全透明的区域上也是如此背景(见 Hit Testing in the Visual Layer )。在这种情况下,您需要忽略对网格本身的点击,而只关注其中的控件。
因此:
// In MainWindow
private bool IsOnExtendedFrame(int lParam)
{
int x = lParam << 16 >> 16, y = lParam >> 16;
var point = PointFromScreen(new Point(x, y));
// In XAML: <Grid x:Name="windowGrid">...</Grid>
var result = VisualTreeHelper.HitTest(windowGrid, point);
if (result != null)
{
// A control was hit - it may be the grid if it has a background
// texture or gradient over the extended window frame
return result.VisualHit == windowGrid;
}
// Nothing was hit - assume that this area is covered by frame extensions anyway
return true;
}
现在可以通过单击并拖动窗口中未被占用的区域来移动窗口。
但这还不是全部。回想一下第一个插图,包含窗口边框的非客户区也受到 HTCAPTION
的影响,因此窗口不再可调整大小。
为了解决这个问题,我必须检查光标是击中了客户区还是非客户区。为了检查这一点,我需要使用 DefWindowProc()
函数并查看它是否返回 HTCLIENT
:
// In my managed DWM API wrapper class, DwmApiInterop
public static bool IsOnClientArea(IntPtr hWnd, int uMsg, IntPtr wParam, IntPtr lParam)
{
if (uMsg == WM_NCHITTEST)
{
if (DefWindowProc(hWnd, uMsg, wParam, lParam).ToInt32() == HTCLIENT)
{
return true;
}
}
return false;
}
// In NativeMethods
[DllImport("user32.dll")]
private static extern IntPtr DefWindowProc(IntPtr hWnd, int uMsg, IntPtr wParam, IntPtr lParam);
最后,这是我最终的窗口过程方法:
// In MainWindow
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case DwmApiInterop.WM_NCHITTEST:
if (DwmApiInterop.IsOnClientArea(hwnd, msg, wParam, lParam)
&& IsOnExtendedFrame(lParam.ToInt32()))
{
handled = true;
return new IntPtr(DwmApiInterop.HTCAPTION);
}
return IntPtr.Zero;
default:
return IntPtr.Zero;
}
}
关于c# - 如何通过拖动扩展窗口框架使 WPF 窗口可移动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5493149/
我是 magento 的新手,目前我在 magento 安装期间遇到“必须加载 PHP 扩展 curl ”错误。你能帮帮我吗? 最佳答案 如果您的服务器上没有安装 curl,您可以键入以下命令之一来安
我在 macOS Mojave/macOS Big Sur/macOS Monterey/macOS Ventura 上使用最新的 php 版本 7.2 并收到类似错误 $composer requ
这个问题已经有答案了: Why generic type is not applicable for argument extends super class for both? (5 个回答) 已关
我正在使用 NightWatch.js 并进行一些 UI 测试,我想用一些额外的 desiredCapabilities 启动默认浏览器实例(即启用扩展并应用一些特定值)。 p> 注意:我可以执行这些
有人知道为什么我在 java 8 中使用此代码时没有服务器扩展名称吗: try { URL url = new URL(urlString); URLC
扩展提供给我的类(class)。为现有的类提供新功能。或扩展现有的mixin s 或虚拟类,任何东西都可以工作。 也许是这样的: class FlatButton {} // maybe no
我有一个关于使用 c 代码和 mod_wsgi 扩展 python 的问题。 我在 apache 服务器中有一个 django 应用程序,它查询 postgresql 数据库以生成报告。在某些报告中,
testcafe支持在Chrome浏览器中加载crx扩展吗? 如果是这样,请告诉我需要尝试什么方法。 我尝试了下面的代码,但没有成功 await t.eval(new Function(fs.read
这个问题已经有答案了: What is a raw type and why shouldn't we use it? (16 个回答) 已关闭 3 年前。 有什么区别: // 1 class A c
我正在编写一个 chrome 扩展来记录单击开始按钮后触发的请求。 这是我的文件:1. list .json { "manifest_version": 2, "name": "recorde
我每天都在使用 vim 和 perforce 现在我的问题是,如果我想查看 perforce 文件修订版,则从命令模式下的 vim :!p4 打印文件#1 vim 试图让我获得缓冲区 #1。有没有办法
大家好,我有一个关于 NUnit 扩展(2.5.10)的问题。 我想做的是向 数据库。为此,我使用 Event 创建了 NUnit 扩展 听众。 我遇到的问题是公共(public)无效 TestFin
我有弹出窗口,而不是模态窗口。 如何通过单击页面的其他部分(不在窗口中)来关闭此窗口? 最佳答案 像这样的东西: function closeWin(e, t) { var el = win.
我通常非常谨慎地使用扩展方法。当我确实觉得有必要编写一个扩展方法时,有时我想重载该方法。我的问题是,您对调用其他扩展方法的扩展方法有何看法?不好的做法?感觉不对,但我无法真正定义原因。 例如,第二个
扩展 Ant Ant带有一组预定义的任务,但是你可以创建自己的任务,如下面的例子所示。 定制Ant 任务应扩展 org.apache.tools.ant.Task 类,同时也应该拓展 execut
我想要一个重定向所有请求的扩展: http://website.com/foo.js 到: http://localhost/myfoo.js 我无法使用主机文件将主机从 website.com 编辑
对于为什么 QChartView 放在 QTabWidget 中时会扩展,我有点迷惑。 这是 QChartView 未展开(因为它被隐藏)时应用程序的图片。 应用程序的黑色部分是 QOpenGLWid
如果在连接条件中使用 OR 运算符,如何优化以下查询以避免 SQL 调优方面的 OR 扩展? SELECT t1.A, t2.B, t1.C, t1.D, t2.E FROM t1 LEFT J
一旦加载插件的问题得到解决(在 .NET 中通过 MEF 的情况下),下一步要解决的是与它们的通信。简单的方法是实现一个接口(interface),使用插件实现,但有时插件只需要扩展应用程序的工作方式
在我的 Symfony2 包中,我需要检查是否定义了一个函数(一个扩展)。更具体地说,如果安装了 KnpMenuBundle,我会在我的包中使用那个,否则我将自己渲染插件。 我试过了,但这当然不起作用
我是一名优秀的程序员,十分优秀!