Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/vcl/win/window/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 222 kB image not shown  

Quelle  salframe.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <com/sun/star/accessibility/MSAAService.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/uno/DeploymentException.hpp>
#include <IconThemeSelector.hxx>

#include <officecfg/Office/Common.hxx>

#include <memory>
#include <string.h>
#include <limits.h>

#include <svsys.h>

#include <comphelper/diagnose_ex.hxx>
#include <comphelper/windowserrorstring.hxx>

#include <rtl/bootstrap.hxx>
#include <rtl/character.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>

#include <osl/module.h>
#include <comphelper/scopeguard.hxx>
#include <tools/debug.hxx>
#include <o3tl/enumarray.hxx>
#include <o3tl/char16_t2wchar_t.hxx>

#include <vcl/event.hxx>
#include <vcl/sysdata.hxx>
#include <vcl/timer.hxx>
#include <vcl/settings.hxx>
#include <vcl/themecolors.hxx>
#include <vcl/keycodes.hxx>
#include <vcl/window.hxx>
#include <vcl/wrkwin.hxx>
#include <vcl/svapp.hxx>
#include <vcl/ptrstyle.hxx>

#include <win/wincomp.hxx>
#include <win/salids.hrc>
#include <win/saldata.hxx>
#include <win/salinst.h>
#include <win/salbmp.h>
#include <win/salgdi.h>
#include <win/salsys.h>
#include <win/salframe.h>
#include <win/salvd.h>
#include <win/salmenu.h>
#include <win/salobj.h>
#include <win/saltimer.h>

#include <helpwin.hxx>
#include <window.h>
#include <sallayout.hxx>

#include <vector>

#include <com/sun/star/uno/Exception.hpp>

#include <oleacc.h>
#include <com/sun/star/accessibility/XMSAAService.hpp>

#include <time.h>

#if !defined WIN32_LEAN_AND_MEAN
define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <dwmapi.h>
#include <shobjidl.h>
#include <propkey.h>
#include <propvarutil.h>
#include <shellapi.h>
#include <uxtheme.h>
#include <Vssym32.h>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::beans;

#ifndef IDC_PEN
define IDC_PEN MAKEINTRESOURCE(32631)
#endif

const unsigned int WM_USER_SYSTEM_WINDOW_ACTIVATED = RegisterWindowMessageW(L"SYSTEM_WINDOW_ACTIVATED");

bool WinSalFrame::mbInReparent = false;

// Macros for support of WM_UNICHAR & Keyman 6.0
#define Uni_SupplementaryPlanesStart    0x10000

static void SetGeometrySize(vcl::WindowPosSize& rWinPosSize, const Size& rSize)
{
    rWinPosSize.setWidth(rSize.Width() < 0 ? 0 : rSize.Width());
    rWinPosSize.setHeight(rSize.Height() < 0 ? 0 : rSize.Height());
}

// If called with UpdateFrameGeometry, it must be called after it, as UpdateFrameGeometry
// updates the geometry depending on the old state!
void WinSalFrame::UpdateFrameState()
{
    // don't overwrite restore state in fullscreen mode
    if (isFullScreen())
        return;

    const bool bVisible = (GetWindowStyle(mhWnd) & WS_VISIBLE);
    if (IsIconic(mhWnd))
    {
        m_eState &= ~vcl::WindowState(vcl::WindowState::Normal | vcl::WindowState::Maximized);
        m_eState |= vcl::WindowState::Minimized;
        if (bVisible)
            mnShowState = SW_SHOWMINIMIZED;
    }
    else if (IsZoomed(mhWnd))
    {
        m_eState &= ~vcl::WindowState(vcl::WindowState::Minimized | vcl::WindowState::Normal);
        m_eState |= vcl::WindowState::Maximized;
        if (bVisible)
            mnShowState = SW_SHOWMAXIMIZED;
        mbRestoreMaximize = true;
    }
    else
    {
        m_eState &= ~vcl::WindowState(vcl::WindowState::Minimized | vcl::WindowState::Maximized);
        m_eState |= vcl::WindowState::Normal;
        if (bVisible)
            mnShowState = SW_SHOWNORMAL;
        mbRestoreMaximize = false;
    }
}

// if pParentRect is set, the workarea of the monitor that contains pParentRect is returned
void ImplSalGetWorkArea( HWND hWnd, RECT *pRect, const RECT *pParentRect )
{
    if (Application::IsHeadlessModeEnabled()) {
        pRect->left = 0;
        pRect->top = 0;
        pRect->right = VIRTUAL_DESKTOP_WIDTH;
        pRect->bottom = VIRTUAL_DESKTOP_HEIGHT;
        return;
    }
    // check if we or our parent is fullscreen, then the taskbar should be ignored
    bool bIgnoreTaskbar = false;
    WinSalFrame* pFrame = GetWindowPtr( hWnd );
    if( pFrame )
    {
        vcl::Window *pWin = pFrame->GetWindow();
        while( pWin )
        {
            WorkWindow *pWorkWin = (pWin->GetType() == WindowType::WORKWINDOW) ? static_cast<WorkWindow *>(pWin) : nullptr;
            if( pWorkWin && pWorkWin->ImplGetWindowImpl()->mbReallyVisible && pWorkWin->IsFullScreenMode() )
            {
                bIgnoreTaskbar = true;
                break;
            }
            else
                pWin = pWin->ImplGetWindowImpl()->mpParent;
        }
    }

    // calculates the work area taking multiple monitors into account
    static int nMonitors = GetSystemMetrics( SM_CMONITORS );
    if( nMonitors == 1 )
    {
        if( bIgnoreTaskbar )
        {
            pRect->left = pRect->top = 0;
            pRect->right   = GetSystemMetrics( SM_CXSCREEN );
            pRect->bottom  = GetSystemMetrics( SM_CYSCREEN );
        }
        else
            SystemParametersInfoW( SPI_GETWORKAREA, 0, pRect, 0 );
    }
    else
    {
        if( pParentRect != nullptr )
        {
            // return the size of the monitor where pParentRect lives
            HMONITOR hMonitor;
            MONITORINFO mi;

            // get the nearest monitor to the passed rect.
            hMonitor = MonitorFromRect(pParentRect, MONITOR_DEFAULTTONEAREST);

            // get the work area or entire monitor rect.
            mi.cbSize = sizeof(mi);
            GetMonitorInfo(hMonitor, &mi);
            if( !bIgnoreTaskbar )
                *pRect = mi.rcWork;
            else
                *pRect = mi.rcMonitor;
        }
        else
        {
            // return the union of all monitors
            pRect->left = GetSystemMetrics( SM_XVIRTUALSCREEN );
            pRect->top = GetSystemMetrics( SM_YVIRTUALSCREEN );
            pRect->right = pRect->left + GetSystemMetrics( SM_CXVIRTUALSCREEN );
            pRect->bottom = pRect->top + GetSystemMetrics( SM_CYVIRTUALSCREEN );

            // virtualscreen does not take taskbar into account, so use the corresponding
            // diffs between screen and workarea from the default screen
            // however, this is still not perfect: the taskbar might not be on the primary screen
            if( !bIgnoreTaskbar )
            {
                RECT wRect, scrRect;
                SystemParametersInfoW( SPI_GETWORKAREA, 0, &wRect, 0 );
                scrRect.left = 0;
                scrRect.top = 0;
                scrRect.right = GetSystemMetrics( SM_CXSCREEN );
                scrRect.bottom = GetSystemMetrics( SM_CYSCREEN );

                pRect->left += wRect.left;
                pRect->top += wRect.top;
                pRect->right -= scrRect.right - wRect.right;
                pRect->bottom -= scrRect.bottom - wRect.bottom;
            }
        }
    }
}

namespace {

enum PreferredAppMode
{
    AllowDark = 1,
    ForceDark = 2,
    ForceLight = 3
};

}

static void UpdateDarkMode(HWND hWnd)
{
    static bool bOSSupportsDarkMode = OSSupportsDarkMode();
    if (!bOSSupportsDarkMode)
        return;

    HINSTANCE hUxthemeLib = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
    if (!hUxthemeLib)
        return;

    typedef PreferredAppMode(WINAPI* SetPreferredAppMode_t)(PreferredAppMode);
    auto SetPreferredAppMode = reinterpret_cast<SetPreferredAppMode_t>(GetProcAddress(hUxthemeLib, MAKEINTRESOURCEA(135)));
    if (SetPreferredAppMode)
    {
        switch (MiscSettings::GetAppColorMode())
        {
            case AppearanceMode::AUTO:
                SetPreferredAppMode(AllowDark);
                break;
            case AppearanceMode::LIGHT:
                SetPreferredAppMode(ForceLight);
                break;
            case AppearanceMode::DARK:
                SetPreferredAppMode(ForceDark);
                break;
        }
    }

    BOOL bDarkMode = UseDarkMode();

    typedef void(WINAPI* AllowDarkModeForWindow_t)(HWND, BOOL);
    auto AllowDarkModeForWindow = reinterpret_cast<AllowDarkModeForWindow_t>(GetProcAddress(hUxthemeLib, MAKEINTRESOURCEA(133)));
    if (AllowDarkModeForWindow)
        AllowDarkModeForWindow(hWnd, bDarkMode);

    FreeLibrary(hUxthemeLib);

    if (!AllowDarkModeForWindow)
        return;

    DwmSetWindowAttribute(hWnd, 20, &bDarkMode, sizeof(bDarkMode));
}

static void UpdateAutoAccel()
{
    BOOL bUnderline = FALSE;
    SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &bUnderline, 0);

    ImplSVData* pSVData = ImplGetSVData();
    pSVData->maNWFData.mbAutoAccel = !bUnderline;
}

SalFrame* ImplSalCreateFrame( WinSalInstance* pInst,
                              HWND hWndParent, SalFrameStyleFlags nSalFrameStyle )
{
    WinSalFrame*   pFrame = new WinSalFrame;
    HWND        hWnd;
    DWORD       nSysStyle = 0;
    DWORD       nExSysStyle = 0;
    bool        bSubFrame = false;

    static const char* pEnvSynchronize = getenv("SAL_SYNCHRONIZE");
    if ( pEnvSynchronize )   // no buffering of drawing commands
        GdiSetBatchLimit( 1 );

    static const char* pEnvTransparentFloats = getenv("SAL_TRANSPARENT_FLOATS" );

    // determine creation data
    if ( nSalFrameStyle & (SalFrameStyleFlags::PLUG | SalFrameStyleFlags::SYSTEMCHILD) )
    {
        nSysStyle |= WS_CHILD;
        if( nSalFrameStyle & SalFrameStyleFlags::SYSTEMCHILD )
            nSysStyle |= WS_CLIPSIBLINGS;
    }
    else
    {
        // #i87402# commenting out WS_CLIPCHILDREN
        // this breaks SalFrameStyleFlags::SYSTEMCHILD handling, which is not
        // used currently. Probably SalFrameStyleFlags::SYSTEMCHILD should be
        // removed again.

        // nSysStyle  |= WS_CLIPCHILDREN;
        if ( hWndParent )
        {
            nSysStyle |= WS_POPUP;
            bSubFrame = true;
            pFrame->mbNoIcon = true;
        }
        else
        {
            // Only with WS_OVERLAPPED we get a useful default position/size
            if ( (nSalFrameStyle & (SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::MOVEABLE)) ==
                 (SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::MOVEABLE) )
                nSysStyle |= WS_OVERLAPPED;
            else
            {
                nSysStyle |= WS_POPUP;
                if ( !(nSalFrameStyle & SalFrameStyleFlags::MOVEABLE) )
                    nExSysStyle |= WS_EX_TOOLWINDOW;    // avoid taskbar appearance, for eg splash screen
            }
        }

        if ( nSalFrameStyle & SalFrameStyleFlags::MOVEABLE )
        {
            pFrame->mbCaption = true;
            nSysStyle |= WS_SYSMENU | WS_CAPTION;
            if ( !hWndParent )
                nSysStyle |= WS_SYSMENU | WS_MINIMIZEBOX;
            else
                nExSysStyle |= WS_EX_DLGMODALFRAME;

            if ( nSalFrameStyle & SalFrameStyleFlags::SIZEABLE )
            {
                pFrame->mbSizeBorder = true;
                nSysStyle |= WS_THICKFRAME;
                if ( !hWndParent )
                    nSysStyle |= WS_MAXIMIZEBOX;
            }
            else
                pFrame->mbFixBorder = true;

            if ( nSalFrameStyle & SalFrameStyleFlags::DEFAULT )
                nExSysStyle |= WS_EX_APPWINDOW;
        }
        if( nSalFrameStyle & SalFrameStyleFlags::TOOLWINDOW
            // #100656# toolwindows lead to bad alt-tab behaviour, if they have the focus
            // you must press it twice to leave the application
            // so toolwindows are only used for non sizeable windows
            // which are typically small, so a small caption makes sense

            // #103578# looked too bad - above changes reverted
            /* && !(nSalFrameStyle & SalFrameStyleFlags::SIZEABLE) */ )
        {
            pFrame->mbNoIcon = true;
            nExSysStyle |= WS_EX_TOOLWINDOW;
            if ( pEnvTransparentFloats /*&& !(nSalFrameStyle & SalFrameStyleFlags::MOVEABLE) */)
                nExSysStyle |= WS_EX_LAYERED;
        }
    }
    if ( nSalFrameStyle & SalFrameStyleFlags::FLOAT )
    {
        nExSysStyle |= WS_EX_TOOLWINDOW;
        pFrame->mbFloatWin = true;

        if (pEnvTransparentFloats)
            nExSysStyle |= WS_EX_LAYERED;

    }
    if (nSalFrameStyle & SalFrameStyleFlags::TOOLTIP)
        nExSysStyle |= WS_EX_TOPMOST;

    // init frame data
    pFrame->mnStyle = nSalFrameStyle;

    // determine show style
    pFrame->mnShowState = SW_SHOWNORMAL;
    if ( (nSysStyle & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME) )
    {
        if ( GetSystemMetrics( SM_CXSCREEN ) <= 1024 )
            pFrame->mnShowState = SW_SHOWMAXIMIZED;
        else
        {
            if ( nSalFrameStyle & SalFrameStyleFlags::DEFAULT )
            {
                SalData* pSalData = GetSalData();
                pFrame->mnShowState = pSalData->mnCmdShow;
                if ( (pFrame->mnShowState != SW_SHOWMINIMIZED) &&
                     (pFrame->mnShowState != SW_MINIMIZE) &&
                     (pFrame->mnShowState != SW_SHOWMINNOACTIVE) )
                {
                    if ( (pFrame->mnShowState == SW_SHOWMAXIMIZED) ||
                         (pFrame->mnShowState == SW_MAXIMIZE) )
                        pFrame->mbOverwriteState = false;
                    pFrame->mnShowState = SW_SHOWMAXIMIZED;
                }
                else
                    pFrame->mbOverwriteState = false;
            }
            else
            {
                // Document Windows are also maximized, if the current Document Window
                // is also maximized
                HWND hWnd2 = GetForegroundWindow();
                if ( hWnd2 && IsMaximized( hWnd2 ) &&
                     (GetWindowInstance( hWnd2 ) == pInst->mhInst) &&
                     ((GetWindowStyle( hWnd2 ) & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME)) )
                    pFrame->mnShowState = SW_SHOWMAXIMIZED;
            }
        }
    }

    // create frame
    LPCWSTR pClassName;
    if ( bSubFrame )
    {
        if ( nSalFrameStyle & (SalFrameStyleFlags::MOVEABLE|SalFrameStyleFlags::NOSHADOW) ) // check if shadow not wanted
            pClassName = SAL_SUBFRAME_CLASSNAMEW;
        else
            pClassName = SAL_TMPSUBFRAME_CLASSNAMEW;    // undecorated floaters will get shadow on XP
    }
    else
    {
        if ( nSalFrameStyle & SalFrameStyleFlags::MOVEABLE )
            pClassName = SAL_FRAME_CLASSNAMEW;
        else
            pClassName = SAL_TMPSUBFRAME_CLASSNAMEW;
    }
    hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
                            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
                            hWndParent, nullptr, pInst->mhInst, pFrame );
    SAL_WARN_IF(!hWnd, "vcl""CreateWindowExW failed: " << comphelper::WindowsErrorString(GetLastError()));

#if OSL_DEBUG_LEVEL > 1
    // set transparency value
    if( GetWindowExStyle( hWnd ) & WS_EX_LAYERED )
        SetLayeredWindowAttributes( hWnd, 0, 230, 0x00000002 /*LWA_ALPHA*/ );
#endif
    if ( !hWnd )
    {
        delete pFrame;
        return nullptr;
    }

    // If we have a Window with a Caption Bar and without
    // a MaximizeBox, we change the SystemMenu
    if ( (nSysStyle & (WS_CAPTION | WS_MAXIMIZEBOX)) == (WS_CAPTION) )
    {
        HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
        if ( hSysMenu )
        {
            if ( !(nSysStyle & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX)) )
                DeleteMenu( hSysMenu, SC_RESTORE, MF_BYCOMMAND );
            else
                EnableMenuItem( hSysMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
            if ( !(nSysStyle & WS_MINIMIZEBOX) )
                DeleteMenu( hSysMenu, SC_MINIMIZE, MF_BYCOMMAND );
            if ( !(nSysStyle & WS_MAXIMIZEBOX) )
                DeleteMenu( hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND );
            if ( !(nSysStyle & WS_THICKFRAME) )
                DeleteMenu( hSysMenu, SC_SIZE, MF_BYCOMMAND );
        }
    }
    if ( (nSysStyle & WS_SYSMENU) && !(nSalFrameStyle & SalFrameStyleFlags::CLOSEABLE) )
    {
        HMENU hSysMenu = GetSystemMenu( hWnd, FALSE );
        if ( hSysMenu )
            EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED );
    }

    // reset input context
    pFrame->mhDefIMEContext = ImmAssociateContext( hWnd, nullptr );

    // determine output size and state
    RECT aRect;
    GetClientRect( hWnd, &aRect );
    pFrame->mbDefPos = true;

    pFrame->UpdateFrameGeometry();
    pFrame->UpdateFrameState();

    if( pFrame->mnShowState == SW_SHOWMAXIMIZED )
    {
        // #96084 set a useful internal window size because
        // the window will not be maximized (and the size updated) before show()

        pFrame->SetMaximizedFrameGeometry(hWnd);
    }

    return pFrame;
}

// helper that only creates the HWND
// to allow for easy reparenting of system windows, (i.e. destroy and create new)
HWND ImplSalReCreateHWND( HWND hWndParent, HWND oldhWnd, bool bAsChild )
{
    HINSTANCE hInstance = GetSalData()->mhInst;
    sal_uLong nSysStyle     = GetWindowLongW( oldhWnd, GWL_STYLE );
    sal_uLong nExSysStyle   = GetWindowLongW( oldhWnd, GWL_EXSTYLE );

    if( bAsChild )
    {
        nSysStyle = WS_CHILD;
        nExSysStyle = 0;
    }

    LPCWSTR pClassName = SAL_SUBFRAME_CLASSNAMEW;
    return CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle,
                            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
                            hWndParent, nullptr, hInstance, GetWindowPtr( oldhWnd ) );
}

// translation table from System keycodes into StartView keycodes
#define KEY_TAB_SIZE     168

const sal_uInt16 aImplTranslateKeyTab[KEY_TAB_SIZE] =
{
    // StarView-Code      System-Code                         Index
    0,                    //                                  0
    0,                    // VK_LBUTTON                       1
    0,                    // VK_RBUTTON                       2
    0,                    // VK_CANCEL                        3
    0,                    // VK_MBUTTON                       4
    0,                    //                                  5
    0,                    //                                  6
    0,                    //                                  7
    KEY_BACKSPACE,        // VK_BACK                          8
    KEY_TAB,              // VK_TAB                           9
    0,                    //                                  10
    0,                    //                                  11
    0,                    // VK_CLEAR                         12
    KEY_RETURN,           // VK_RETURN                        13
    0,                    //                                  14
    0,                    //                                  15
    0,                    // VK_SHIFT                         16
    0,                    // VK_CONTROL                       17
    0,                    // VK_MENU                          18
    0,                    // VK_PAUSE                         19
    0,                    // VK_CAPITAL                       20
    0,                    // VK_HANGUL                        21
    0,                    //                                  22
    0,                    //                                  23
    0,                    //                                  24
    KEY_HANGUL_HANJA,     // VK_HANJA                         25
    0,                    //                                  26
    KEY_ESCAPE,           // VK_ESCAPE                        27
    0,                    //                                  28
    0,                    //                                  29
    0,                    //                                  30
    0,                    //                                  31
    KEY_SPACE,            // VK_SPACE                         32
    KEY_PAGEUP,           // VK_PRIOR                         33
    KEY_PAGEDOWN,         // VK_NEXT                          34
    KEY_END,              // VK_END                           35
    KEY_HOME,             // VK_HOME                          36
    KEY_LEFT,             // VK_LEFT                          37
    KEY_UP,               // VK_UP                            38
    KEY_RIGHT,            // VK_RIGHT                         39
    KEY_DOWN,             // VK_DOWN                          40
    0,                    // VK_SELECT                        41
    0,                    // VK_PRINT                         42
    0,                    // VK_EXECUTE                       43
    0,                    // VK_SNAPSHOT                      44
    KEY_INSERT,           // VK_INSERT                        45
    KEY_DELETE,           // VK_DELETE                        46
    KEY_HELP,             // VK_HELP                          47
    KEY_0,                //                                  48
    KEY_1,                //                                  49
    KEY_2,                //                                  50
    KEY_3,                //                                  51
    KEY_4,                //                                  52
    KEY_5,                //                                  53
    KEY_6,                //                                  54
    KEY_7,                //                                  55
    KEY_8,                //                                  56
    KEY_9,                //                                  57
    0,                    //                                  58
    0,                    //                                  59
    0,                    //                                  60
    0,                    //                                  61
    0,                    //                                  62
    0,                    //                                  63
    0,                    //                                  64
    KEY_A,                //                                  65
    KEY_B,                //                                  66
    KEY_C,                //                                  67
    KEY_D,                //                                  68
    KEY_E,                //                                  69
    KEY_F,                //                                  70
    KEY_G,                //                                  71
    KEY_H,                //                                  72
    KEY_I,                //                                  73
    KEY_J,                //                                  74
    KEY_K,                //                                  75
    KEY_L,                //                                  76
    KEY_M,                //                                  77
    KEY_N,                //                                  78
    KEY_O,                //                                  79
    KEY_P,                //                                  80
    KEY_Q,                //                                  81
    KEY_R,                //                                  82
    KEY_S,                //                                  83
    KEY_T,                //                                  84
    KEY_U,                //                                  85
    KEY_V,                //                                  86
    KEY_W,                //                                  87
    KEY_X,                //                                  88
    KEY_Y,                //                                  89
    KEY_Z,                //                                  90
    0,                    // VK_LWIN                          91
    0,                    // VK_RWIN                          92
    KEY_CONTEXTMENU,      // VK_APPS                          93
    0,                    //                                  94
    0,                    //                                  95
    KEY_0,                // VK_NUMPAD0                       96
    KEY_1,                // VK_NUMPAD1                       97
    KEY_2,                // VK_NUMPAD2                       98
    KEY_3,                // VK_NUMPAD3                       99
    KEY_4,                // VK_NUMPAD4                      100
    KEY_5,                // VK_NUMPAD5                      101
    KEY_6,                // VK_NUMPAD6                      102
    KEY_7,                // VK_NUMPAD7                      103
    KEY_8,                // VK_NUMPAD8                      104
    KEY_9,                // VK_NUMPAD9                      105
    KEY_MULTIPLY,         // VK_MULTIPLY                     106
    KEY_ADD,              // VK_ADD                          107
    KEY_DECIMAL,          // VK_SEPARATOR                    108
    KEY_SUBTRACT,         // VK_SUBTRACT                     109
    KEY_DECIMAL,          // VK_DECIMAL                      110
    KEY_DIVIDE,           // VK_DIVIDE                       111
    KEY_F1,               // VK_F1                           112
    KEY_F2,               // VK_F2                           113
    KEY_F3,               // VK_F3                           114
    KEY_F4,               // VK_F4                           115
    KEY_F5,               // VK_F5                           116
    KEY_F6,               // VK_F6                           117
    KEY_F7,               // VK_F7                           118
    KEY_F8,               // VK_F8                           119
    KEY_F9,               // VK_F9                           120
    KEY_F10,              // VK_F10                          121
    KEY_F11,              // VK_F11                          122
    KEY_F12,              // VK_F12                          123
    KEY_F13,              // VK_F13                          124
    KEY_F14,              // VK_F14                          125
    KEY_F15,              // VK_F15                          126
    KEY_F16,              // VK_F16                          127
    KEY_F17,              // VK_F17                          128
    KEY_F18,              // VK_F18                          129
    KEY_F19,              // VK_F19                          130
    KEY_F20,              // VK_F20                          131
    KEY_F21,              // VK_F21                          132
    KEY_F22,              // VK_F22                          133
    KEY_F23,              // VK_F23                          134
    KEY_F24,              // VK_F24                          135
    0,                    //                                 136
    0,                    //                                 137
    0,                    //                                 138
    0,                    //                                 139
    0,                    //                                 140
    0,                    //                                 141
    0,                    //                                 142
    0,                    //                                 143
    0,                    // NUMLOCK                         144
    0,                    // SCROLLLOCK                      145
    0,                    //                                 146
    0,                    //                                 147
    0,                    //                                 148
    0,                    //                                 149
    0,                    //                                 150
    0,                    //                                 151
    0,                    //                                 152
    0,                    //                                 153
    0,                    //                                 154
    0,                    //                                 155
    0,                    //                                 156
    0,                    //                                 157
    0,                    //                                 158
    0,                    //                                 159
    0,                    //                                 160
    0,                    //                                 161
    0,                    //                                 162
    0,                    //                                 163
    0,                    //                                 164
    0,                    //                                 165
    KEY_XF86BACK,         // VK_BROWSER_BACK                 166
    KEY_XF86FORWARD       // VK_BROWSER_FORWARD              167
};

static UINT ImplSalGetWheelScrollLines()
{
    UINT nScrLines = 0;
    if (!SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &nScrLines, 0) || !nScrLines)
        nScrLines = 3;

    return nScrLines;
}

static UINT ImplSalGetWheelScrollChars()
{
    UINT nScrChars = 0;
    if( !SystemParametersInfoW( SPI_GETWHEELSCROLLCHARS, 0, &nScrChars, 0 ) )
    {
        return 3;
    }

    // system settings successfully read
    return nScrChars;
}

static void ImplSalAddBorder( const WinSalFrame* pFrame, int& width, int& height )
{
    // transform client size into window size
    RECT    aWinRect;
    aWinRect.left   = 0;
    aWinRect.right  = width-1;
    aWinRect.top    = 0;
    aWinRect.bottom = height-1;
    AdjustWindowRectEx( &aWinRect, GetWindowStyle( pFrame->mhWnd ),
                        FALSE,     GetWindowExStyle( pFrame->mhWnd ) );
    width  = aWinRect.right - aWinRect.left + 1;
    height = aWinRect.bottom - aWinRect.top + 1;
}

static void ImplSalCalcFullScreenSize( const WinSalFrame* pFrame,
                                       int& rX, int& rY, int& rDX, int& rDY )
{
    // set window to screen size
    int nFrameX;
    int nFrameY;
    int nCaptionY;
    int nScreenX = 0;
    int nScreenY = 0;
    int nScreenDX = 0;
    int nScreenDY = 0;

    if ( pFrame->mbSizeBorder )
    {
        nFrameX = GetSystemMetrics( SM_CXSIZEFRAME );
        nFrameY = GetSystemMetrics( SM_CYSIZEFRAME );
    }
    else if ( pFrame->mbFixBorder )
    {
        nFrameX = GetSystemMetrics( SM_CXFIXEDFRAME );
        nFrameY = GetSystemMetrics( SM_CYFIXEDFRAME );
    }
    else if ( pFrame->mbBorder )
    {
        nFrameX = GetSystemMetrics( SM_CXBORDER );
        nFrameY = GetSystemMetrics( SM_CYBORDER );
    }
    else
    {
        nFrameX = 0;
        nFrameY = 0;
    }
    if ( pFrame->mbCaption )
        nCaptionY = GetSystemMetrics( SM_CYCAPTION );
    else
        nCaptionY = 0;

    try
    {
        AbsoluteScreenPixelRectangle aRect;
        sal_Int32 nMonitors = Application::GetScreenCount();
        if( (pFrame->mnDisplay >= 0) && (pFrame->mnDisplay < nMonitors) )
        {
            aRect = Application::GetScreenPosSizePixel(pFrame->mnDisplay);
        }
        else
        {
            for (sal_Int32 i = 0; i < nMonitors; i++)
                aRect.Union(Application::GetScreenPosSizePixel(i));
        }
        nScreenX = aRect.Left();
        nScreenY = aRect.Top();
        nScreenDX = aRect.GetWidth() + 1;
        nScreenDY = aRect.GetHeight() + 1;
    }
    catch( Exception& )
    {
    }

    if( !nScreenDX || !nScreenDY )
    {
        nScreenDX   = GetSystemMetrics( SM_CXSCREEN );
        nScreenDY   = GetSystemMetrics( SM_CYSCREEN );
    }

    rX  = nScreenX -nFrameX;
    rY  = nScreenY -(nFrameY+nCaptionY);
    rDX = nScreenDX+(nFrameX*2);
    rDY = nScreenDY+(nFrameY*2)+nCaptionY;
}

static void ImplSalFrameFullScreenPos( WinSalFrame* pFrame, bool bAlways = false )
{
    if ( bAlways || !IsIconic( pFrame->mhWnd ) )
    {
        // set window to screen size
        int nX;
        int nY;
        int nWidth;
        int nHeight;
        ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight );
        SetWindowPos( pFrame->mhWnd, nullptr,
                      nX, nY, nWidth, nHeight,
                      SWP_NOZORDER | SWP_NOACTIVATE );
    }
}

namespace {

void SetForegroundWindow_Impl(HWND hwnd)
{
    if (!Application::IsHeadlessModeEnabled())
        SetForegroundWindow(hwnd);
}

}

WinSalFrame::WinSalFrame()
{
    SalData* pSalData = GetSalData();

    mhWnd               = nullptr;
    mhCursor            = LoadCursor( nullptr, IDC_ARROW );
    mhDefIMEContext     = nullptr;
    mpLocalGraphics     = nullptr;
    mpThreadGraphics    = nullptr;
    m_eState = vcl::WindowState::Normal;
    mnShowState         = SW_SHOWNORMAL;
    mnMinWidth          = 0;
    mnMinHeight         = 0;
    mnMaxWidth          = SHRT_MAX;
    mnMaxHeight         = SHRT_MAX;
    mnInputLang         = 0;
    mnInputCodePage     = 0;
    mbGraphicsAcquired  = false;
    mbCaption           = false;
    mbBorder            = false;
    mbFixBorder         = false;
    mbSizeBorder        = false;
    mbFullScreenCaption = false;
    mbPresentation      = false;
    mbInShow            = false;
    mbRestoreMaximize   = false;
    mbInMoveMsg         = false;
    mbInSizeMsg         = false;
    mbFullScreenToolWin = false;
    mbDefPos            = true;
    mbOverwriteState    = true;
    mbIME               = false;
    mbHandleIME         = false;
    mbSpezIME           = false;
    mbAtCursorIME       = false;
    mbCandidateMode     = false;
    mbFloatWin          = false;
    mbNoIcon            = false;
    mSelectedhMenu      = nullptr;
    mLastActivatedhMenu = nullptr;
    mpClipRgnData       = nullptr;
    mbFirstClipRect     = true;
    mpNextClipRect      = nullptr;
    mnDisplay           = 0;
    mbPropertiesStored  = false;
    m_pTaskbarList3     = nullptr;
    maFirstPanGesturePt = POINT(0,0);

    // get data, when making 1st frame
    if ( !pSalData->mpFirstFrame )
    {
        if ( !aSalShlData.mnWheelScrollLines )
            aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines();
        if ( !aSalShlData.mnWheelScrollChars )
            aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars();
    }

    // insert frame in framelist
    mpNextFrame = pSalData->mpFirstFrame;
    pSalData->mpFirstFrame = this;
}

void WinSalFrame::updateScreenNumber()
{
    if( mnDisplay == -1 ) // spans all monitors
        return;
    WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
    if( pSys )
    {
        const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
            pSys->getMonitors();
        AbsoluteScreenPixelPoint aPoint(maGeometry.pos());
        size_t nMon = rMonitors.size();
        for( size_t i = 0; i < nMon; i++ )
        {
            if( rMonitors[i].m_aArea.Contains( aPoint ) )
            {
                mnDisplay = static_cast<sal_Int32>(i);
                maGeometry.setScreen(static_cast<unsigned int>(i));
            }
        }
    }
}

WinSalFrame::~WinSalFrame()
{
    SalData* pSalData = GetSalData();

    if( mpClipRgnData )
        delete [] reinterpret_cast<BYTE*>(mpClipRgnData);

    // remove frame from framelist
    WinSalFrame** ppFrame = &pSalData->mpFirstFrame;
    for(; (*ppFrame != this) && *ppFrame; ppFrame = &(*ppFrame)->mpNextFrame );
    if( *ppFrame )
        *ppFrame = mpNextFrame;
    mpNextFrame = nullptr;

    // destroy the thread SalGraphics
    if ( mpThreadGraphics )
    {
        HDC hDC = mpThreadGraphics->getHDC();
        if (hDC)
        {
            mpThreadGraphics->setHDC(nullptr);
            pSalData->mpInstance->SendComWndMessage(SAL_MSG_RELEASEDC,
                reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) );
        }
        delete mpThreadGraphics;
        mpThreadGraphics = nullptr;
    }

    // destroy the local SalGraphics
    if ( mpLocalGraphics )
    {
        HDC hDC = mpLocalGraphics->getHDC();
        mpLocalGraphics->setHDC(nullptr);
        ReleaseDC(mhWnd, hDC);
        delete mpLocalGraphics;
        mpLocalGraphics = nullptr;
    }

    if ( m_pTaskbarList3 )
    {
        m_pTaskbarList3->Release();
    }

    if ( mhWnd )
    {
        // reset mouse leave data
        if ( pSalData->mhWantLeaveMsg == mhWnd )
        {
            pSalData->mhWantLeaveMsg = nullptr;
        }

        // remove windows properties
        if ( mbPropertiesStored )
            SetApplicationID( OUString() );

        // destroy system frame
        if ( !DestroyWindow( mhWnd ) )
            SetWindowPtr( mhWnd, nullptr );

        mhWnd = nullptr;
    }
}

SalGraphics* WinSalFrame::AcquireGraphics()
{
    if ( mbGraphicsAcquired || !mhWnd )
        return nullptr;

    SalData* pSalData = GetSalData();

    // Other threads get an own DC, because Windows modify in the
    // other case our DC (changing clip region), when they send a
    // WM_ERASEBACKGROUND message
    if ( !pSalData->mpInstance->IsMainThread() )
    {
        HDC hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>(pSalData->mpInstance->SendComWndMessage(
                                    SAL_MSG_GETCACHEDDC, reinterpret_cast<WPARAM>(mhWnd), 0 )));
        if ( !hDC )
            return nullptr;

        if ( !mpThreadGraphics )
            mpThreadGraphics = new WinSalGraphics(WinSalGraphics::WINDOW, true, mhWnd, this);

        assert(!mpThreadGraphics->getHDC() && "this is supposed to be zeroed when ReleaseGraphics is called");
        mpThreadGraphics->setHDC( hDC );

        mbGraphicsAcquired = true;
        return mpThreadGraphics;
    }
    else
    {
        if ( !mpLocalGraphics )
        {
            HDC hDC = GetDC( mhWnd );
            if ( !hDC )
                return nullptr;
            mpLocalGraphics = new WinSalGraphics(WinSalGraphics::WINDOW, true, mhWnd, this);
            mpLocalGraphics->setHDC( hDC );
        }
        mbGraphicsAcquired = true;
        return mpLocalGraphics;
    }
}

void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
{
    if ( mpThreadGraphics == pGraphics )
    {
        SalData* pSalData = GetSalData();
        HDC hDC = mpThreadGraphics->getHDC();
        assert(hDC);
        mpThreadGraphics->setHDC(nullptr);
        pSalData->mpInstance->SendComWndMessage(SAL_MSG_RELEASEDC,
            reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) );
    }
    mbGraphicsAcquired = false;
}

bool WinSalFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData)
{
    bool const ret = PostMessageW(mhWnd, SAL_MSG_USEREVENT, 0, reinterpret_cast<LPARAM>(pData.get()));
    SAL_WARN_IF(!ret, "vcl""ERROR: PostMessage() failed!");
    if (ret)
        pData.release();
    return ret;
}

void WinSalFrame::SetTitle( const OUString& rTitle )
{
    static_assert( sizeof( WCHAR ) == sizeof( sal_Unicode ), "must be the same size" );

    WinSalInstance::SendWndMessage(mhWnd, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(rTitle.getStr()));
}

void WinSalFrame::SetIcon( sal_uInt16 nIcon )
{
    // If we have a window without an Icon (for example a dialog), ignore this call
    if ( mbNoIcon )
        return;

    // 0 means default (class) icon
    HICON hIcon = nullptr, hSmIcon = nullptr;
    if ( !nIcon )
        nIcon = 1;

    ImplLoadSalIcon( nIcon, hIcon, hSmIcon );

    SAL_WARN_IF( !hIcon , "vcl",   "WinSalFrame::SetIcon(): Could not load large icon !" );
    SAL_WARN_IF( !hSmIcon , "vcl""WinSalFrame::SetIcon(): Could not load small icon !" );

    WinSalInstance::SendWndMessage(mhWnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hIcon));
    WinSalInstance::SendWndMessage(mhWnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(hSmIcon));
}

void WinSalFrame::SetMenu( SalMenu* pSalMenu )
{
    WinSalMenu* pWMenu = static_cast<WinSalMenu*>(pSalMenu);
    if( pSalMenu && pWMenu->mbMenuBar )
        ::SetMenu( mhWnd, pWMenu->mhMenu );
}

static HWND ImplGetParentHwnd( HWND hWnd )
{
    WinSalFrame* pFrame = GetWindowPtr( hWnd );
    if( !pFrame || !pFrame->GetWindow())
        return ::GetParent( hWnd );
    vcl::Window *pRealParent = pFrame->GetWindow()->ImplGetWindowImpl()->mpRealParent;
    if( pRealParent )
        return static_cast<WinSalFrame*>(pRealParent->ImplGetWindowImpl()->mpFrame)->mhWnd;
    else
        return ::GetParent( hWnd );

}

SalFrame* WinSalFrame::GetParent() const
{
    return GetWindowPtr( ImplGetParentHwnd( mhWnd ) );
}

static void ImplSalShow( HWND hWnd, bool bVisible, bool bNoActivate )
{
    WinSalFrame* pFrame = GetWindowPtr( hWnd );
    if ( !pFrame )
        return;

    if ( bVisible )
    {
        pFrame->mbDefPos = false;
        pFrame->mbOverwriteState = true;
        pFrame->mbInShow = true;

        // #i4715, save position
        RECT aRectPreMatrox, aRectPostMatrox;
        GetWindowRect( hWnd, &aRectPreMatrox );

        vcl::DeletionListener aDogTag( pFrame );
        if( bNoActivate )
            ShowWindow( hWnd, SW_SHOWNOACTIVATE );
        else
            ShowWindow( hWnd, pFrame->mnShowState );
        if( aDogTag.isDeleted() )
            return;

        if (pFrame->mbFloatWin && !(pFrame->mnStyle & SalFrameStyleFlags::NOSHADOW))
        {
            // erase the window immediately to improve XP shadow effect
            // otherwise the shadow may appears long time before the rest of the window
            // especially when accessibility is on
            HDC dc = GetDC( hWnd );
            RECT aRect;
            GetClientRect( hWnd, &aRect );
            FillRect( dc, &aRect, reinterpret_cast<HBRUSH>(COLOR_MENU+1) ); // choose the menucolor, because its mostly noticeable for menus
            ReleaseDC( hWnd, dc );
        }

        // #i4715, matrox centerpopup might have changed our position
        // reposition popups without caption (menus, dropdowns, tooltips)
        GetWindowRect( hWnd, &aRectPostMatrox );
        if( (GetWindowStyle( hWnd ) & WS_POPUP) &&
            !pFrame->mbCaption &&
            (aRectPreMatrox.left != aRectPostMatrox.left || aRectPreMatrox.top != aRectPostMatrox.top) )
            SetWindowPos( hWnd, nullptr, aRectPreMatrox.left, aRectPreMatrox.top, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE  );

        if( aDogTag.isDeleted() )
            return;
        vcl::Window *pClientWin = pFrame->GetWindow()->ImplGetClientWindow();
        if ( pFrame->mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
            pFrame->mnShowState = SW_SHOWNOACTIVATE;
        else
            pFrame->mnShowState = SW_SHOW;
        // hide toolbar for W98
        if ( pFrame->mbPresentation )
        {
            HWND hWndParent = ::GetParent( hWnd );
            if ( hWndParent )
                SetForegroundWindow_Impl( hWndParent );
            SetForegroundWindow_Impl( hWnd );
        }

        pFrame->mbInShow = false;
        pFrame->updateScreenNumber();

        // Direct Paint only, if we get the SolarMutex
        if ( ImplSalYieldMutexTryToAcquire() )
        {
            UpdateWindow( hWnd );
            ImplSalYieldMutexRelease();
        }
    }
    else
    {
        ShowWindow( hWnd, SW_HIDE );
    }
}

void WinSalFrame::SetExtendedFrameStyle( SalExtStyle )
{
}

void WinSalFrame::Show( bool bVisible, bool bNoActivate )
{
    // Post this Message to the window, because this only works
    // in the thread of the window, which has create this window.
    // We post this message to avoid deadlocks
    if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
    {
        bool const ret = PostMessageW(mhWnd, SAL_MSG_SHOW, WPARAM(bVisible), LPARAM(bNoActivate));
        SAL_WARN_IF(!ret, "vcl""ERROR: PostMessage() failed!");
    }
    else
        ImplSalShow( mhWnd, bVisible, bNoActivate );
}

void WinSalFrame::SetMinClientSize( tools::Long nWidth, tools::Long nHeight )
{
    mnMinWidth  = nWidth;
    mnMinHeight = nHeight;
}

void WinSalFrame::SetMaxClientSize( tools::Long nWidth, tools::Long nHeight )
{
    mnMaxWidth  = nWidth;
    mnMaxHeight = nHeight;
}

void WinSalFrame::SetPosSize( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
                                                   sal_uInt16 nFlags )
{
    bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0;
    if ( !bVisible )
    {
        vcl::Window *pClientWin = GetWindow()->ImplGetClientWindow();
        if ( mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) )
                mnShowState = SW_SHOWNOACTIVATE;
        else
                mnShowState = SW_SHOWNORMAL;
    }
    else
    {
        if ( IsIconic( mhWnd ) || IsZoomed( mhWnd ) )
                ShowWindow( mhWnd, SW_RESTORE );
    }

    SalEvent nEvent = SalEvent::NONE;
    UINT    nPosSize = 0;
    RECT    aClientRect, aWindowRect;
    GetClientRect( mhWnd, &aClientRect );   // x,y always 0,0, but width and height without border
    GetWindowRect( mhWnd, &aWindowRect );   // x,y in screen coordinates, width and height with border

    if ( !(nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) )
        nPosSize |= SWP_NOMOVE;
    else
    {
        //SAL_WARN_IF( !nX || !nY, "vcl", " Windowposition of (0,0) requested!" );
        nEvent = SalEvent::Move;
    }
    if ( !(nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) )
        nPosSize |= SWP_NOSIZE;
    else
        nEvent = (nEvent == SalEvent::Move) ? SalEvent::MoveResize : SalEvent::Resize;

    if ( !(nFlags & SAL_FRAME_POSSIZE_X) )
        nX = aWindowRect.left;
    if ( !(nFlags & SAL_FRAME_POSSIZE_Y) )
        nY = aWindowRect.top;
    if ( !(nFlags & SAL_FRAME_POSSIZE_WIDTH) )
        nWidth = aClientRect.right-aClientRect.left;
    if ( !(nFlags & SAL_FRAME_POSSIZE_HEIGHT) )
        nHeight = aClientRect.bottom-aClientRect.top;

    // Calculate window size including the border
    RECT    aWinRect;
    aWinRect.left   = 0;
    aWinRect.right  = static_cast<int>(nWidth)-1;
    aWinRect.top    = 0;
    aWinRect.bottom = static_cast<int>(nHeight)-1;
    AdjustWindowRectEx( &aWinRect, GetWindowStyle( mhWnd ),
                        FALSE,     GetWindowExStyle( mhWnd ) );
    nWidth  = aWinRect.right - aWinRect.left + 1;
    nHeight = aWinRect.bottom - aWinRect.top + 1;

    HWND hWndParent = ImplGetParentHwnd(mhWnd);
    // For dialogs (WS_POPUP && WS_DLGFRAME), we need to find the "real" parent,
    // in case multiple dialogs are stacked on each other
    // (we don't want to position the second dialog relative to the first one, but relative to the main window)
    if ( (GetWindowStyle( mhWnd ) & WS_POPUP) &&  (GetWindowStyle( mhWnd ) & WS_DLGFRAME) ) // mhWnd is a dialog
    {
        while ( hWndParent && (GetWindowStyle( hWndParent ) & WS_POPUP) &&  (GetWindowStyle( hWndParent ) & WS_DLGFRAME) )
        {
            hWndParent = ::ImplGetParentHwnd( hWndParent );
        }
    }

    if ( !(nPosSize & SWP_NOMOVE) && hWndParent )
    {
            RECT aParentRect;
            GetClientRect( hWndParent, &aParentRect );
            if( AllSettings::GetLayoutRTL() )
                nX = (aParentRect.right - aParentRect.left) - nWidth-1 - nX;

            //#110386#, do not transform coordinates for system child windows
            if( !(GetWindowStyle( mhWnd ) & WS_CHILD) )
            {
                POINT aPt;
                aPt.x = nX;
                aPt.y = nY;

                WinSalFrame* pParentFrame = GetWindowPtr( hWndParent );
                if ( pParentFrame && pParentFrame->mnShowState == SW_SHOWMAXIMIZED )
                {
                    // #i42485#: parent will be shown maximized in which case
                    // a ClientToScreen uses the wrong coordinates (i.e. those from the restore pos)
                    // so use the (already updated) frame geometry for the transformation
                    aPt.x +=  pParentFrame->maGeometry.x();
                    aPt.y +=  pParentFrame->maGeometry.y();
                }
                else
                    ClientToScreen( hWndParent, &aPt );

                nX = aPt.x;
                nY = aPt.y;

                // the position is set
                mbDefPos = false;
            }
    }

    // #i3338# to be conformant to UNIX we must position the client window, ie without the decoration
    // #i43250# if the position was read from the system (GetWindowRect(), see above), it must not be modified
    if ( nFlags & SAL_FRAME_POSSIZE_X )
        nX += aWinRect.left;
    if ( nFlags & SAL_FRAME_POSSIZE_Y )
        nY += aWinRect.top;

    int     nScreenX;
    int     nScreenY;
    int     nScreenWidth;
    int     nScreenHeight;

    RECT aRect;
    ImplSalGetWorkArea( mhWnd, &aRect, nullptr );
    nScreenX        = aRect.left;
    nScreenY        = aRect.top;
    nScreenWidth    = aRect.right-aRect.left;
    nScreenHeight   = aRect.bottom-aRect.top;

    if ( mbDefPos && (nPosSize & SWP_NOMOVE)) // we got no positioning request, so choose default position
    {
        // center window

        HWND hWndParent2 = ::GetParent( mhWnd );
        // Search for TopLevel Frame
        while ( hWndParent2 && (GetWindowStyle( hWndParent2 ) & WS_CHILD) )
            hWndParent2 = ::GetParent( hWndParent2 );
        // if the Window has a Parent, then center the window to
        // the parent, in the other case to the screen
        if ( hWndParent2 && !IsIconic( hWndParent2 ) &&
             (GetWindowStyle( hWndParent2 ) & WS_VISIBLE) )
        {
            RECT aParentRect;
            GetWindowRect( hWndParent2, &aParentRect );
            int nParentWidth    = aParentRect.right-aParentRect.left;
            int nParentHeight   = aParentRect.bottom-aParentRect.top;

            // We don't center, when Parent is smaller than our window
            if ( (nParentWidth-GetSystemMetrics( SM_CXFIXEDFRAME ) <= nWidth) &&
                 (nParentHeight-GetSystemMetrics( SM_CYFIXEDFRAME ) <= nHeight) )
            {
                int nOff = GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
                nX = aParentRect.left+nOff;
                nY = aParentRect.top+nOff;
            }
            else
            {
                nX = (nParentWidth-nWidth)/2 + aParentRect.left;
                nY = (nParentHeight-nHeight)/2 + aParentRect.top;
            }
        }
        else
        {
            POINT pt;
            GetCursorPos( &pt );
            RECT aRect2;
            aRect2.left = pt.x;
            aRect2.top = pt.y;
            aRect2.right = pt.x+2;
            aRect2.bottom = pt.y+2;

            // dualmonitor support:
            // Get screensize of the monitor with the mouse pointer
            ImplSalGetWorkArea( mhWnd, &aRect2, &aRect2 );

            nX = ((aRect2.right-aRect2.left)-nWidth)/2 + aRect2.left;
            nY = ((aRect2.bottom-aRect2.top)-nHeight)/2 + aRect2.top;
        }

        //if ( bVisible )
        //    mbDefPos = FALSE;

        mbDefPos = false;   // center only once
        nPosSize &= ~SWP_NOMOVE;        // activate positioning
        nEvent = SalEvent::MoveResize;
    }

    // Adjust Window in the screen
    bool bCheckOffScreen = true;

    // but don't do this for floaters or ownerdraw windows that are currently moved interactively
    if( (mnStyle & SalFrameStyleFlags::FLOAT) && !(mnStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) )
        bCheckOffScreen = false;

    if( mnStyle & SalFrameStyleFlags::OWNERDRAWDECORATION )
    {
        // may be the window is currently being moved (mouse is captured), then no check is required
        if( mhWnd == ::GetCapture() )
            bCheckOffScreen = false;
        else
            bCheckOffScreen = true;
    }

    if( bCheckOffScreen )
    {
        if ( nX+nWidth > nScreenX+nScreenWidth )
            nX = (nScreenX+nScreenWidth) - nWidth;
        if ( nY+nHeight > nScreenY+nScreenHeight )
            nY = (nScreenY+nScreenHeight) - nHeight;
        if ( nX < nScreenX )
            nX = nScreenX;
        if ( nY < nScreenY )
            nY = nScreenY;
    }

    UINT nPosFlags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | nPosSize;
    // bring floating windows always to top
    if( !(mnStyle & SalFrameStyleFlags::FLOAT) )
        nPosFlags |= SWP_NOZORDER; // do not change z-order

    SetWindowPos( mhWnd, HWND_TOP, nX, nY, static_cast<int>(nWidth), static_cast<int>(nHeight), nPosFlags  );

    UpdateFrameGeometry();

    // Notification -- really ???
    if( nEvent != SalEvent::NONE )
        CallCallback( nEvent, nullptr );
}

void WinSalFrame::ImplSetParentFrame( HWND hNewParentWnd, bool bAsChild )
{
    // save hwnd, will be overwritten in WM_CREATE during createwindow
    HWND hWndOld = mhWnd;
    HWND hWndOldParent = ::GetParent( hWndOld );
    SalData* pSalData = GetSalData();

    if( hNewParentWnd == hWndOldParent )
        return;

    ::std::vector< WinSalFrame* > children;
    ::std::vector< WinSalObject* > systemChildren;

    // search child windows
    WinSalFrame *pFrame = pSalData->mpFirstFrame;
    while( pFrame )
    {
        HWND hWndParent = ::GetParent( pFrame->mhWnd );
        if( mhWnd == hWndParent )
            children.push_back( pFrame );
        pFrame = pFrame->mpNextFrame;
    }

    // search system child windows (plugins etc.)
    WinSalObject *pObject = pSalData->mpFirstObject;
    while( pObject )
    {
        HWND hWndParent = ::GetParent( pObject->mhWnd );
        if( mhWnd == hWndParent )
            systemChildren.push_back( pObject );
        pObject = pObject->mpNextObject;
    }

    // to recreate the DCs, if they were destroyed
    bool bHadLocalGraphics = false, bHadThreadGraphics = false;

    HFONT   hFont   = nullptr;
    HPEN    hPen    = nullptr;
    HBRUSH  hBrush  = nullptr;

    // release the thread DC
    if ( mpThreadGraphics )
    {
        // save current gdi objects before hdc is gone
        HDC hDC = mpThreadGraphics->getHDC();
        if (hDC)
        {
            hFont  = static_cast<HFONT>(GetCurrentObject( hDC, OBJ_FONT ));
            hPen   = static_cast<HPEN>(GetCurrentObject( hDC, OBJ_PEN ));
            hBrush = static_cast<HBRUSH>(GetCurrentObject( hDC, OBJ_BRUSH ));

            mpThreadGraphics->setHDC(nullptr);
            pSalData->mpInstance->SendComWndMessage(SAL_MSG_RELEASEDC,
                reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) );

            bHadThreadGraphics = true;
        }
    }

    // release the local DC
    if ( mpLocalGraphics )
    {
        bHadLocalGraphics = true;
        HDC hDC = mpLocalGraphics->getHDC();
        mpLocalGraphics->setHDC(nullptr);
        ReleaseDC(mhWnd, hDC);
    }

    // create a new hwnd with the same styles
    HWND hWndParent = hNewParentWnd;
    // forward to main thread
    HWND hWnd = reinterpret_cast<HWND>(static_cast<sal_IntPtr>(pSalData->mpInstance->SendComWndMessage(
                                        bAsChild ? SAL_MSG_RECREATECHILDHWND : SAL_MSG_RECREATEHWND,
                                        reinterpret_cast<WPARAM>(hWndParent), reinterpret_cast<LPARAM>(mhWnd) )));

    // succeeded ?
    SAL_WARN_IF( !IsWindow( hWnd ), "vcl""WinSalFrame::SetParent not successful");

    // re-create thread DC
    if( bHadThreadGraphics )
    {
        mpThreadGraphics->setHWND( hWnd );
        HDC hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>(
                    pSalData->mpInstance->SendComWndMessage(
                        SAL_MSG_GETCACHEDDC, reinterpret_cast<WPARAM>(hWnd), 0 )));
        if ( hDC )
        {
            mpThreadGraphics->setHDC( hDC );
            // re-select saved gdi objects
            if( hFont )
                SelectObject( hDC, hFont );
            if( hPen )
                SelectObject( hDC, hPen );
            if( hBrush )
                SelectObject( hDC, hBrush );
        }
    }

    // re-create local DC
    if( bHadLocalGraphics )
    {
        mpLocalGraphics->setHWND( hWnd );
        HDC hDC = GetDC( hWnd );
        if (hDC)
            mpLocalGraphics->setHDC( hDC );
    }

    // TODO: add SetParent() call for SalObjects
    SAL_WARN_IF( !systemChildren.empty(), "vcl""WinSalFrame::SetParent() parent of living system child window will be destroyed!");

    // reparent children before old parent is destroyed
    for (auto & child : children)
        child->ImplSetParentFrame( hWnd, false );

    children.clear();
    systemChildren.clear();

    // Now destroy original HWND in the thread where it was created.
    pSalData->mpInstance->SendComWndMessage(
                     SAL_MSG_DESTROYHWND, WPARAM(0), reinterpret_cast<LPARAM>(hWndOld));
}

void WinSalFrame::SetParent( SalFrame* pNewParent )
{
    WinSalFrame::mbInReparent = true;
    ImplSetParentFrame( static_cast<WinSalFrame*>(pNewParent)->mhWnd, false );
    WinSalFrame::mbInReparent = false;
}

void WinSalFrame::SetPluginParent( SystemParentData* pNewParent )
{
    if ( pNewParent->hWnd == nullptr )
    {
        pNewParent->hWnd = GetDesktopWindow();
    }

    WinSalFrame::mbInReparent = true;
    ImplSetParentFrame( pNewParent->hWnd, true );
    WinSalFrame::mbInReparent = false;
}

void WinSalFrame::GetWorkArea( AbsoluteScreenPixelRectangle &rRect )
{
    RECT aRect;

    // pass cursor's position to ImplSalGetWorkArea to determine work area on
    // multi monitor setups correctly.
    POINT aPoint;
    GetCursorPos(&aPoint);
    RECT aRect2{ aPoint.x, aPoint.y, aPoint.x + 2, aPoint.y + 2 };

    ImplSalGetWorkArea( mhWnd, &aRect, &aRect2 );
    rRect.SetLeft( aRect.left );
    rRect.SetRight( aRect.right-1 );
    rRect.SetTop( aRect.top );
    rRect.SetBottom( aRect.bottom-1 );
}

void WinSalFrame::GetClientSize( tools::Long& rWidth, tools::Long& rHeight )
{
    rWidth  = maGeometry.width();
    rHeight = maGeometry.height();
}

void WinSalFrame::SetWindowState(const vcl::WindowData* pState)
{
    // Check if the window fits into the screen, in case the screen
    // resolution changed
    int     nX;
    int     nY;
    int     nWidth;
    int     nHeight;
    int     nScreenX;
    int     nScreenY;
    int     nScreenWidth;
    int     nScreenHeight;

    RECT aRect;
    ImplSalGetWorkArea( mhWnd, &aRect, nullptr );
    // #102500# allow some overlap, the window could have been made a little larger than the physical screen
    nScreenX        = aRect.left-10;
    nScreenY        = aRect.top-10;
    nScreenWidth    = aRect.right-aRect.left+20;
    nScreenHeight   = aRect.bottom-aRect.top+20;

    UINT    nPosSize    = 0;
    RECT    aWinRect;
    GetWindowRect( mhWnd, &aWinRect );

    // to be consistent with Unix, the frame state is without(!) decoration
    // ->add the decoration
    RECT aRect2 = aWinRect;
    AdjustWindowRectEx( &aRect2, GetWindowStyle( mhWnd ),
                    FALSE,     GetWindowExStyle( mhWnd ) );
    tools::Long nTopDeco = abs( aWinRect.top - aRect2.top );
    tools::Long nLeftDeco = abs( aWinRect.left - aRect2.left );
    tools::Long nBottomDeco = abs( aWinRect.bottom - aRect2.bottom );
    tools::Long nRightDeco = abs( aWinRect.right - aRect2.right );

    // adjust window position/size to fit the screen
    if ( !(pState->mask() & vcl::WindowDataMask::Pos) )
        nPosSize |= SWP_NOMOVE;
    if ( !(pState->mask() & vcl::WindowDataMask::Size) )
        nPosSize |= SWP_NOSIZE;
    if ( pState->mask() & vcl::WindowDataMask::X )
        nX = static_cast<int>(pState->x()) - nLeftDeco;
    else
        nX = aWinRect.left;
    if ( pState->mask() & vcl::WindowDataMask::Y )
        nY = static_cast<int>(pState->y()) - nTopDeco;
    else
        nY = aWinRect.top;
    if ( pState->mask() & vcl::WindowDataMask::Width )
        nWidth = static_cast<int>(pState->width()) + nLeftDeco + nRightDeco;
    else
        nWidth = aWinRect.right-aWinRect.left;
    if ( pState->mask() & vcl::WindowDataMask::Height )
        nHeight = static_cast<int>(pState->height()) + nTopDeco + nBottomDeco;
    else
        nHeight = aWinRect.bottom-aWinRect.top;

    // Adjust Window in the screen:
    // if it does not fit into the screen do nothing, ie default pos/size will be used
    // if there is an overlap with the screen border move the window while keeping its size

    if( nWidth > nScreenWidth || nHeight > nScreenHeight )
        nPosSize |= (SWP_NOMOVE | SWP_NOSIZE);

    if ( nX+nWidth > nScreenX+nScreenWidth )
        nX = (nScreenX+nScreenWidth) - nWidth;
    if ( nY+nHeight > nScreenY+nScreenHeight )
        nY = (nScreenY+nScreenHeight) - nHeight;
    if ( nX < nScreenX )
        nX = nScreenX;
    if ( nY < nScreenY )
        nY = nScreenY;

    // set Restore-Position
    WINDOWPLACEMENT aPlacement;
    aPlacement.length = sizeof( aPlacement );
    GetWindowPlacement( mhWnd, &aPlacement );

    // set State
    const bool bIsMinimized = IsIconic(mhWnd);
    const bool bIsMaximized = IsZoomed(mhWnd);
    const bool bVisible = (GetWindowStyle(mhWnd) & WS_VISIBLE);
    bool bUpdateHiddenFramePos = false;
    if ( !bVisible )
    {
        aPlacement.showCmd = SW_HIDE;

        if (mbOverwriteState && (pState->mask() & vcl::WindowDataMask::State))
        {
            if (pState->state() & vcl::WindowState::Minimized)
                mnShowState = SW_SHOWMINIMIZED;
            else if (pState->state() & vcl::WindowState::Maximized)
            {
                mnShowState = SW_SHOWMAXIMIZED;
                bUpdateHiddenFramePos = true;
            }
            else if (pState->state() & vcl::WindowState::Normal)
                mnShowState = SW_SHOWNORMAL;
        }
    }
    else
    {
        if ( pState->mask() & vcl::WindowDataMask::State )
        {
            if ( pState->state() & vcl::WindowState::Minimized )
            {
                if ( pState->state() & vcl::WindowState::Maximized )
                    aPlacement.flags |= WPF_RESTORETOMAXIMIZED;
                aPlacement.showCmd = SW_SHOWMINIMIZED;
            }
            else if ( pState->state() & vcl::WindowState::Maximized )
                aPlacement.showCmd = SW_SHOWMAXIMIZED;
            else if ( pState->state() & vcl::WindowState::Normal )
                aPlacement.showCmd = SW_RESTORE;
        }
    }

    // if a window is neither minimized nor maximized or need not be
    // positioned visibly (that is in visible state), do not use
    // SetWindowPlacement since it calculates including the TaskBar
    if (!bIsMinimized && !bIsMaximized && (!bVisible || (aPlacement.showCmd == SW_RESTORE)))
    {
        if( bUpdateHiddenFramePos )
        {
            RECT aStateRect;
            aStateRect.left   = nX;
            aStateRect.top    = nY;
            aStateRect.right  = nX+nWidth;
            aStateRect.bottom = nY+nHeight;
            // #96084 set a useful internal window size because
            // the window will not be maximized (and the size updated) before show()
            SetMaximizedFrameGeometry(mhWnd, &aStateRect);
            SetWindowPos( mhWnd, nullptr,
                          maGeometry.x(), maGeometry.y(), maGeometry.width(), maGeometry.height(),
                          SWP_NOZORDER | SWP_NOACTIVATE | nPosSize );
        }
        else
            SetWindowPos( mhWnd, nullptr,
                      nX, nY, nWidth, nHeight,
                      SWP_NOZORDER | SWP_NOACTIVATE | nPosSize );
    }
    else
    {
        if( !(nPosSize & (SWP_NOMOVE|SWP_NOSIZE)) )
        {
            aPlacement.rcNormalPosition.left    = nX-nScreenX;
            aPlacement.rcNormalPosition.top     = nY-nScreenY;
            aPlacement.rcNormalPosition.right   = nX+nWidth-nScreenX;
            aPlacement.rcNormalPosition.bottom  = nY+nHeight-nScreenY;
        }
        SetWindowPlacement( mhWnd, &aPlacement );
    }

    if( !(nPosSize & SWP_NOMOVE) )
        mbDefPos = false// window was positioned
}

bool WinSalFrame::GetWindowState(vcl::WindowData* pState)
{
    pState->setPosSize(maGeometry.posSize());
    pState->setState(m_eState);
    pState->setMask(vcl::WindowDataMask::PosSizeState);
    return true;
}

void WinSalFrame::SetScreenNumber( unsigned int nNewScreen )
{
    WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem());
    if( pSys )
    {
        const std::vector<WinSalSystem::DisplayMonitor>& rMonitors =
            pSys->getMonitors();
        size_t nMon = rMonitors.size();
        if( nNewScreen < nMon )
        {
            AbsoluteScreenPixelPoint aOldMonPos, aNewMonPos( rMonitors[nNewScreen].m_aArea.TopLeft() );
            AbsoluteScreenPixelPoint aCurPos(maGeometry.pos());
            for( size_t i = 0; i < nMon; i++ )
            {
                if( rMonitors[i].m_aArea.Contains( aCurPos ) )
                {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=87 H=97 G=91

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Entwurf

Ziele

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Ergonomie der
Schnittstellen

Diese beiden folgenden Angebotsgruppen bietet das Unternehmen

Angebot

Hier finden Sie eine Liste der Produkte des Unternehmens