【问题标题】:Is it possible to set another application's window's maximum width from its window handle?是否可以从其窗口句柄设置另一个应用程序窗口的最大宽度?
【发布时间】:2017-03-16 08:46:43
【问题描述】:

我目前有一个窗口句柄的IntPtr,我尝试使用HwndSource.FromHwnd 获取它的Window,但它返回null。如果检索到Window 元素,则可以设置其MaxWidth 属性。

是否有其他方法可以仅通过拥有外部应用程序的窗口句柄来设置最大宽度?

编辑: 试图查看RbMm 的方法是否有效。问题标记为 C#,但使用 C++ 自定义 DLL 可能值得一试:

bool InitializeMaxWidthHook(int threadID, HWND destination)
{
    if (g_appInstance == NULL)
    {
        return false;
    }

    SetProp(GetDesktopWindow(), "WILSON_HOOK_HCBT_MINMAX", destination);

    hookMaxWidth = SetWindowsHookEx(WH_CBT, (HOOKPROC)MinMaxHookCallback, g_appInstance, threadID);
    return hookMaxWidth != NULL;
}

void UninitializeMaxWidthHook()
{
    if (hookMaxWidth != NULL)
        UnhookWindowsHookEx(hookMaxWidth);
    hookMaxWidth = NULL;
}

static LRESULT CALLBACK MinMaxHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
    if (code >= 0)
    {
        UINT msg = 0;

        if (code == HCBT_MINMAX)
            msg = RegisterWindowMessage("WILSON_HOOK_HCBT_MINMAX");

        HWND dstWnd = (HWND)GetProp(GetDesktopWindow(), "WILSON_HOOK_HCBT_MINMAX");

        if (msg != 0)
            SendNotifyMessage(dstWnd, msg, wparam, lparam);
    }

    return CallNextHookEx(hookMaxWidth, code, wparam, lparam);
}

我会在修改后再次更新问题。

【问题讨论】:

  • 窗口没有任何MaxWidth 属性。窗口过程处理WM_GETMINMAXINFO 消息并在MINMAXINFO 中返回ptMaxSize - 所以只有控制窗口过程的方法
  • 可能的方法 - 设置 WH_CALLWNDPROCRET - 实现 CallWndRetProc 回调函数并更改 MINMAXINFO 结构
  • 另一种方法是监视(轮询)窗口大小和resize it,当它太大时。
  • RbMm 的解决方案不起作用,它需要将代码注入拥有窗口的进程中,并且不能是 C# 代码。使用 System.Windows.Automation 命名空间或 SetWinEventHook() 来监视大小变化几乎是最实用的。
  • @Hans 是的,标签实际上是用于 C# 的。在检查自定义 DLL 之后,我一定会尝试您的方法。

标签: c# windows window-handles


【解决方案1】:

我想出的解决方案不是纯粹的 C#,所以这不完全适合问题标签,但我还是会发布它。

我为WndProc创建了一个带有初始化函数的第三方DLL来监听GETMINMAXINFO(出于隐私考虑,我删除了部分代码,但这是GETMINMAXINFO的代码:

#include "stdafx.h"
#include <windows.h>

HINSTANCE g_appInstance = NULL;
typedef void (CALLBACK *HookProc)(int code, WPARAM w, LPARAM l);

HHOOK hookWndProc = NULL;
static LRESULT CALLBACK WndProcHookCallback(int code, WPARAM wparam, LPARAM lparam);

bool InitializeWndProcHook(int threadID, HWND destination)
{
    if (g_appInstance == NULL)
    {
        return false;
    }

    SetProp(GetDesktopWindow(), "WILSON_HOOK_HWND_WND_PROC", destination);

    hookWndProc = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)WndProcHookCallback, g_appInstance, threadID);
    return hookWndProc != NULL;
}

void UninitializeWndProcHook()
{
    if (hookWndProc != NULL)
        UnhookWindowsHookEx(hookWndProc);
    hookWndProc = NULL;
}

static LRESULT CALLBACK WndProcHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
    if (code >= 0)
    {
        UINT msg = 0;

        WPARAM newWPARAM;
        LPARAM newLPARAM;
        if (code == HC_ACTION)
        {
            CWPSTRUCT *wndProc = (CWPSTRUCT *)lparam;           
            if (shouldSendMessageOnWindow(wndProc->hwnd))
            {
                // if the message is from other process, the value of wparam is null
                UINT wndProcMessage = wndProc->message;
                if (wndProcMessage == WM_GETMINMAXINFO)
                {
                    newWPARAM = (WPARAM)wndProc->hwnd;
                    newLPARAM = (LPARAM)wndProc->lParam;
                    msg = RegisterWindowMessage("WILSON_HOOK_HC_ACTION_WND_PROC_WM_GETMINMAXINFO");
                }
            }
        }

        if (msg != 0)
        {
            HWND dstWnd = (HWND)GetProp(GetDesktopWindow(), "WILSON_HOOK_HWND_WND_PROC");
            SendNotifyMessage(dstWnd, msg, newWPARAM, newLPARAM);
        }
    }

    return CallNextHookEx(hookWndProc, code, wparam, lparam);
}

然后我在我的 C# 代码中初始化了这个钩子并等待 MINMAX 消息然后将信息设置为我想要的大小。

private struct POINT
{
    public int x;
    public int y;
}

private struct MINMAXINFO
{
    public POINT ptReserved;
    public POINT ptMaxSize;
    public POINT ptMaxPosition;
    public POINT ptMinTrackSize;
    public POINT ptMaxTrackSize;
}

/**Other Code**/

MINMAXINFO* minMaxInfo = (MINMAXINFO*) lParam;

int currentMaxSize = minMaxInfo->ptMaxSize.x;
Debug.WriteLine("Updated max" + currentMaxSize);

minMaxInfo->ptMaxSize.x = screenWidth; 
minMaxInfo->ptMaxSize.y = screenHeight;

User32.SetWindowPos(wParam, User32.SpecialWindowHandles.HWND_TOP, 0, 0, screenWidth, screenHeight, User32.SetWindowPosFlags.SWP_DRAWFRAME | User32.SetWindowPosFlags.SWP_ASYNCWINDOWPOS);

/**Other Code**/

这适用于某些应用程序(我认为只适用于 Win32 应用程序)。某些应用程序(例如 Metro Apps 和可能的 Java 小程序)无法访问。

但就目前而言,这对初学者来说可能是件好事。

感谢Hans PassantRbMm 指导我回答这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    相关资源
    最近更新 更多