2017-02-16 3 views
-1

У меня есть окно WPF с отключенной возможностью изменения размера (WindowStyle = None, ResizeMode = CanMinimize).Отключить реакцию окна на вызов функции ShowWindow

Это нормально работает, кроме одной ситуации. Если какое-либо приложение (то есть AutoHotKey) вызывает функцию WIN API ShowWindow в моем окне с параметром SW_MAXIMIZE, то мои репозиции окна (0, 0) координируются на рабочем столе без изменения размера, и пользователь не может перемещать его по экрану дальше ,

Как я могу отключить это поведение? Я хочу, чтобы окно игнорировало этот вызов в моем окне.

Я попытался реагировать на событие WM_WINDOWPOSCHANGING, но это работает только до тех пор, пока пользователь не минимизирует окно. После того, как он будет сведен к минимуму и восстановлен, он снова будет перемещен в положение (0, 0).

private IntPtr ProcessMessage(IntPtr windowHandle, int msg, IntPtr wideParam, IntPtr leftParam, ref bool handled) 
{ 
    Msg windowsMessage = (Msg)msg; 
    switch (windowsMessage) 
    { 
     case Msg.WM_WINDOWPOSCHANGING: 
      { 
       WindowPos windowPos = (WindowPos)Marshal.PtrToStructure(leftParam, typeof(WindowPos)); 

       if (IsNoClientAction(windowPos) && !IsMinimizing(windowPos) && window.WindowState == WindowState.Normal) 
       { 
        windowPos.Flags = SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_NOMOVE; 
        handled = true; 
        Marshal.StructureToPtr(windowPos, leftParam, true); 
       } 

       break; 
      } 
    } 

    return IntPtr.Zero; 
} 

private static bool IsNoClientAction(WindowPos windowPos) 
{ 
    return (windowPos.Flags & SetWindowPosFlags.SWP_NOCLIENTSIZE) != 0 || (windowPos.Flags & SetWindowPosFlags.SWP_NOCLIENTMOVE) != 0; 
} 

private static bool IsMinimizing(WindowPos windowPos) 
{ 
    return windowPos.Left == -32000 && windowPos.Top == -32000; 
} 

ответ

0

Я проанализировал, что делает user32.dll к окну и понял, решение, основанное на этом. Перед отправкой любых сообщений на Wndproc он обновляет GWL_STYLE флаги окна, разрешающие WS_MAXIMIZE для него. По этой причине состояние окна становится поврежденным, и дальнейшее поведение вряд ли может быть обработано только обработкой оконных сообщений.

Чтобы отключить реакцию окна на ShowWindow с SW_MAXIMIZE опцией Я заходящего этот флаг назад, когда WM_WINDOWPOSCHANGING обрабатывается:

private IntPtr ProcessMessage(IntPtr windowHandle, int msg, IntPtr wideParam, IntPtr leftParam, ref bool handled) 
{ 
    Msg windowsMessage = (Msg)msg; 
    switch (windowsMessage) 
    { 
     case Msg.WM_WINDOWPOSCHANGING: 
      { 
       WindowPos windowPos = (WindowPos)Marshal.PtrToStructure(leftParam, typeof(WindowPos)); 

       if (IsNoClientAction(windowPos)) 
       { 
        WindowStyles styles = (WindowStyles)WindowsAPI.GetWindowLongPtr(windowHandle, GWL.GWL_STYLE); 
        if ((styles & WindowStyles.WS_MAXIMIZE) != 0) 
        { 
         windowPos.Flags |= SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_NOMOVE; 
         WindowsAPI.SetWindowLongPtr(new HandleRef(this, windowHandle), GWL.GWL_STYLE, (IntPtr)(long)(styles^WindowStyles.WS_MAXIMIZE)); 
         handled = true; 
         Marshal.StructureToPtr(windowPos, leftParam, true); 
        } 
       } 

       break; 
      } 
    } 

    return IntPtr.Zero; 
} 

private static bool IsNoClientAction(WindowPos windowPos) 
{ 
    return (windowPos.Flags & SetWindowPosFlags.SWP_NOCLIENTSIZE) != 0 || (windowPos.Flags & SetWindowPosFlags.SWP_NOCLIENTMOVE) != 0; 
} 
Смежные вопросы