是否可以从窗口句柄设置另一个应用程序窗口的最大宽度?

时间:2017-03-16 08:46:43

标签: c# windows window-handles

我目前有一个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);
}

我在修补此问题后再次更新问题。

1 个答案:

答案 0 :(得分:0)

我提出的解决方案不仅仅是C#,所以这并不完全符合问题标签,但无论如何我都会发布它。

我创建了一个第三方DLL,其中WndProc挂钩的初始化函数可以收听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指导我这个答案。