9

我需要以编程方式和最好手动调整大于屏幕分辨率或桌面大小的窗口大小。

由于 MS-Windows XP/Vista 不允许窗口大小大于屏幕,有没有人有任何想法来解决这个限制?

我试图在笔记本电脑上制作平移效果,以便给我更多的工作空间。具有较小 LCD 尺寸的旧笔记本电脑确实具有这样的功能。

看到这个: http ://www.experts-exchange.com/OS/Microsoft_Operating_Systems/Windows/98/Q_21832063.html

4

9 回答 9

15

如果您想调整不属于您的窗口的大小(并且不使用任何类型的挂钩),您可以使用设置了 SWP_NOSENDCHANGING (0x0400) 标志的 Windows SetWindowPos API:

BOOL WINAPI SetWindowPos(
__in      HWND hWnd,
__in_opt  HWND hWndInsertAfter,
__in      int X,
__in      int Y,
__in      int cx,
__in      int cy,
__in      UINT uFlags // ** SWP_NOSENDCHANGING must be passed here **
);

这将阻止发送 WM_WINDOWPOSCHANGING 消息,这是触发 WM_GETMINMAXINFO 限制的原因。窗口的任何其他大小都会导致限制将窗口捕捉回桌面限制大小,因为将发送消息并强制执行窗口大小。

窗口大小调整器 (C#)

以下是一个小示例程序,它将记事本的大小调整为 6000x6000(将字符串“Untitled - Notepad”更改为要调整大小的窗口的标题,或者从命令行参数中获取窗口名称和所需大小)

namespace Example
{
 class Program
 {
  [DllImport("USER32.DLL")]
  public static extern IntPtr FindWindow(String className, String windowName);

  [DllImport("USER32.DLL", SetLastError = true)]
  public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int left, int top, int width, int height, uint flags);

  static void Main(string[] args)
  {
   var TOP = new IntPtr(0);
   uint SHOWWINDOW = 0x0040, NOCOPYBITS = 0x0100, NOSENDCHANGING = 0x0400;
   var hwnd = FindWindow(null, "Untitled - Notepad");
   SetWindowPos(hwnd, TOP, 0, 0, 6000, 6000, NOCOPYBITS | NOSENDCHANGING | SHOWWINDOW);
  }
 }
}

限制和警告

这种方法通常是有效的,但有许多限制可能会阻止窗口调整大小或以任何有用的方式调整大小。

安全

从 Windows Vista 开始,Microsoft 已针对窗口消息实施了越来越高的安全性。可执行文件只能与处于或低于其自身安全上下文的窗口进行交互。例如,要调整“计算机管理”窗口的大小(始终以提升的方式运行),该程序也必须以提升的方式运行。

固定窗口和布局逻辑

窗口大小可能由程序被动主动强制执行。具有强制大小的窗口被动地设置初始大小,并且简单地不向用户展示调整窗口大小的能力(例如,没有大小控制控件)。这些窗口通常可以通过发送所描述的消息来调整大小,但是由于缺少布局逻辑,除了额外的空客户区之外,不会显示任何其他内容。

具有主动强制执行功能的 Windows 通过捕获诸如 WM_SIZE 之类的 Windows 消息或更复杂的布局逻辑来监视大小。这些窗口可能会接受消息,但会在它们自己的代码中限制或限制最终大小。

在任何一种情况下,具有固定大小的 Windows 通常都缺乏任何布局逻辑来利用更大的大小,因此,即使您可以强制这样做,调整它们的大小也不会带来任何好处。

WPF

WPF 中的Window类有一个HwndSource处理发送到 WPF 窗口的窗口消息。私有方法LayoutFilterMessage捕获WM_SYSCOMMANDWM_SIZINGWM_WINDOWPOSCHANGINGWM_SIZE消息。在这种情况下,WM_SIZE消息然后由私有处理Process_WM_SIZE,实际上,绕过NOSENDCHANGING标志并更改RenderSizeWPF 客户区的标志。这是使旧版 Win32 消息适应 WPF 事件的整个过程的一部分。

最终结果是调整了 Win32主机窗口的大小(除非将 SizeToContent 设置为 SizeToContent.WidthAndHeight),但 WPF呈现区域被锁定到桌面区域,就好像没有设置 NOSENDCHANGING 标志一样。当上面的代码示例针对 WPF 应用程序运行时,您可以从任务栏中看到 Aero Peek 中的 6000x6000 窗口或 Windows-Tab 切换器中的窗口预览,但您也可以看到 WPF 内容和布局逻辑被剪辑到桌面区域。这样,WPF 窗口就像主动执行的窗口,但不是强制执行特定的大小,而是强制执行特定的最大值(对于 RenderArea)并且不考虑WM_WINDOWPOSCHANGING消息。

如果它是您自己的应用程序并且您在Windows 窗体窗口中托管 WPF (通过ElementHost),您可以调整窗口大小,并且 WPF 内容将遵循大于桌面的 Windows 窗体窗口。

其他框架

其他框架(例如 GTK 和 Qt)可能会或可能不会强制执行大小行为和限制,并且可能有各种解决方法来克服这些限制。任何给定的程序都可以忽略、重写或绕过窗口消息,并且框架可以在整个应用程序类中强制执行它,例如上面的 WPF。

有关 SetWindowPos API 的更多信息:

Process_WM_SIZE方法的参考来源HwndSource

http://referencesource.microsoft.com/#PresentationCore/Core/CSharp/System/Windows/Interop/HwndSource.cs,da4aa32ad121c1b9,references

于 2011-11-09T03:27:39.563 回答
3

C# 中的这段代码可以满足您的要求。窗口比桌面宽得多。

 protected override void WndProc(ref Message m) {
        if (m.ToString().Contains("GETMINMAXINFO")) {
            //Hent data
            MINMAXINFO obj = (MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(MINMAXINFO));
            //Endre
            if (obj.ptMaxSize.X > 0) {
                obj.ptMaxSize.X = 60000;
                obj.ptMaxSize.Y = 60000;
                obj.ptMaxTrackSize.X = 60000;
                obj.ptMaxTrackSize.Y = 60000;
                //Oppdater
                Marshal.StructureToPtr(obj, m.LParam, true);
            }
        }
        if (m.ToString().Contains("WINDOWPOSCHANGING")) {
            //Hent data
            WINDOWPOS obj = (WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(WINDOWPOS));
            //Endre
            if (obj.cx > 0) {
                obj.cx = 8000;
                //Oppdater
                Marshal.StructureToPtr(obj, m.LParam, true);
            }
        }
        //Debug.WriteLine(m.ToString());
        base.WndProc(ref m);
    }











    [StructLayout(LayoutKind.Sequential)]
    internal struct WINDOWPOS {
        internal IntPtr hwnd;
        internal IntPtr hWndInsertAfter;
        internal int x;
        internal int y;
        internal int cx;
        internal int cy;
        internal uint flags;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct MINMAXINFO {
        internal POINT ptReserverd;
        internal POINT ptMaxSize;
        internal POINT ptMaxPosition;
        internal POINT ptMinTrackSize;
        internal POINT ptMaxTrackSize;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct POINT {
        internal int X;
        internal int Y;
    }
于 2011-01-25T14:32:16.157 回答
3

您可以在 WinProc(); 中执行类似以下代码的操作;

case WM_GETMINMAXINFO:
    {
        LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam; 
        GetWindowRect(GetDesktopWindow(), &actualDesktop);
        lpmmi->ptMaxTrackSize.x = 3000;// set the value that you really need.
        lpmmi->ptMaxTrackSize.y = 3000;// set the value that you really need.
    }
    break;

应用程序可以使用此消息来覆盖窗口的默认最大化大小和位置,或者其默认的最小或最大跟踪大小。

于 2016-04-07T06:02:13.477 回答
1

窗口大小似乎取决于桌面大小,而不是屏幕分辨率;但是桌面符合分辨率。诀窍可能是更改桌面大小或从那里开始。

不久前,一位名叫 Robert Bresner(他的网站)的开发人员制作了一款名为 sDesk(可从此处下载)的产品,该产品将 Windows 扩展到了屏幕分辨率之外。

什么是 SDesk?SDesk 不是多桌面程序。它是一个程序,可以创建一个超出显示器可见区域的巨大桌面。根据 Windows 桌面设置的定义,一次只能看到 SDesk 的一部分。

SDesk 软件的原始主页存档在此处Internet 上没有当前页面(我可以找到),但此存档版本是通过缓存大量 Internet的Way Back Machine访问的。

SDesk 产品是免费软件。虽然没有包含源代码。您可以访问他的联系页面(也可以在存档版本中找到),询问是否有可用的资源或是否可以为您的研究获取资源。

于 2010-01-05T22:01:53.520 回答
1

如果您有一个可以连接多个屏幕的视频卡,另一种解决方法是设置您的系统,就好像它使用两个相邻的屏幕一样。然后,您可以将窗口大小调整为两个屏幕的大小。

于 2009-12-28T13:46:23.353 回答
1

仅列出推荐的屏幕分辨率。对于其他设置,单击选项卡Advanced上的按钮Settings,单击Adapter tab,然后单击List all Modes。选择所需的分辨率、颜色级别和刷新率。

我刚刚做了,在这里你可以在最后一点找到答案。

http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/display_change_screen_resolution.mspx?mfr=true

于 2011-11-06T21:14:36.100 回答
0

ok, I did try use keystrokes to move, resize windows. But system will automatically move windows back to visible region of desktop in my XP. I also tried SetWindowPos API, and no helps. The best chance will be to write a Video driver, but it may need more study. The 360 desktop claims you can expand desktop horizontally. But actually it just pan the current desktop in a virtual wider space. Any windows inside still have the size limitation of no larger than your screen resolution.

Video driver set the screen resolution(yes, have to compatibile to lcd/crt screen capability), and Windows did limit window-size by this thresholds. I just want to work around in user space API.

于 2009-01-16T00:18:46.677 回答
0

我需要将窗口的一部分从屏幕顶部推开,我终于能够使用这个 AutoHotKey 脚本来做到这一点:

SetTitleMatchMode, 2
WinTitle := "Visual Studio Code"

; --- WinMove version

; WinMove, %WinTitle%, , 0, -64, 1280, 1504

; -- DLL version

WinGet, id, , %WinTitle%
Result := DllCall("SetWindowPos", "uint", id, "uint", HWND_TOP, "Int", 0, "Int", -64, "Int", 1280, "Int", 1504, "UInt", 0x400)

(我想通过完全隐藏标题栏和选项卡部分来最大化 VSCode 的编辑器区域,这在程序本身中是不可配置的。)

于 2018-11-12T11:09:06.527 回答
-1

对于需要 MSDN 的屏幕更友好的视图的特定情况,或者在任何其他网站(如 StackOverflow)上对屏幕空间的利用不佳的情况下,我建议使用像 IE7Pro 这样的工具将自定义样式表应用于页面(IE)、Greasemonkey (Firefox)、Stylish (Fireox) 或 Opera 中内置的样式表选择器。

于 2009-01-15T07:45:11.877 回答